From e1f4e414151974170111ce5bc51070c50eaba357 Mon Sep 17 00:00:00 2001 From: Dan Kortschak <90160302+efd6@users.noreply.github.com> Date: Thu, 27 Jan 2022 15:47:50 +1030 Subject: [PATCH] x-pack/packetbeat: install Npcap at start-up when required (#29112) This add automated installation of an OEM Npcap provided by embedding in the packetbeat executable. The installation is configurable to allow users to retain their own version of Npcap if they have one and to specify the location of the install. To simplify support this configurablity will not be included in the next release, but is comitted here to allow it to be reverted back out to make it easier to add if the decision is made to do that later. (cherry picked from commit 72a43be9ed23efc3dc2b371e2cadf5a7c575e429) # Conflicts: # go.mod --- CHANGELOG.next.asciidoc | 2 + NOTICE.txt | 75 +++--- dev-tools/mage/config.go | 1 + dev-tools/mage/crossbuild.go | 7 +- dev-tools/mage/settings.go | 1 + dev-tools/notice/NOTICE.txt.tmpl | 4 +- dev-tools/packaging/package_test.go | 78 +++++- go.mod | 5 + packetbeat/README.md | 14 ++ .../_meta/config/beat.reference.yml.tmpl | 2 + packetbeat/_meta/config/beat.yml.tmpl | 2 + .../_meta/config/windows_npcap.yml.tmpl | 36 +++ packetbeat/beater/install_npcap.go | 104 ++++++++ packetbeat/beater/packetbeat.go | 6 + packetbeat/npcap/npcap.go | 166 +++++++++++++ packetbeat/npcap/npcap_other.go | 25 ++ packetbeat/npcap/npcap_test.go | 93 +++++++ packetbeat/npcap/npcap_windows.go | 33 +++ packetbeat/npcap/testdata/mock_installer.go | 44 ++++ packetbeat/npcap/testdata/mock_uninstaller.go | 34 +++ packetbeat/scripts/mage/package.go | 29 +++ x-pack/packetbeat/LICENSE-Npcap.txt | 228 +++++++++++++++++ x-pack/packetbeat/cmd/root.go | 3 + x-pack/packetbeat/magefile.go | 40 ++- x-pack/packetbeat/npcap/installer/.gitignore | 5 + x-pack/packetbeat/npcap/installer/LICENSE | 229 ++++++++++++++++++ x-pack/packetbeat/npcap/installer/README | 19 ++ .../packetbeat/npcap/installer/npcap-0.00.exe | 1 + x-pack/packetbeat/npcap/npcap_other.go | 9 + x-pack/packetbeat/npcap/npcap_windows.go | 54 +++++ 30 files changed, 1303 insertions(+), 46 deletions(-) create mode 100644 packetbeat/_meta/config/windows_npcap.yml.tmpl create mode 100644 packetbeat/beater/install_npcap.go create mode 100644 packetbeat/npcap/npcap.go create mode 100644 packetbeat/npcap/npcap_other.go create mode 100644 packetbeat/npcap/npcap_test.go create mode 100644 packetbeat/npcap/npcap_windows.go create mode 100644 packetbeat/npcap/testdata/mock_installer.go create mode 100644 packetbeat/npcap/testdata/mock_uninstaller.go create mode 100644 x-pack/packetbeat/LICENSE-Npcap.txt create mode 100644 x-pack/packetbeat/npcap/installer/.gitignore create mode 100644 x-pack/packetbeat/npcap/installer/LICENSE create mode 100644 x-pack/packetbeat/npcap/installer/README create mode 100644 x-pack/packetbeat/npcap/installer/npcap-0.00.exe create mode 100644 x-pack/packetbeat/npcap/npcap_other.go create mode 100644 x-pack/packetbeat/npcap/npcap_windows.go diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index b512fd5c46c8..94d366e0df41 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 a8494a37f8c6..f248155d3678 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 da54123e9169..b80bd9a197be 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 9f56fd125c3e..e434be6101fc 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 b721b730c6a3..fbcc916fbe92 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 b32b4e808ca4..5477a22975eb 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 249bd0bb6dbb..9759568de6a6 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 7f2fc8b256e0..93d7a3d4a846 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 fcda826edbf3..0ce898ac4991 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 5d8d8fa9c7a7..856a9475fe91 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 2a69df425175..954100455933 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 000000000000..a6c13db4a539 --- /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 000000000000..ef9edd5617b7 --- /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 d72a98d4a5f9..3a1f7d6c2d92 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 000000000000..c81d1ce731d2 --- /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 000000000000..c813644d4717 --- /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 000000000000..e0f1a3e4eaf3 --- /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 000000000000..44d0053820f5 --- /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 000000000000..cb82464d8b0b --- /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 000000000000..f86472cb9900 --- /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 55f26493cf5b..031ca09c894b 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 000000000000..850c567c3172 --- /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 c7c15b058be7..407d24570df4 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 f5e930c5156a..d8a82058c24d 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 000000000000..43c0420c1719 --- /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 000000000000..941340729304 --- /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 000000000000..404d6617dd13 --- /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 000000000000..43d4762b1ed8 --- /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 000000000000..647eab35bff2 --- /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 000000000000..0eab2f5c67c9 --- /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)) + } +}