diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index b512fd5c46c..94d366e0df4 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -181,6 +181,8 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d *Packetbeat* +- Add automated OEM Npcap installation handling. {pull}29112[29112] + *Functionbeat* diff --git a/NOTICE.txt b/NOTICE.txt index a8494a37f8c..f248155d367 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -16728,6 +16728,43 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +Dependency : golang.org/x/mod +Version: v0.5.1 +Licence type (autodetected): BSD-3-Clause +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/golang.org/x/mod@v0.5.1/LICENSE: + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + -------------------------------------------------------------------------------- Dependency : golang.org/x/net Version: v0.0.0-20211020060615-d418f374d309 @@ -34313,43 +34350,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------------------------------- -Dependency : golang.org/x/mod -Version: v0.5.1 -Licence type (autodetected): BSD-3-Clause --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/golang.org/x/mod@v0.5.1/LICENSE: - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------------------- Dependency : golang.org/x/term Version: v0.0.0-20210220032956-6a3ed077a48d @@ -36969,4 +36969,3 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/dev-tools/mage/config.go b/dev-tools/mage/config.go index da54123e916..b80bd9a197b 100644 --- a/dev-tools/mage/config.go +++ b/dev-tools/mage/config.go @@ -149,6 +149,7 @@ func makeConfigTemplate(destination string, mode os.FileMode, confParams ConfigF params := map[string]interface{}{ "GOOS": EnvOr("DEV_OS", "linux"), "GOARCH": EnvOr("DEV_ARCH", "amd64"), + "BeatLicense": BeatLicense, "Reference": false, "Docker": false, "ExcludeConsole": false, diff --git a/dev-tools/mage/crossbuild.go b/dev-tools/mage/crossbuild.go index 9f56fd125c3..e434be6101f 100644 --- a/dev-tools/mage/crossbuild.go +++ b/dev-tools/mage/crossbuild.go @@ -183,7 +183,7 @@ func CrossBuild(options ...CrossBuildOption) error { builder := GolangCrossBuilder{buildPlatform.Name, params.Target, params.InDir, params.ImageSelector} if params.Serial { if err := builder.Build(); err != nil { - return errors.Wrapf(err, "failed cross-building target=%v for platform=%v %v", params.ImageSelector, + return errors.Wrapf(err, "failed cross-building target=%s for platform=%s", params.Target, buildPlatform.Name) } } else { @@ -321,8 +321,11 @@ func (b GolangCrossBuilder) Build() error { "-v", repoInfo.RootDir+":"+mountPoint, "-w", workDir, image, + + // Arguments for docker crossbuild entrypoint. For details see + // https://github.com/elastic/golang-crossbuild/blob/main/go1.17/base/rootfs/entrypoint.go. "--build-cmd", buildCmd+" "+b.Target, - "-p", b.Platform, + "--platforms", b.Platform, ) return dockerRun(args...) diff --git a/dev-tools/mage/settings.go b/dev-tools/mage/settings.go index b721b730c6a..fbcc916fbe9 100644 --- a/dev-tools/mage/settings.go +++ b/dev-tools/mage/settings.go @@ -209,6 +209,7 @@ BeatUser = {{.BeatUser}} VersionQualifier = {{.Qualifier}} PLATFORMS = {{.PLATFORMS}} PACKAGES = {{.PACKAGES}} +CI = {{.CI}} ## Functions diff --git a/dev-tools/notice/NOTICE.txt.tmpl b/dev-tools/notice/NOTICE.txt.tmpl index b32b4e808ca..5477a22975e 100644 --- a/dev-tools/notice/NOTICE.txt.tmpl +++ b/dev-tools/notice/NOTICE.txt.tmpl @@ -26,5 +26,5 @@ Third party libraries used by the Elastic Beats project: {{ "=" | line }} Indirect dependencies -{{ template "depInfo" .Indirect }} -{{ end }} +{{ template "depInfo" .Indirect -}} +{{- end}} diff --git a/dev-tools/packaging/package_test.go b/dev-tools/packaging/package_test.go index 249bd0bb6db..9759568de6a 100644 --- a/dev-tools/packaging/package_test.go +++ b/dev-tools/packaging/package_test.go @@ -23,6 +23,7 @@ package dev_tools import ( "archive/tar" "archive/zip" + "bufio" "bytes" "compress/gzip" "encoding/json" @@ -169,7 +170,7 @@ func checkTar(t *testing.T, file string) { } func checkZip(t *testing.T, file string) { - p, err := readZip(file) + p, err := readZip(t, file, checkNpcapNotices) if err != nil { t.Error(err) return @@ -183,6 +184,62 @@ func checkZip(t *testing.T, file string) { checkLicensesPresent(t, "", p) } +const ( + npcapSettings = "Windows Npcap installation settings" + npcapGrant = `Insecure.Com LLC \(“The Nmap Project”\) has granted Elasticsearch` + npcapLicense = `Dependency : Npcap \(https://nmap.org/npcap/\)` + libpcapLicense = `Dependency : Libpcap \(http://www.tcpdump.org/\)` + winpcapLicense = `Dependency : Winpcap \(https://www.winpcap.org/\)` + radiotapLicense = `Dependency : ieee80211_radiotap.h Header File` +) + +var ( + // These reflect the order that the licenses and notices appear in the relevant files. + npcapConfigPattern = regexp.MustCompile( + "(?s)" + npcapSettings + + ".*" + npcapGrant, + ) + npcapLicensePattern = regexp.MustCompile( + "(?s)" + npcapLicense + + ".*" + libpcapLicense + + ".*" + winpcapLicense + + ".*" + radiotapLicense, + ) +) + +func checkNpcapNotices(pkg, file string, contents io.Reader) error { + if !strings.Contains(pkg, "packetbeat") { + return nil + } + + wantNotices := strings.Contains(pkg, "windows") && !strings.Contains(pkg, "oss") + + // If the packetbeat README.md is made to be generated + // conditionally then it should also be checked here. + pkg = filepath.Base(pkg) + file, err := filepath.Rel(pkg[:len(pkg)-len(filepath.Ext(pkg))], file) + if err != nil { + return err + } + switch file { + case "packetbeat.yml", "packetbeat.reference.yml": + if npcapConfigPattern.MatchReader(bufio.NewReader(contents)) != wantNotices { + if wantNotices { + return fmt.Errorf("Npcap config section not found in config file %s in %s", file, pkg) + } + return fmt.Errorf("unexpected Npcap config section found in config file %s in %s", file, pkg) + } + case "NOTICE.txt": + if npcapLicensePattern.MatchReader(bufio.NewReader(contents)) != wantNotices { + if wantNotices { + return fmt.Errorf("Npcap license section not found in %s file in %s", file, pkg) + } + return fmt.Errorf("unexpected Npcap license section found in %s file in %s", file, pkg) + } + } + return nil +} + func checkDocker(t *testing.T, file string) { p, info, err := readDocker(file) if err != nil { @@ -623,7 +680,11 @@ func readTarContents(tarName string, data io.Reader) (*packageFile, error) { return p, nil } -func readZip(zipFile string) (*packageFile, error) { +// inspector is a file contents inspector. It vets the contents of the file +// within a package for a requirement and returns an error if it is not met. +type inspector func(pkg, file string, contents io.Reader) error + +func readZip(t *testing.T, zipFile string, inspectors ...inspector) (*packageFile, error) { r, err := zip.OpenReader(zipFile) if err != nil { return nil, err @@ -636,6 +697,18 @@ func readZip(zipFile string) (*packageFile, error) { File: f.Name, Mode: f.Mode(), } + for _, inspect := range inspectors { + r, err := f.Open() + if err != nil { + t.Errorf("failed to open %s in %s: %v", f.Name, zipFile, err) + break + } + err = inspect(zipFile, f.Name, r) + if err != nil { + t.Error(err) + } + r.Close() + } } return p, nil @@ -740,7 +813,6 @@ func readDockerManifest(r io.Reader) (*dockerManifest, error) { err = json.Unmarshal(data, &manifests) if err != nil { return nil, err - } if len(manifests) != 1 { diff --git a/go.mod b/go.mod index 7f2fc8b256e..93d7a3d4a84 100644 --- a/go.mod +++ b/go.mod @@ -165,6 +165,7 @@ require ( go.uber.org/zap v1.14.0 golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 + golang.org/x/mod v0.5.1 golang.org/x/net v0.0.0-20211020060615-d418f374d309 golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c @@ -268,9 +269,13 @@ require ( github.com/xdg/stringprep v1.0.3 // indirect go.elastic.co/fastjson v1.1.0 // indirect go.opencensus.io v0.23.0 // indirect +<<<<<<< HEAD go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee // indirect golang.org/x/mod v0.5.1 // indirect golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect +======= + golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect +>>>>>>> 72a43be9e (x-pack/packetbeat: install Npcap at start-up when required (#29112)) golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/appengine v1.6.7 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect diff --git a/packetbeat/README.md b/packetbeat/README.md index fcda826edbf..0ce898ac499 100644 --- a/packetbeat/README.md +++ b/packetbeat/README.md @@ -39,3 +39,17 @@ If you are sure you found a bug or have a feature request, open an issue on We love contributions from our community! Please read the [CONTRIBUTING.md](../CONTRIBUTING.md) file. + +## LICENSE NOTICE for Windows users of Packetbeat + +The default distribution of Packetbeat for Windows comes bundled with the Npcap +library. This is not available in the OSS-only distribution of Packetbeat. + +**Restrictions on Distribution** + +Insecure.Com LLC (“The Nmap Project”) has granted Elasticsearch BV and its +affiliates the right to include Npcap with this distribution of Packetbeat. +You may not distribute this version of Packetbeat or any other package from +Elastic that includes Npcap. If you wish to distribute Npcap, or any package +that includes Npcap, you should reach out to The Nmap Project to obtain a +distribution license. See https://nmap.org/npcap/ for more details. diff --git a/packetbeat/_meta/config/beat.reference.yml.tmpl b/packetbeat/_meta/config/beat.reference.yml.tmpl index 5d8d8fa9c7a..856a9475fe9 100644 --- a/packetbeat/_meta/config/beat.reference.yml.tmpl +++ b/packetbeat/_meta/config/beat.reference.yml.tmpl @@ -57,6 +57,8 @@ packetbeat.interfaces.internal_networks: # can stay enabled even after beat is shut down. #packetbeat.interfaces.auto_promisc_mode: true +{{- template "windows_npcap.yml.tmpl" .}} + {{header "Flows"}} packetbeat.flows: diff --git a/packetbeat/_meta/config/beat.yml.tmpl b/packetbeat/_meta/config/beat.yml.tmpl index 2a69df42517..95410045593 100644 --- a/packetbeat/_meta/config/beat.yml.tmpl +++ b/packetbeat/_meta/config/beat.yml.tmpl @@ -23,6 +23,8 @@ packetbeat.interfaces.device: {{ call .device .GOOS }} packetbeat.interfaces.internal_networks: - private +{{- template "windows_npcap.yml.tmpl" .}} + {{header "Flows"}} # Set `enabled: false` or comment out all options to disable flows reporting. diff --git a/packetbeat/_meta/config/windows_npcap.yml.tmpl b/packetbeat/_meta/config/windows_npcap.yml.tmpl new file mode 100644 index 00000000000..a6c13db4a53 --- /dev/null +++ b/packetbeat/_meta/config/windows_npcap.yml.tmpl @@ -0,0 +1,36 @@ +{{if and (eq .BeatLicense "Elastic License") (eq .GOOS "windows")}} + +{{header "Windows Npcap installation settings"}} + +# Windows Npcap installation options. These options specify how the Npcap packet +# capture library for Windows should be obtained and installed. +# Npcap installation is only available in the default distribution of Packetbeat +# for Windows and is not available in the OSS-only distribution of Packetbeat. +# +# LICENSE NOTICE +# +# Restrictions on Distribution +# +# Insecure.Com LLC (“The Nmap Project”) has granted Elasticsearch BV and its +# affiliates the right to include Npcap with this distribution of Packetbeat. +# You may not distribute this version of Packetbeat or any other package from +# Elastic that includes Npcap. If you wish to distribute Npcap, or any package +# that includes Npcap, you should reach out to The Nmap Project to obtain a +# distribution license. See https://nmap.org/npcap/ for more details. +# +#npcap: +# # install_destination allows configuration of the location that the Npcap will +# # place the Npcap library and associated files. See https://nmap.org/npcap/guide/npcap-users-guide.html#npcap-installation-uninstall-options. +# install_destination: "" +# install_timeout: 120s +# # ignore_missing_registry specifies that failure to query the registry server +# # will be ignored with a logged warning. +# ignore_missing_registry: false +# # By default Npcap will be installed only when a newer version of Npcap is available. +# # force_reinstall forces a new installation of Npcap in all cases. +# force_reinstall: false +# # If a specific local version of Npcap is required installation by packetbeat +# # can be blocked by setting never_install to true. No action is taken if this +# # option is set to true. +# never_install: false +{{- end -}} diff --git a/packetbeat/beater/install_npcap.go b/packetbeat/beater/install_npcap.go new file mode 100644 index 00000000000..ef9edd5617b --- /dev/null +++ b/packetbeat/beater/install_npcap.go @@ -0,0 +1,104 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +package beater + +import ( + "context" + "fmt" + "os" + "path/filepath" + "runtime" + "time" + + "github.com/google/gopacket/pcap" + + "github.com/elastic/beats/v7/libbeat/beat" + "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/packetbeat/npcap" +) + +type npcapConfig struct { + NeverInstall bool `config:"npcap.never_install"` + ForceReinstall bool `config:"npcap.force_reinstall"` + InstallTimeout time.Duration `config:"npcap.install_timeout"` + InstallDestination string `config:"npcal.install_destination"` +} + +func (c *npcapConfig) Init() { + // Set defaults. + c.InstallTimeout = 120 * time.Second +} + +func installNpcap(b *beat.Beat) error { + if !b.Info.ElasticLicensed { + return nil + } + if runtime.GOOS != "windows" { + return nil + } + + defer func() { + log := logp.NewLogger("npcap") + npcapVersion := pcap.Version() + if npcapVersion == "" { + log.Warn("no version available for npcap") + } else { + log.Infof("npcap version: %s", npcapVersion) + } + }() + + var cfg npcapConfig + err := b.BeatConfig.Unpack(&cfg) + if err != nil { + return fmt.Errorf("failed to unpack npcap config: %w", err) + } + if cfg.NeverInstall { + return nil + } + + ctx, cancel := context.WithTimeout(context.Background(), cfg.InstallTimeout) + defer cancel() + + log := logp.NewLogger("npcap_install") + + if npcap.Installer == nil { + return nil + } + if !cfg.ForceReinstall && !npcap.Upgradeable() { + npcap.Installer = nil + return nil + } + tmp, err := os.MkdirTemp("", "") + if err != nil { + return fmt.Errorf("could not create installation temporary directory: %w", err) + } + defer func() { + // The init sequence duplicates the embedded binary. + // Get rid of the part we can. The remainder is in + // the packetbeat text section as a string. + npcap.Installer = nil + // Remove the installer from the file system. + os.RemoveAll(tmp) + }() + installerPath := filepath.Join(tmp, "npcap.exe") + err = os.WriteFile(installerPath, npcap.Installer, 0o700) + if err != nil { + return fmt.Errorf("could not create installation temporary file: %w", err) + } + return npcap.Install(ctx, log, installerPath, cfg.InstallDestination, false) +} diff --git a/packetbeat/beater/packetbeat.go b/packetbeat/beater/packetbeat.go index d72a98d4a5f..3a1f7d6c2d9 100644 --- a/packetbeat/beater/packetbeat.go +++ b/packetbeat/beater/packetbeat.go @@ -111,6 +111,12 @@ func (pb *packetbeat) Run(b *beat.Beat) error { } }() + // Install Npcap if needed. + err := installNpcap(b) + if err != nil { + return err + } + if !b.Manager.Enabled() { return pb.runStatic(b, pb.factory) } diff --git a/packetbeat/npcap/npcap.go b/packetbeat/npcap/npcap.go new file mode 100644 index 00000000000..c81d1ce731d --- /dev/null +++ b/packetbeat/npcap/npcap.go @@ -0,0 +1,166 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +// Package npcap handles fetching and installing Npcap fow Windows. +// +// The npcap package interacts with a registry and download server that +// provides a current_version end point that serves a JSON message that +// corresponds to the this Go type: +// +// struct { +// Version string // The semverish version of the Npcap installer. +// URL string // The location of the Npcap installer. +// Hash string // The sha256 hash of the Npcap installer. +// } +// +// The URL field will point to the location of anb Npcap installer. +package npcap + +import ( + "bytes" + "context" + "errors" + "fmt" + "os/exec" + "runtime" + "strings" + + "github.com/google/gopacket/pcap" + "golang.org/x/mod/semver" + + "github.com/elastic/beats/v7/libbeat/logp" +) + +var ( + // Installer holds the embedded installer when run with x-pack. + Installer []byte + + // EmbeddedInstallerVersion holds the version of the embedded installer. + EmbeddedInstallerVersion string +) + +// Install runs the Npcap installer at the provided path. The install +// destination is specified by dst and installation using WinPcap +// API-compatible Mode is specifed by compat. If dst is the empty string +// the default install location is used. +// +// See https://nmap.org/npcap/guide/npcap-users-guide.html#npcap-installation-uninstall-options +// for details. +func Install(ctx context.Context, log *logp.Logger, path, dst string, compat bool) error { + if runtime.GOOS != "windows" { + return errors.New("npcap: called Install on non-Windows platform") + } + return install(ctx, log, path, dst, compat) +} + +func install(ctx context.Context, log *logp.Logger, path, dst string, compat bool) error { + args := []string{"/S", "/winpcap_mode=no"} + if compat { + args[1] = "/winpcap_mode=yes" + } + if dst != "" { + // The destination switch must be last as it uses unquoted spaces. + // See https://nmap.org/npcap/guide/npcap-users-guide.html#npcap-installation-uninstall-options. + args = append(args, "/D="+dst) + } + cmd := exec.CommandContext(ctx, path, args...) + var outBuf, errBuf bytes.Buffer + cmd.Stdout = &outBuf + cmd.Stderr = &errBuf + + err := cmd.Start() + if err != nil { + return fmt.Errorf("npcap: failed to start Npcap installer: %w", err) + } + + err = cmd.Wait() + if outBuf.Len() != 0 { + log.Info(&outBuf) + } + if err != nil { + log.Error(&errBuf) + return fmt.Errorf("npcap: failed to install Npcap: %w", err) + } + + return reloadWinPCAP() +} + +func Upgradeable() bool { + // This is only set when a real installer is placed in + // x-pack/packetbeat/npcap/installer. + if EmbeddedInstallerVersion == "" { + return false + } + + // pcap.Version() returns a string in the form: + // + // Npcap version 1.55, based on libpcap version 1.10.2-PRE-GIT + // + // if an Npcap version is installed. See https://nmap.org/npcap/guide/npcap-devguide.html#npcap-detect + installed := pcap.Version() + if !strings.HasPrefix(installed, "Npcap version") { + return true + } + installed = strings.TrimPrefix(installed, "Npcap version ") + idx := strings.Index(installed, ",") + if idx < 0 { + return true + } + installed = installed[:idx] + return semver.Compare("v"+installed, "v"+EmbeddedInstallerVersion) < 0 +} + +// Uninstall uninstalls the Npcap tools. The path to the uninstaller can +// be provided, otherwise the default install location in used. +// +// See https://nmap.org/npcap/guide/npcap-users-guide.html#npcap-installation-uninstall-options +// for details. +func Uninstall(ctx context.Context, log *logp.Logger, path string) error { + if runtime.GOOS != "windows" { + return errors.New("npcap: called Uninstall on non-Windows platform") + } + if pcap.Version() == "" { + return nil + } + return uninstall(ctx, log, path) +} + +func uninstall(ctx context.Context, log *logp.Logger, path string) error { + const uninstaller = `C:\Program Files\Npcap\Uninstall.exe` + if path == "" { + path = uninstaller + } + cmd := exec.CommandContext(ctx, path, `/S`) + var outBuf, errBuf bytes.Buffer + cmd.Stdout = &outBuf + cmd.Stderr = &errBuf + + err := cmd.Start() + if err != nil { + return fmt.Errorf("npcap: failed to start Npcap uninstaller: %w", err) + } + + err = cmd.Wait() + if outBuf.Len() != 0 { + log.Info(&outBuf) + } + if err != nil { + log.Error(&errBuf) + return fmt.Errorf("npcap: failed to uninstall Npcap: %w", err) + } + return nil +} diff --git a/packetbeat/npcap/npcap_other.go b/packetbeat/npcap/npcap_other.go new file mode 100644 index 00000000000..c813644d471 --- /dev/null +++ b/packetbeat/npcap/npcap_other.go @@ -0,0 +1,25 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +//go:build !windows +// +build !windows + +package npcap + +func loadWinPCAP() error { return nil } + +func reloadWinPCAP() error { return nil } diff --git a/packetbeat/npcap/npcap_test.go b/packetbeat/npcap/npcap_test.go new file mode 100644 index 00000000000..e0f1a3e4eaf --- /dev/null +++ b/packetbeat/npcap/npcap_test.go @@ -0,0 +1,93 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +package npcap + +import ( + "context" + "os" + "os/exec" + "path/filepath" + "runtime" + "testing" + + "github.com/elastic/beats/v7/libbeat/logp" +) + +func TestNpcap(t *testing.T) { + // Ugh. + var lcfg logp.Config + logp.ToObserverOutput()(&lcfg) + logp.Configure(lcfg) + obs := logp.ObserverLogs() + + // Working space. + dir, err := os.MkdirTemp("", "packetbeat-npcap-*") + if err != nil { + t.Fatalf("failed to create working directory: %v", err) + } + defer os.RemoveAll(dir) + path := filepath.Join(dir, "installer") + if runtime.GOOS == "windows" { + path += ".exe" + } + + t.Run("Install", func(t *testing.T) { + build := exec.Command("go", "build", "-o", path, filepath.FromSlash("testdata/mock_installer.go")) + b, err := build.CombinedOutput() + if err != nil { + t.Fatalf("failed to build mock installer: %v\n%s", err, b) + } + log := logp.NewLogger("npcap_test_install") + for _, compat := range []bool{false, true} { + for _, dst := range []string{ + "", // Default. + `C:\some\other\location`, + } { + err = install(context.Background(), log, path, dst, compat) + messages := obs.TakeAll() + if err != nil { + if dst == "" { + dst = "default location" + } + t.Errorf("unexpected error running installer to %s with compat=%t: %v", dst, compat, err) + for _, e := range messages { + t.Log(e.Message) + } + } + } + } + }) + + t.Run("Uninstall", func(t *testing.T) { + path = filepath.Join(filepath.Dir(path), "Uninstall.exe") + build := exec.Command("go", "build", "-o", path, filepath.FromSlash("testdata/mock_uninstaller.go")) + b, err := build.CombinedOutput() + if err != nil { + t.Fatalf("failed to build mock uninstaller: %v\n%s", err, b) + } + log := logp.NewLogger("npcap_test_uninstall") + err = uninstall(context.Background(), log, path) + messages := obs.TakeAll() + if err != nil { + t.Errorf("unexpected error running uninstaller: %v", err) + for _, e := range messages { + t.Log(e.Message) + } + } + }) +} diff --git a/packetbeat/npcap/npcap_windows.go b/packetbeat/npcap/npcap_windows.go new file mode 100644 index 00000000000..44d0053820f --- /dev/null +++ b/packetbeat/npcap/npcap_windows.go @@ -0,0 +1,33 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +//go:build windows +// +build windows + +package npcap + +import "github.com/google/gopacket/pcap" + +func loadWinPCAP() error { return pcap.LoadWinPCAP() } + +func reloadWinPCAP() error { + err := pcap.UnloadWinPCAP() + if err != nil { + return err + } + return pcap.LoadWinPCAP() +} diff --git a/packetbeat/npcap/testdata/mock_installer.go b/packetbeat/npcap/testdata/mock_installer.go new file mode 100644 index 00000000000..cb82464d8b0 --- /dev/null +++ b/packetbeat/npcap/testdata/mock_installer.go @@ -0,0 +1,44 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +package main + +import ( + "log" + "os" + "strings" +) + +func main() { + log.SetFlags(0) + log.SetPrefix("installer message: ") + switch len(os.Args) { + case 3, 4: + // OK + default: + log.Fatalf("unexpected number of argument: want 3 or 4 but got:%q", os.Args) + } + if os.Args[1] != "/S" { + log.Fatalf(`unexpected first argument: want:"/S" got:%q`, os.Args[1]) + } + if os.Args[2] != "/winpcap_mode=yes" && os.Args[2] != "/winpcap_mode=no" { + log.Fatalf(`unexpected second argument: want:"/winpcap_mode={yes,no}" got:%q`, os.Args[2]) + } + if len(os.Args) > 3 && !strings.HasPrefix(os.Args[len(os.Args)-1], "/D=") { + log.Fatalf(`unexpected final argument: want:"/D=" got:%#q`, os.Args[3]) + } +} diff --git a/packetbeat/npcap/testdata/mock_uninstaller.go b/packetbeat/npcap/testdata/mock_uninstaller.go new file mode 100644 index 00000000000..f86472cb990 --- /dev/null +++ b/packetbeat/npcap/testdata/mock_uninstaller.go @@ -0,0 +1,34 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +package main + +import ( + "log" + "os" +) + +func main() { + log.SetFlags(0) + log.SetPrefix("uninstaller message: ") + if len(os.Args) != 2 { + log.Fatalf("unexpected number of argument: want 2 but got:%q", os.Args) + } + if os.Args[1] != "/S" { + log.Fatalf(`unexpected first argument: want:"/S" got:%q`, os.Args[1]) + } +} diff --git a/packetbeat/scripts/mage/package.go b/packetbeat/scripts/mage/package.go index 55f26493cf5..031ca09c894 100644 --- a/packetbeat/scripts/mage/package.go +++ b/packetbeat/scripts/mage/package.go @@ -18,6 +18,9 @@ package mage import ( + "os" + "path/filepath" + "github.com/pkg/errors" devtools "github.com/elastic/beats/v7/dev-tools/mage" @@ -48,6 +51,31 @@ func CustomizePackaging() { return devtools.Config(devtools.ReferenceConfigType, c, spec.MustExpand("{{.PackageDir}}")) }, } + npcapNoticeTxt = devtools.PackageFile{ + Mode: 0o644, + Source: "{{.PackageDir}}/NOTICE.txt", + Dep: func(spec devtools.PackageSpec) error { + repo, err := devtools.GetProjectRepoInfo() + if err != nil { + return err + } + + notice, err := os.ReadFile(filepath.Join(repo.RootDir, "NOTICE.txt")) + if err != nil { + return err + } + + if spec.OS == "windows" && spec.License == "Elastic License" { + license, err := os.ReadFile(devtools.XPackBeatDir("npcap/installer/LICENSE")) + if err != nil { + return err + } + notice = append(notice, license...) + } + + return os.WriteFile(devtools.CreateDir(spec.MustExpand("{{.PackageDir}}/NOTICE.txt")), notice, 0o644) + }, + } ) for _, args := range devtools.Packages { @@ -56,6 +84,7 @@ func CustomizePackaging() { case devtools.TarGz, devtools.Zip: args.Spec.ReplaceFile("{{.BeatName}}.yml", configYml) args.Spec.ReplaceFile("{{.BeatName}}.reference.yml", referenceConfigYml) + args.Spec.ReplaceFile("NOTICE.txt", npcapNoticeTxt) case devtools.Deb, devtools.RPM, devtools.DMG: args.Spec.ReplaceFile("/etc/{{.BeatName}}/{{.BeatName}}.yml", configYml) args.Spec.ReplaceFile("/etc/{{.BeatName}}/{{.BeatName}}.reference.yml", referenceConfigYml) diff --git a/x-pack/packetbeat/LICENSE-Npcap.txt b/x-pack/packetbeat/LICENSE-Npcap.txt new file mode 100644 index 00000000000..850c567c317 --- /dev/null +++ b/x-pack/packetbeat/LICENSE-Npcap.txt @@ -0,0 +1,228 @@ + +NPCAP COPYRIGHT / END USER LICENSE AGREEMENT + +Npcap is a Windows packet sniffing driver and library and is copyright +(c) 2013-2021 by Insecure.Com LLC ("The Nmap Project"). All rights +reserved. + +Even though Npcap source code is publicly available for review, it is +not open source software and may not be redistributed without special +permission from the Nmap Project. The standard version is also +limited to installation on five systems. We fund the Npcap project by +selling two types of commercial licenses to a special Npcap OEM +edition: + +1) Npcap OEM Redistribution License allows companies to redistribute +Npcap with their products. + +2) Npcap OEM Internal Use License allows companies to use Npcap OEM +internally in excess of the free/demo version's normal 5-system +limitation. + +Both of these licenses include updates and support as well as a +warranty. Npcap OEM also includes a silent installer for unattended +installation. Further details about Npcap OEM are available from +https://nmap.org/npcap/oem/, and you are also welcome to contact us at +sales@nmap.com to ask any questions or set up a license for your +organization. + +Free and open source software producers are also welcome to contact us +for redistribution requests. However, we normally recommend that such +authors instead ask your users to download and install Npcap themselves. + +If the Nmap Project (directly or through one of our commercial +licensing customers) has granted you additional rights to Npcap or +Npcap OEM, those additional rights take precedence where they conflict +with the terms of this license agreement. + +Since the Npcap source code is available for download and review, +users sometimes contribute code patches to fix bugs or add new +features. By sending these changes to the Nmap Project (including +through direct email or our mailing lists or submitting pull requests +through our source code repository), it is understood unless you +specify otherwise that you are offering the Nmap Project the +unlimited, non-exclusive right to reuse, modify, and relicence your +code contribution so that we may (but are not obligated to) +incorporate it into Npcap. If you wish to specify special license +conditions or restrictions on your contributions, just say so when you +send them. + +This copy of Npcap (the "Software") and accompanying documentation is +licensed and not sold. This Software is protected by copyright laws +and treaties, as well as laws and treaties related to other forms of +intellectual property. The Nmap Project owns intellectual property +rights in the Software. The Licensee's ("you" or "your") license to +download, use, copy, or change the Software is subject to these rights +and to all the terms and conditions of this End User License Agreement +("Agreement"). + +ACCEPTANCE + +By accepting this agreement or by downloading, installing, using, or +copying the Software, or by clicking "I Agree", you agree to be bound +by the terms of this EULA. If you do not agree to the terms of this +EULA, do not install, use, or copy the Software. + +LICENSE GRANT + +This Agreement entitles you to install and use five (5) copies of the +Software. In addition, you may make archival copies of the Software +which may only be used for the reinstallation of the Software. This +Agreement does not permit the installation or use of more than 5 +copies of the Software, or the installation of the Software on more +than five computer at any given time, on a system that allows shared +used of applications by more than five users, or on any configuration +or system of computers that allows more than five users. A user may +only have one instance of this Agreement active at once. For example, +downloading the software multiple times, downloading multiple versions +of the software, and/or executing the software installer multiple +times do not grant any additional rights such as using the software on +more machines. + +The terms "computer" and "machine" in this license include any +computing device, including software computing instances such as +virtual machines and Docker containers. + +Copies of Npcap do not count toward the five copy, five computer, or +five user limitations imposed by this section if they are installed +and used solely in conjunction with any of the following software: + +o The Nmap Security Scanner, as distributed from https://nmap.org + +o The Wireshark network protocol analyzer, as distributed from + https://www.wireshark.org/ + +o Microsoft Defender for Identity, as distributed from + https://www.microsoft.com/en-us/microsoft-365/security/identity-defender + +Users wishing to redistribute Npcap or exceed the usage limits imposed +by this free license or benefit from commercial support and features +such as a silent installer should contact sales@nmap.com to obtain an +appropriate commercial license agreement. More details on our OEM +edition is also available from https://nmap.org/npcap/oem/. + +DISCLAIMER OF WARRANTIES AND LIMITATION OF LIABILITY + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +RESTRICTIONS ON TRANSFER + +Without first obtaining the express written consent of the Nmap +Project, you may not assign your rights and obligations under this +Agreement, or redistribute, encumber, sell, rent, lease, sublicense, +or otherwise transfer your rights to the Software Product. + +RESTRICTIONS ON USE + +You may not use, copy, or install the Software Product on more than +five computers, or permit the use, copying, or installation of the +Software Product by more than five users or on more than five +computers. + +RESTRICTIONS ON COPYING + +You may not copy any part of the Software except to the extent that +licensed use inherently demands the creation of a temporary copy +stored in computer memory and not permanently affixed on storage +medium. You may make archival copies as well. + +DISCLAIMER OF WARRANTIES AND LIMITATION OF LIABILITY + +UNLESS OTHERWISE EXPLICITLY AGREED TO IN WRITING BY THE NMAP PROJECT, +THE NMAP PROJECT MAKES NO OTHER WARRANTIES, EXPRESS OR IMPLIED, IN +FACT OR IN LAW, INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES +OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OTHER THAN AS +SET FORTH IN THIS AGREEMENT OR IN THE LIMITED WARRANTY DOCUMENTS +PROVIDED WITH THE SOFTWARE. + +The Nmap Project makes no warranty that the Software will meet your +requirements or operate under your specific conditions of use. The +Nmap Project makes no warranty that operation of the Software Product +will be secure, error free, or free from interruption. YOU MUST +DETERMINE WHETHER THE SOFTWARE SUFFICIENTLY MEETS YOUR REQUIREMENTS +FOR SECURITY AND UNINTERRUPTABILITY. YOU BEAR SOLE RESPONSIBILITY AND +ALL LIABILITY FOR ANY LOSS INCURRED DUE TO FAILURE OF THE SOFTWARE TO +MEET YOUR REQUIREMENTS. THE NMAP PROJECT WILL NOT, UNDER ANY +CIRCUMSTANCES, BE RESPONSIBLE OR LIABLE FOR THE LOSS OF DATA ON ANY +COMPUTER OR INFORMATION STORAGE DEVICE. + +UNDER NO CIRCUMSTANCES SHALL THE NMAP PROJECT, ITS DIRECTORS, +OFFICERS, EMPLOYEES OR AGENTS BE LIABLE TO YOU OR ANY OTHER PARTY FOR +INDIRECT, CONSEQUENTIAL, SPECIAL, INCIDENTAL, PUNITIVE, OR EXEMPLARY +DAMAGES OF ANY KIND (INCLUDING LOST REVENUES OR PROFITS OR LOSS OF +BUSINESS) RESULTING FROM THIS AGREEMENT, OR FROM THE FURNISHING, +PERFORMANCE, INSTALLATION, OR USE OF THE SOFTWARE, WHETHER DUE TO A +BREACH OF CONTRACT, BREACH OF WARRANTY, OR THE NEGLIGENCE OF THE NMAP +PROJECT OR ANY OTHER PARTY, EVEN IF THE NMAP PROJECT IS ADVISED +BEFOREHAND OF THE POSSIBILITY OF SUCH DAMAGES. TO THE EXTENT THAT THE +APPLICABLE JURISDICTION LIMITS THE NMAP PROJECT'S ABILITY TO DISCLAIM +ANY IMPLIED WARRANTIES, THIS DISCLAIMER SHALL BE EFFECTIVE TO THE +MAXIMUM EXTENT PERMITTED. + +LIMITATIONS OF REMEDIES AND DAMAGES + +Your remedy for a breach of this Agreement or of any warranty included +in this Agreement is the correction or replacement of the Software or +a refund of the purchase price of the Software, exclusive of any costs +for shipping and handling. Selection of whether to correct or replace +or refund shall be solely at the discretion of the Nmap Project. The +Nmap Project reserves the right to substitute a functionally +equivalent copy of the Software Product as a replacement. + +Any claim must be made within the applicable warranty period. All +warranties cover only defects arising under normal use and do not +include malfunctions or failure resulting from misuse, abuse, neglect, +alteration, problems with electrical power, acts of nature, unusual +temperatures or humidity, improper installation, or damage determined +by the Nmap Project to have been caused by you. All limited warranties +on the Software Product are granted only to you and are +non-transferable. + +You agree to indemnify and hold the Nmap Project harmless from all +claims, judgments, liabilities, expenses, or costs arising from your +breach of this Agreement and/or acts or omissions. + +GOVERNING LAW, JURISDICTION AND COSTS + +This Agreement is governed by the laws the United States of America +and Washington State, without regard to Washington's conflict or +choice of law provisions. + +SEVERABILITY + +If any provision of this Agreement shall be held to be invalid or +unenforceable, the remainder of this Agreement shall remain in full +force and effect. To the extent any express or implied restrictions +are not permitted by applicable laws, these express or implied +restrictions shall remain in force and effect to the maximum extent +permitted by such applicable laws. + +THIRD PARTY SOFTWARE ATTRIBUTION + +Npcap uses several 3rd party open source software libraries: + +* The libpcap portable packet capturing library from https://tcpdump.org +* The Winpcap packet capturing library. It has been abandoned, but is + currently still available from https://www.winpcap.org/. +* The ieee80211_radiotap.h header file from David Young + +All of these are open source with BSD-style licenses that allow for +unlimited use and royalty-free redistribution within other software +(including commercial/proprietary software). Some include a warranty +disclaimer (relating to the original authors) and require a small +amount of acknowledgment text be added somewhere in the documentation +of any software which includes them (including indirect inclusion +through Npcap). + +The required acknowledgement text as well as full license text and +source details for these libraries is available from: +https://npcap.org/src/docs/Npcap-Third-Party-Open-Source.pdf . + +Since Insecure.Com LLC is not the author of this 3rd party code, we +can not waive or modify it’s software copyright or license. Npcap +users and redistributors must comply with the relevant Npcap license +(either the free/demo license or a commercial Npcap OEM license they +may have purchased) as well as the minimal requirements of this 3rd +party open source software. diff --git a/x-pack/packetbeat/cmd/root.go b/x-pack/packetbeat/cmd/root.go index c7c15b058be..407d24570df 100644 --- a/x-pack/packetbeat/cmd/root.go +++ b/x-pack/packetbeat/cmd/root.go @@ -9,6 +9,9 @@ import ( packetbeatCmd "github.com/elastic/beats/v7/packetbeat/cmd" _ "github.com/elastic/beats/v7/x-pack/libbeat/include" + + // This registers the Npcap installer on Windows. + _ "github.com/elastic/beats/v7/x-pack/packetbeat/npcap" ) // Name of this beat. diff --git a/x-pack/packetbeat/magefile.go b/x-pack/packetbeat/magefile.go index f5e930c5156..d8a82058c24 100644 --- a/x-pack/packetbeat/magefile.go +++ b/x-pack/packetbeat/magefile.go @@ -10,9 +10,11 @@ package main import ( "fmt" "os" + "strings" "time" "github.com/magefile/mage/mg" + "github.com/magefile/mage/sh" devtools "github.com/elastic/beats/v7/dev-tools/mage" packetbeat "github.com/elastic/beats/v7/packetbeat/scripts/mage" @@ -27,6 +29,11 @@ import ( _ "github.com/elastic/beats/v7/dev-tools/mage/target/test" ) +// NpcapVersion specifies the version of the OEM Npcap installer to bundle with +// the packetbeat executable. It is used to specify which npcap builder crossbuild +// image to use. +const NpcapVersion = "1.60" + func init() { common.RegisterCheckDeps(Update) @@ -57,12 +64,43 @@ func Build() error { // GolangCrossBuild build the Beat binary inside of the golang-builder. // Do not use directly, use crossBuild instead. func GolangCrossBuild() error { + if devtools.Platform.GOOS == "windows" && (devtools.Platform.GOARCH == "amd64" || devtools.Platform.GOARCH == "386") { + const installer = "npcap-" + NpcapVersion + "-oem.exe" + err := sh.Copy("./npcap/installer/"+installer, "/installer/"+installer) + if err != nil { + return fmt.Errorf("failed to copy Npcap installer into source tree: %w", err) + } + } return packetbeat.GolangCrossBuild() } // CrossBuild cross-builds the beat for all target platforms. +// +// On Windows platforms, if CrossBuild is invoked with the environment variables +// CI or NPCAP_LOCAL set to "true", a private cross-build image is selected that +// provides the OEM Npcap installer for the build. This behaviour requires access +// to the private image. func CrossBuild() error { - return packetbeat.CrossBuild() + return devtools.CrossBuild( + // Run all builds serially to try to address failures that might be caused + // by concurrent builds. See https://github.com/elastic/beats/issues/24304. + devtools.Serially(), + + devtools.ImageSelector(func(platform string) (string, error) { + image, err := devtools.CrossBuildImage(platform) + if err != nil { + return "", err + } + if os.Getenv("CI") != "true" && os.Getenv("NPCAP_LOCAL") != "true" { + return image, nil + } + if platform == "windows/amd64" || platform == "windows/386" { + image = strings.ReplaceAll(image, "beats-dev", "observability-ci") // Temporarily work around naming of npcap image. + image = strings.ReplaceAll(image, "main", "npcap-"+NpcapVersion+"-debian9") + } + return image, nil + }), + ) } // BuildGoDaemon builds the go-daemon binary (use crossBuildGoDaemon). diff --git a/x-pack/packetbeat/npcap/installer/.gitignore b/x-pack/packetbeat/npcap/installer/.gitignore new file mode 100644 index 00000000000..43c0420c171 --- /dev/null +++ b/x-pack/packetbeat/npcap/installer/.gitignore @@ -0,0 +1,5 @@ +# Ignore everything but the README and the place-holder. +* +!.gitignore +!README +!npcap-0.00.exe diff --git a/x-pack/packetbeat/npcap/installer/LICENSE b/x-pack/packetbeat/npcap/installer/LICENSE new file mode 100644 index 00000000000..94134072930 --- /dev/null +++ b/x-pack/packetbeat/npcap/installer/LICENSE @@ -0,0 +1,229 @@ +-------------------------------------------------------------------------------- +Dependency : Npcap (https://nmap.org/npcap/) +Version: 1.60 +Licence type: Commercial +-------------------------------------------------------------------------------- + +Npcap is Copyright (c) 2013-2021 Insecure.Com LLC. All rights reserved. +See https://npcap.org for details. + +Portions of Npcap are Copyright (c) 1999 - 2005 NetGroup, Politecnico di +Torino (Italy). +Portions of Npcap are Copyright (c) 2005 - 2010 CACE Technologies, +Davis (California). +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. Neither the name of the Politecnico di Torino, CACE Technologies + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +This product includes software developed by the University of California, +Lawrence Berkeley Laboratory and its contributors. + +Portions of Npcap are Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, +1996, 1997 The Regents of the University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Portions of Npcap are Copyright (c) 2003, 2004 David Young. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright notice, + thislist of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of David Young may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL DAVID YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +-------------------------------------------------------------------------------- +Dependency : Libpcap (http://www.tcpdump.org/) +Version: 1.10 +Licence type: BSD +-------------------------------------------------------------------------------- + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +-------------------------------------------------------------------------------- +Dependency : Winpcap (https://www.winpcap.org/) +Version: 4.1.3 +Licence type: BSD +-------------------------------------------------------------------------------- + +Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy). +Copyright (c) 2005 - 2010 CACE Technologies, Davis (California). +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. Neither the name of the Politecnico di Torino, CACE Technologies + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This product includes software developed by the University of California, +Lawrence Berkeley Laboratory and its contributors. +Portions Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 The +Regents of the University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. Neither the name of the University nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + + +-------------------------------------------------------------------------------- +Dependency : ieee80211_radiotap.h Header File +Version: Unversioned +Licence type: BSD +-------------------------------------------------------------------------------- + +Copyright (c) 2003, 2004 David Young. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The name of David Young may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL DAVID YOUNG BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/x-pack/packetbeat/npcap/installer/README b/x-pack/packetbeat/npcap/installer/README new file mode 100644 index 00000000000..404d6617dd1 --- /dev/null +++ b/x-pack/packetbeat/npcap/installer/README @@ -0,0 +1,19 @@ +This directory is pinned to allow placement of the Npcap OEM installer +during x-pack Packetbeat builds. + +Only one additional exe file may be placed here beyond the place-holder +and this should be the most recent available Npcap installer. As part of the +distribution a place-holder file is put here to allow compilation. + +LICENSE NOTICE + +Restrictions on Distribution + +Insecure.Com LLC (“The Nmap Project”) has granted Elasticsearch BV and its +affiliates the right to include Npcap with this distribution of Packetbeat. +You may not distribute this version of Packetbeat or any other package from +Elastic that includes Npcap. If you wish to distribute Npcap, or any package +that includes Npcap, you should reach out to The Nmap Project to obtain a +distribution license. See https://nmap.org/npcap/ for more details. + +See the LICENSE file in this directory. diff --git a/x-pack/packetbeat/npcap/installer/npcap-0.00.exe b/x-pack/packetbeat/npcap/installer/npcap-0.00.exe new file mode 100644 index 00000000000..43d4762b1ed --- /dev/null +++ b/x-pack/packetbeat/npcap/installer/npcap-0.00.exe @@ -0,0 +1 @@ +This is not the installer you are looking for. \ No newline at end of file diff --git a/x-pack/packetbeat/npcap/npcap_other.go b/x-pack/packetbeat/npcap/npcap_other.go new file mode 100644 index 00000000000..647eab35bff --- /dev/null +++ b/x-pack/packetbeat/npcap/npcap_other.go @@ -0,0 +1,9 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +//go:build !windows +// +build !windows + +// Package npcap provides an embedded Npcap OEM installer on Windows systems. +package npcap diff --git a/x-pack/packetbeat/npcap/npcap_windows.go b/x-pack/packetbeat/npcap/npcap_windows.go new file mode 100644 index 00000000000..0eab2f5c67c --- /dev/null +++ b/x-pack/packetbeat/npcap/npcap_windows.go @@ -0,0 +1,54 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +//go:build windows +// +build windows + +// Package npcap provides an embedded Npcap OEM installer. The embedded installer +// must be placed in the installer directory and have a name that matches the pattern +// "npcap-([0-9]\.[0-9]+)(?:|-oem)\.exe" where the capture is the installer version. +package npcap + +import ( + "embed" + "fmt" + "path" + "strings" + + "github.com/elastic/beats/v7/packetbeat/npcap" +) + +//go:embed installer/*.exe +var fs embed.FS + +func init() { + list, err := fs.ReadDir("installer") + if err != nil { + panic(fmt.Sprintf("failed to set up npcap installer: %v", err)) + } + var installer string + for _, f := range list { + name := f.Name() + if name != "npcap-0.00.exe" { + installer = name + break + } + } + if installer == "" { + return + } + if len(list) > 2 { + panic(fmt.Sprintf("unexpected number of installers found: want only one but got %d", len(list)-1)) + } + + version := strings.TrimPrefix(installer, "npcap-") + version = strings.TrimSuffix(version, ".exe") + version = strings.TrimSuffix(version, "-oem") + npcap.EmbeddedInstallerVersion = version + + npcap.Installer, err = fs.ReadFile(path.Join("installer", installer)) + if err != nil { + panic(fmt.Sprintf("failed to set up npcap installer: %v", err)) + } +}