From b61a49cad108140e8eb6dc7ea942b85222822a51 Mon Sep 17 00:00:00 2001
From: lologit1998
Date: Thu, 2 Aug 2018 17:01:34 +0200
Subject: [PATCH] services: update hadoop
---
config/config.go | 7 +-
server/honeytrap.go | 27 ++--
services/hadoop/hadoop.go | 139 +++++++++++++++++++++
services/hadoop/hadoop_datanode.go | 126 +++++++++++++++++++
services/hadoop/hadoop_messages.go | 193 +++++++++++++++++++++++++++++
services/hadoop/hadoop_namenode.go | 123 ++++++++++++++++++
6 files changed, 606 insertions(+), 9 deletions(-)
create mode 100644 services/hadoop/hadoop.go
create mode 100644 services/hadoop/hadoop_datanode.go
create mode 100644 services/hadoop/hadoop_messages.go
create mode 100644 services/hadoop/hadoop_namenode.go
diff --git a/config/config.go b/config/config.go
index cd1b1a646..2a26fd133 100644
--- a/config/config.go
+++ b/config/config.go
@@ -37,7 +37,7 @@ import (
"os"
"github.com/BurntSushi/toml"
- logging "github.com/op/go-logging"
+ "github.com/op/go-logging"
)
var log = logging.MustGetLogger("honeytrap:config")
@@ -50,6 +50,8 @@ var format = logging.MustStringFormatter(
// Config defines the central type where all configuration is umarhsalled to.
type Config struct {
+ toml.MetaData
+
Listener toml.Primitive `toml:"listener"`
Web toml.Primitive `toml:"web"`
@@ -72,10 +74,11 @@ var Default = Config{}
// Load attempts to load the giving toml configuration file.
func (c *Config) Load(r io.Reader) error {
- _, err := toml.DecodeReader(r, c)
+ md, err := toml.DecodeReader(r, c)
if err != nil {
return err
}
+ c.MetaData = md
logBackends := []logging.Backend{}
for _, log := range c.Logging {
diff --git a/server/honeytrap.go b/server/honeytrap.go
index 67a36d2aa..6be784670 100644
--- a/server/honeytrap.go
+++ b/server/honeytrap.go
@@ -42,7 +42,6 @@ import (
"github.com/mattn/go-isatty"
- "github.com/BurntSushi/toml"
"github.com/fatih/color"
"github.com/honeytrap/honeytrap/cmd"
@@ -63,6 +62,7 @@ import (
_ "github.com/honeytrap/honeytrap/services/eos"
_ "github.com/honeytrap/honeytrap/services/ethereum"
_ "github.com/honeytrap/honeytrap/services/ftp"
+ _ "github.com/honeytrap/honeytrap/services/hadoop"
_ "github.com/honeytrap/honeytrap/services/ipp"
_ "github.com/honeytrap/honeytrap/services/redis"
_ "github.com/honeytrap/honeytrap/services/smtp"
@@ -329,6 +329,7 @@ func (hc *Honeytrap) Run(ctx context.Context) {
w.Start()
channels := map[string]pushers.Channel{}
+ isChannelUsed := make(map[string]bool)
// sane defaults!
for key, s := range hc.config.Channels {
@@ -336,7 +337,7 @@ func (hc *Honeytrap) Run(ctx context.Context) {
Type string `toml:"type"`
}{}
- err := toml.PrimitiveDecode(s, &x)
+ err := hc.config.PrimitiveDecode(s, &x)
if err != nil {
log.Error("Error parsing configuration of channel: %s", err.Error())
continue
@@ -355,6 +356,7 @@ func (hc *Honeytrap) Run(ctx context.Context) {
log.Fatalf("Error initializing channel %s(%s): %s", key, x.Type, err)
} else {
channels[key] = d
+ isChannelUsed[key] = false
}
}
@@ -365,7 +367,7 @@ func (hc *Honeytrap) Run(ctx context.Context) {
Categories []string `toml:"categories"`
}{}
- err := toml.PrimitiveDecode(s, &x)
+ err := hc.config.PrimitiveDecode(s, &x)
if err != nil {
log.Error("Error parsing configuration of filter: %s", err.Error())
continue
@@ -378,6 +380,7 @@ func (hc *Honeytrap) Run(ctx context.Context) {
continue
}
+ isChannelUsed[name] = true
channel = pushers.TokenChannel(channel, hc.token)
if len(x.Categories) != 0 {
@@ -394,6 +397,12 @@ func (hc *Honeytrap) Run(ctx context.Context) {
}
}
+ for name, isUsed := range isChannelUsed {
+ if !isUsed {
+ log.Warningf("Channel %s is unused. Did you forget to add a filter?", name)
+ }
+ }
+
// initialize directors
directors := map[string]director.Director{}
availableDirectorNames := director.GetAvailableDirectorNames()
@@ -403,7 +412,7 @@ func (hc *Honeytrap) Run(ctx context.Context) {
Type string `toml:"type"`
}{}
- err := toml.PrimitiveDecode(s, &x)
+ err := hc.config.PrimitiveDecode(s, &x)
if err != nil {
log.Error("Error parsing configuration of director: %s", err.Error())
continue
@@ -431,7 +440,7 @@ func (hc *Honeytrap) Run(ctx context.Context) {
Type string `toml:"type"`
}{}
- if err := toml.PrimitiveDecode(hc.config.Listener, &x); err != nil {
+ if err := hc.config.PrimitiveDecode(hc.config.Listener, &x); err != nil {
log.Error("Error parsing configuration of listener: %s", err.Error())
return
}
@@ -455,7 +464,7 @@ func (hc *Honeytrap) Run(ctx context.Context) {
Port string `toml:"port"`
}{}
- if err := toml.PrimitiveDecode(s, &x); err != nil {
+ if err := hc.config.PrimitiveDecode(s, &x); err != nil {
log.Error("Error parsing configuration of service %s: %s", key, err.Error())
continue
}
@@ -518,7 +527,7 @@ func (hc *Honeytrap) Run(ctx context.Context) {
Services []string `toml:"services"`
}{}
- if err := toml.PrimitiveDecode(s, &x); err != nil {
+ if err := hc.config.PrimitiveDecode(s, &x); err != nil {
log.Error("Error parsing configuration of generic ports: %s", err.Error())
continue
}
@@ -597,6 +606,10 @@ func (hc *Honeytrap) Run(ctx context.Context) {
}
}
+ if len(hc.config.Undecoded()) != 0 {
+ log.Warningf("Unrecognized keys in configuration: %v", hc.config.Undecoded())
+ }
+
if err := l.Start(ctx); err != nil {
fmt.Println(color.RedString("Error starting listener: %s", err.Error()))
return
diff --git a/services/hadoop/hadoop.go b/services/hadoop/hadoop.go
new file mode 100644
index 000000000..5e58e9ed3
--- /dev/null
+++ b/services/hadoop/hadoop.go
@@ -0,0 +1,139 @@
+/*
+* Honeytrap
+* Copyright (C) 2016-2017 DutchSec (https://dutchsec.com/)
+*
+* This program is free software; you can redistribute it and/or modify it under
+* the terms of the GNU Affero General Public License version 3 as published by the
+* Free Software Foundation.
+*
+* 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. See the GNU Affero General Public License for more
+* details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* version 3 along with this program in the file "LICENSE". If not, see
+* .
+*
+* See https://honeytrap.io/ for more details. All requests should be sent to
+* licensing@honeytrap.io
+*
+* The interactive user interfaces in modified source and object code versions
+* of this program must display Appropriate Legal Notices, as required under
+* Section 5 of the GNU Affero General Public License version 3.
+*
+* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
+* these Appropriate Legal Notices must retain the display of the "Powered by
+* Honeytrap" logo and retain the original copyright notice. If the display of the
+* logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
+* must display the words "Powered by Honeytrap" and retain the original copyright notice.
+ */
+
+package hadoop
+
+import (
+ "bufio"
+ "context"
+ "io"
+ "net"
+ "net/http"
+ "strings"
+
+ "github.com/honeytrap/honeytrap/pushers"
+ "github.com/honeytrap/honeytrap/services"
+)
+
+var (
+ hadoopRequestNameNode = map[string]func(*hadoopService) string{
+ "service=NameNode,name=NameNodeInfo": (*hadoopService).showNameNode,
+ "service=NameNode,name=FSNamesystemState": (*hadoopService).showFSNamesystemState,
+ }
+ hadoopRequestDataNode = map[string]func(*hadoopService) string{
+ "service=DataNode,name=DataNodeInfo": (*hadoopService).showDataNode,
+ }
+)
+
+func Hadoop(options ...services.ServicerFunc) services.Servicer {
+ s := &hadoopService{
+ hadoopServiceConfig: hadoopServiceConfig{
+ Version: "2.7.1",
+ Os: "Linux",
+ },
+ }
+ for _, o := range options {
+ o(s)
+ }
+ return s
+}
+
+type hadoopServiceConfig struct {
+ Version string `toml:"version"`
+ Os string `toml:"os"`
+}
+
+type hadoopService struct {
+ hadoopServiceConfig
+
+ ch pushers.Channel
+}
+
+func (s *hadoopService) SetChannel(ch pushers.Channel) {
+ s.ch = ch
+}
+
+func (s *hadoopService) ShowRequest(req *http.Request, hadoopRequest map[string]func(*hadoopService) string) string {
+ for i, _ := range req.Form {
+ if !strings.Contains(strings.Join(req.Form[i], ""), ":") {
+ return s.showEmpty()
+ }
+ request := strings.Split(strings.Join(req.Form[i], ""), ":")
+ switch request[0] {
+ case "Hadoop":
+ fn, ok := hadoopRequest[request[1]]
+ if !strings.Contains(request[1], ",") {
+ return s.showEmpty()
+ }
+ if !ok {
+ return s.showNothing()
+ }
+ return fn(s)
+ default:
+ return s.showNothing()
+ }
+ }
+ return ""
+}
+
+func (s *hadoopService) Handle(ctx context.Context, conn net.Conn) error {
+ defer conn.Close()
+ br := bufio.NewReader(conn)
+ req, err := http.ReadRequest(br)
+ if err == io.EOF {
+ return nil
+ } else if err != nil {
+ return err
+ }
+
+ err = req.ParseForm()
+ if err != nil {
+ return err
+ }
+
+<<<<<<< HEAD
+ port := strings.Split(conn.LocalAddr().String(), ":")
+
+ if port[1] == "50070" {
+ return s.HandleNameNode(conn, req)
+ } else if port[1] == "50075" {
+=======
+ port := conn.LocalAddr().(*net.TCPAddr).Port
+
+ if port == 50070 {
+ return s.HandleNameNode(conn, req)
+ } else if port == 50075 {
+>>>>>>> 3ca8ba0529510d2a72fa2251532783c3bfcfdbf6
+ return s.HandleDataNode(conn, req)
+ }
+
+ return nil
+}
diff --git a/services/hadoop/hadoop_datanode.go b/services/hadoop/hadoop_datanode.go
new file mode 100644
index 000000000..96706922d
--- /dev/null
+++ b/services/hadoop/hadoop_datanode.go
@@ -0,0 +1,126 @@
+/*/*
+* Honeytrap
+* Copyright (C) 2016-2017 DutchSec (https://dutchsec.com/)
+*
+* This program is free software; you can redistribute it and/or modify it under
+* the terms of the GNU Affero General Public License version 3 as published by the
+* Free Software Foundation.
+*
+* 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. See the GNU Affero General Public License for more
+* details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* version 3 along with this program in the file "LICENSE". If not, see
+* .
+*
+* See https://honeytrap.io/ for more details. All requests should be sent to
+* licensing@honeytrap.io
+*
+* The interactive user interfaces in modified source and object code versions
+* of this program must display Appropriate Legal Notices, as required under
+* Section 5 of the GNU Affero General Public License version 3.
+*
+* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
+* these Appropriate Legal Notices must retain the display of the "Powered by
+* Honeytrap" logo and retain the original copyright notice. If the display of the
+* logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
+* must display the words "Powered by Honeytrap" and retain the original copyright notice.
+ */
+
+package hadoop
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net"
+ "net/http"
+ "strings"
+ "time"
+
+ "github.com/honeytrap/honeytrap/event"
+ "github.com/honeytrap/honeytrap/services"
+)
+
+/*Example config:
+
+[service.hadoop_datanode]
+type="hadoop_datanode"
+version="2.7.1"
+os="Linux"
+
+[[port]]
+port="tcp/50075"
+services=["hadoop_datanode"]
+
+*/
+
+var (
+ _ = services.Register("hadoop_datanode", Hadoop)
+)
+
+func (s *hadoopService) HandleDataNode(conn net.Conn, req *http.Request) error {
+
+ hadoopRequest := hadoopRequestDataNode
+
+ s.ch.Send(event.New(
+ services.EventOptions,
+ event.Service("Hadoop DataNode"),
+ event.Category("hadoop_datanode"),
+ event.SourceAddr(conn.RemoteAddr()),
+ event.DestinationAddr(conn.LocalAddr()),
+ event.Custom("http.user-agent", req.UserAgent()),
+ event.Custom("http.method", req.Method),
+ event.Custom("http.proto", req.Proto),
+ event.Custom("http.host", req.Host),
+ event.Custom("http.url", req.URL.String()),
+ event.Custom("http.request", req.RequestURI),
+ ))
+
+ if req.URL.Path != "/jmx" {
+ resp := http.Response{
+ StatusCode: http.StatusNotFound,
+ Status: http.StatusText(http.StatusNotFound),
+ Proto: req.Proto,
+ ProtoMajor: req.ProtoMajor,
+ ProtoMinor: req.ProtoMinor,
+ Request: req,
+ Header: map[string][]string{
+ "Cache-Control": []string{"must-revalidate,no-cache,no-store"},
+ "Date": []string{time.Now().Format(http.TimeFormat)},
+ "Pragma": []string{"no-cache"},
+ "Content-Type": []string{"text/html; charset=iso-8859-1"},
+ "Content-length": []string{fmt.Sprintf("%d", len(s.htmlErrorPage(req.URL.Path)))},
+ "Server": []string{"Jetty(6.1.26)"},
+ },
+ }
+ resp.Body = ioutil.NopCloser(strings.NewReader(s.htmlErrorPage(req.URL.Path)))
+ return resp.Write(conn)
+ }
+
+ resp := http.Response{
+ StatusCode: http.StatusOK,
+ Status: http.StatusText(http.StatusOK),
+ Proto: req.Proto,
+ ProtoMajor: req.ProtoMajor,
+ ProtoMinor: req.ProtoMinor,
+ Request: req,
+ Header: map[string][]string{
+ "Cache-Control": []string{"no-cache"},
+ "Expires": []string{time.Now().Format(http.TimeFormat)},
+ "Date": []string{time.Now().Format(http.TimeFormat)},
+ "Pragma": []string{"no-cache"},
+ "Content-Type": []string{"application/json; charset=utf-8"},
+ "Access-Control-Allow-Methods": []string{req.Method},
+ "Access-Control-Allow-Origin": []string{"*"},
+ "Transfer-Encoding": []string{"chunked"},
+ "Server": []string{"Jetty(6.1.26)"},
+ },
+ }
+
+ resp.Body = ioutil.NopCloser(strings.NewReader(s.ShowRequest(req, hadoopRequest)))
+
+ return resp.Write(conn)
+
+}
diff --git a/services/hadoop/hadoop_messages.go b/services/hadoop/hadoop_messages.go
new file mode 100644
index 000000000..121eda0bf
--- /dev/null
+++ b/services/hadoop/hadoop_messages.go
@@ -0,0 +1,193 @@
+/*
+* Honeytrap
+* Copyright (C) 2016-2017 DutchSec (https://dutchsec.com/)
+*
+* This program is free software; you can redistribute it and/or modify it under
+* the terms of the GNU Affero General Public License version 3 as published by the
+* Free Software Foundation.
+*
+* 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. See the GNU Affero General Public License for more
+* details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* version 3 along with this program in the file "LICENSE". If not, see
+* .
+*
+* See https://honeytrap.io/ for more details. All requests should be sent to
+* licensing@honeytrap.io
+*
+* The interactive user interfaces in modified source and object code versions
+* of this program must display Appropriate Legal Notices, as required under
+* Section 5 of the GNU Affero General Public License version 3.
+*
+* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
+* these Appropriate Legal Notices must retain the display of the "Powered by
+* Honeytrap" logo and retain the original copyright notice. If the display of the
+* logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
+* must display the words "Powered by Honeytrap" and retain the original copyright notice.
+ */
+package hadoop
+
+import (
+ "fmt"
+ "time"
+)
+
+func getDayLetter() string {
+ return fmt.Sprint(time.Now().Weekday(), time.Month(time.Now().Month()), time.Now().Day())
+}
+
+func getDayNumber() string {
+ return fmt.Sprintf("%v-%d-%v", time.Now().Year(), time.Month(time.Now().Month()), time.Now().Day())
+}
+
+func getTime() string {
+ return fmt.Sprintf("%v:%v:%v", time.Now().Hour(), time.Now().Minute(), time.Now().Second())
+}
+
+func (s *hadoopService) htmlErrorPage(reqPath string) string {
+ return fmt.Sprintln(`
+
+
+
+ Error 404 NOT_FOUND
+
+ HTTP ERROR 404
+ Problem accessing `, reqPath, `. Reason:
+
NOT_FOUND
Powered by Jetty://
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `)
+}
+
+func (s *hadoopService) showEmpty() string {
+ return `{ }`
+}
+
+func (s *hadoopService) showNothing() string {
+ return `
+{
+ "beans": []
+}`
+}
+
+func (s *hadoopService) showFSNamesystemState() string {
+ return fmt.Sprintln(`
+{
+ "beans" : [ {
+ "name" : "Hadoop:service=NameNode,name=FSNamesystemState",
+ "modelerType" : "org.apache.hadoop.hdfs.server.namenode.FSNamesystem",
+ "CapacityTotal" : 41083600896,
+ "CapacityUsed" : 327680,
+ "CapacityRemaining" : 14096678912,
+ "TotalLoad" : 1,
+ "SnapshotStats" : "{\"SnapshottableDirectories\":0,\"Snapshots\":0}",
+ "BlocksTotal" : 31,
+ "MaxObjects" : 0,
+ "FilesTotal" : 35,
+ "PendingReplicationBlocks" : 0,
+ "UnderReplicatedBlocks" : 0,
+ "ScheduledReplicationBlocks" : 0,
+ "PendingDeletionBlocks" : 0,
+ "BlockDeletionStartTime" : 1532001516964,
+ "FSState" : "Operational",
+ "NumLiveDataNodes" : 1,
+ "NumDeadDataNodes" : 0,
+ "NumDecomLiveDataNodes" : 0,
+ "NumDecomDeadDataNodes" : 0,
+ "VolumeFailuresTotal" : 0,
+ "EstimatedCapacityLostTotal" : 0,
+ "NumDecommissioningDataNodes" : 0,
+ "NumStaleDataNodes" : 0,
+ "NumStaleStorages" : 0,
+ "TopUserOpCounts" : "{\"timestamp\":\"`, getDayNumber(), `T`, getTime(), `-0400\",\"windows\":[{\"windowLenMs\":300000,\"ops\":[]},{\"windowLenMs\":1500000,\"ops\":[]},{\"windowLenMs\":60000,\"ops\":[]}]}"
+ } ]
+}`)
+}
+
+func (s *hadoopService) showNameNode() string {
+ return fmt.Sprintln(`
+{
+ "beans" : [ {
+ "name" : "Hadoop:service=NameNode,name=NameNodeInfo",
+ "modelerType" : "org.apache.hadoop.hdfs.server.namenode.FSNamesystem",
+ "UpgradeFinalized" : true,
+ "ClusterId" : "CID-5e691286-4de5-4dde-800b-c02a7a8bf44a",
+ "Version" : "`, s.Version, `, r15ecc87ccf4a0228f35af08fc56de536e6ce657a",
+ "Used" : 327680,
+ "Free" : 14100385792,
+ "Safemode" : "",
+ "NonDfsUsedSpace" : 26982887424,
+ "PercentUsed" : 7.975932E-4,
+ "BlockPoolUsedSpace" : 327680,
+ "PercentBlockPoolUsed" : 7.975932E-4,
+ "PercentRemaining" : 34.321205,
+ "CacheCapacity" : 0,
+ "CacheUsed" : 0,
+ "TotalBlocks" : 31,
+ "TotalFiles" : 35,
+ "NumberOfMissingBlocks" : 0,
+ "NumberOfMissingBlocksWithReplicationFactorOne" : 0,
+ "LiveNodes" : "{\"4a41865ca8bc:50010\":{\"infoAddr\":\"172.17.0.2:50075\",\"infoSecureAddr\":\"172.17.0.2:0\",\"xferaddr\":\"172.17.0.2:50010\",\"lastContact\":0,\"usedSpace\":327680,\"adminState\":\"In Service\",\"nonDfsUsedSpace\":26982887424,\"capacity\":41083600896,\"numBlocks\":31,\"version\":\"`, s.Version, `\",\"used\":327680,\"remaining\":14100385792,\"blockScheduled\":0,\"blockPoolUsed\":327680,\"blockPoolUsedPercent\":7.975932E-4,\"volfails\":0}}",
+ "DeadNodes" : "{}",
+ "DecomNodes" : "{}",
+ "BlockPoolId" : "BP-1961412683-172.17.0.32-1450036414523",
+ "NameDirStatuses" : "{\"failed\":{},\"active\":{\"/tmp/hadoop-root/dfs/name\":\"IMAGE_AND_EDITS\"}}",
+ "NodeUsage" : "{\"nodeUsage\":{\"min\":\"0.00%\",\"median\":\"0.00%\",\"max\":\"0.00%\",\"stdDev\":\"0.00%\"}}",
+ "NameJournalStatus" : "[{\"stream\":\"EditLogFileOutputStream(/tmp/hadoop-root/dfs/name/current/edits_inprogress_0000000000000000192)\",\"manager\":\"FileJournalManager(root=/tmp/hadoop-root/dfs/name)\",\"required\":\"false\",\"disabled\":\"false\"}]",
+ "JournalTransactionInfo" : "{\"LastAppliedOrWrittenTxId\":\"192\",\"MostRecentCheckpointTxId\":\"191\"}",
+ "NNStarted" : `, getDayLetter(), `"07:58:36 EDT 2018",
+ "CompileInfo" : "2015-06-29T06:04Z by jenkins from (detached from 15ecc87)",
+ "CorruptFiles" : "[]",
+ "DistinctVersionCount" : 1,
+ "DistinctVersions" : [ {
+ "key" : "`, s.Version, `",
+ "value" : 1
+ } ],
+ "SoftwareVersion" : "`, s.Version, `",
+ "RollingUpgradeStatus" : null,
+ "Threads" : 33,
+ "Total" : 41083600896
+ } ]
+}`)
+}
+
+func (s *hadoopService) showDataNode() string {
+ return fmt.Sprintln(`
+{
+ "beans" : [ {
+ "name" : "Hadoop:service=DataNode,name=DataNodeInfo",
+ "modelerType" : "org.apache.hadoop.hdfs.server.datanode.DataNode",
+ "XceiverCount" : 1,
+ "DatanodeNetworkCounts" : [ ],
+ "Version" : "`, s.Version, `",
+ "RpcPort" : "50020",
+ "HttpPort" : null,
+ "NamenodeAddresses" : "{\"4a41865ca8bc\":\"BP-1961412683-172.17.0.32-1450036414523\"}",
+ "VolumeInfo" : "{\"/tmp/hadoop-root/dfs/data/current\":{\"freeSpace\":14075846656,\"usedSpace\":327680,\"reservedSpace\":0}}",
+ "ClusterId" : "CID-5e691286-4de5-4dde-800b-c02a7a8bf44a"
+ } ]
+}`)
+}
diff --git a/services/hadoop/hadoop_namenode.go b/services/hadoop/hadoop_namenode.go
new file mode 100644
index 000000000..ed5e3e2b2
--- /dev/null
+++ b/services/hadoop/hadoop_namenode.go
@@ -0,0 +1,123 @@
+/*
+* Honeytrap
+* Copyright (C) 2016-2017 DutchSec (https://dutchsec.com/)
+*
+* This program is free software; you can redistribute it and/or modify it under
+* the terms of the GNU Affero General Public License version 3 as published by the
+* Free Software Foundation.
+*
+* 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. See the GNU Affero General Public License for more
+* details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* version 3 along with this program in the file "LICENSE". If not, see
+* .
+*
+* See https://honeytrap.io/ for more details. All requests should be sent to
+* licensing@honeytrap.io
+*
+* The interactive user interfaces in modified source and object code versions
+* of this program must display Appropriate Legal Notices, as required under
+* Section 5 of the GNU Affero General Public License version 3.
+*
+* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
+* these Appropriate Legal Notices must retain the display of the "Powered by
+* Honeytrap" logo and retain the original copyright notice. If the display of the
+* logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
+* must display the words "Powered by Honeytrap" and retain the original copyright notice.
+ */
+
+package hadoop
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net"
+ "net/http"
+ "strings"
+ "time"
+
+ "github.com/honeytrap/honeytrap/event"
+ "github.com/honeytrap/honeytrap/services"
+)
+
+/*Example config:
+
+[service.hadoop_namenode]
+type="hadoop_namenode"
+version="2.7.1"
+os="Linux"
+
+[[port]]
+port="tcp/50070"
+services=["hadoop_namenode"]
+
+*/
+
+var (
+ _ = services.Register("hadoop_namenode", Hadoop)
+)
+
+func (s *hadoopService) HandleNameNode(conn net.Conn, req *http.Request) error {
+ hadoopRequest := hadoopRequestNameNode
+ s.ch.Send(event.New(
+ services.EventOptions,
+ event.Service("Hadoop NameNode"),
+ event.Category("hadoop_namenode"),
+ event.SourceAddr(conn.RemoteAddr()),
+ event.DestinationAddr(conn.LocalAddr()),
+ event.Custom("http.user-agent", req.UserAgent()),
+ event.Custom("http.method", req.Method),
+ event.Custom("http.proto", req.Proto),
+ event.Custom("http.host", req.Host),
+ event.Custom("http.url", req.URL.String()),
+ event.Custom("http.request", req.RequestURI),
+ ))
+
+ if req.URL.Path != "/jmx" {
+ resp := http.Response{
+ StatusCode: http.StatusNotFound,
+ Status: http.StatusText(http.StatusNotFound),
+ Proto: req.Proto,
+ ProtoMajor: req.ProtoMajor,
+ ProtoMinor: req.ProtoMinor,
+ Request: req,
+ Header: map[string][]string{
+ "Cache-Control": []string{"must-revalidate,no-cache,no-store"},
+ "Date": []string{time.Now().Format(http.TimeFormat)},
+ "Pragma": []string{"no-cache"},
+ "Content-Type": []string{"text/html; charset=iso-8859-1"},
+ "Content-length": []string{fmt.Sprintf("%d", len(s.htmlErrorPage(req.URL.Path)))},
+ "Server": []string{"Jetty(6.1.26)"},
+ },
+ }
+ resp.Body = ioutil.NopCloser(strings.NewReader(s.htmlErrorPage(req.URL.Path)))
+ return resp.Write(conn)
+ }
+
+ resp := http.Response{
+ StatusCode: http.StatusOK,
+ Status: http.StatusText(http.StatusOK),
+ Proto: req.Proto,
+ ProtoMajor: req.ProtoMajor,
+ ProtoMinor: req.ProtoMinor,
+ Request: req,
+ Header: map[string][]string{
+ "Cache-Control": []string{"no-cache"},
+ "Expires": []string{time.Now().Format(http.TimeFormat)},
+ "Date": []string{time.Now().Format(http.TimeFormat)},
+ "Pragma": []string{"no-cache"},
+ "Content-Type": []string{"application/json; charset=utf-8"},
+ "Access-Control-Allow-Methods": []string{req.Method},
+ "Access-Control-Allow-Origin": []string{"*"},
+ "Transfer-Encoding": []string{"chunked"},
+ "Server": []string{"Jetty(6.1.26)"},
+ },
+ }
+
+ resp.Body = ioutil.NopCloser(strings.NewReader(s.ShowRequest(req, hadoopRequest)))
+
+ return resp.Write(conn)
+}