mirror of
https://github.com/bettercap/bettercap
synced 2025-07-06 13:02:12 -07:00
new: api.rest is now on HTTPS (closes #5)
This commit is contained in:
parent
be570432ef
commit
47e814c9a9
4 changed files with 143 additions and 12 deletions
26
core/core.go
26
core/core.go
|
@ -2,7 +2,10 @@ package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"os/user"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,3 +23,26 @@ func Exec(executable string, args []string) (string, error) {
|
||||||
return strings.Trim(string(raw), "\r\n\t "), nil
|
return strings.Trim(string(raw), "\r\n\t "), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Exists(path string) bool {
|
||||||
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExpandPath(path string) (string, error) {
|
||||||
|
// Check if path is empty
|
||||||
|
if path != "" {
|
||||||
|
if strings.HasPrefix(path, "~") {
|
||||||
|
usr, err := user.Current()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// Replace only the first occurence of ~
|
||||||
|
path = strings.Replace(path, "~", usr.HomeDir, 1)
|
||||||
|
}
|
||||||
|
return filepath.Abs(path)
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
10
main.go
10
main.go
|
@ -30,11 +30,11 @@ func main() {
|
||||||
sess.Register(session_modules.NewRestAPI(sess))
|
sess.Register(session_modules.NewRestAPI(sess))
|
||||||
|
|
||||||
if err = sess.Start(); err != nil {
|
if err = sess.Start(); err != nil {
|
||||||
sess.Events.Log(session.FATAL, "%s", err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = sess.Run("events.stream on"); err != nil {
|
if err = sess.Run("events.stream on"); err != nil {
|
||||||
sess.Events.Log(session.FATAL, "%s", err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer sess.Close()
|
defer sess.Close()
|
||||||
|
@ -43,21 +43,21 @@ func main() {
|
||||||
for _, cmd := range strings.Split(*sess.Options.Commands, ";") {
|
for _, cmd := range strings.Split(*sess.Options.Commands, ";") {
|
||||||
cmd = strings.Trim(cmd, "\r\n\t ")
|
cmd = strings.Trim(cmd, "\r\n\t ")
|
||||||
if err = sess.Run(cmd); err != nil {
|
if err = sess.Run(cmd); err != nil {
|
||||||
sess.Events.Log(session.FATAL, "%s", err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if *sess.Options.Caplet != "" {
|
if *sess.Options.Caplet != "" {
|
||||||
if err = sess.RunCaplet(*sess.Options.Caplet); err != nil {
|
if err = sess.RunCaplet(*sess.Options.Caplet); err != nil {
|
||||||
sess.Events.Log(session.FATAL, "%s", err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for sess.Active {
|
for sess.Active {
|
||||||
line, err := sess.ReadLine()
|
line, err := sess.ReadLine()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sess.Events.Log(session.FATAL, "%s", err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if line == "" || line[0] == '#' {
|
if line == "" || line[0] == '#' {
|
||||||
|
|
|
@ -8,7 +8,9 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/evilsocket/bettercap-ng/core"
|
||||||
"github.com/evilsocket/bettercap-ng/session"
|
"github.com/evilsocket/bettercap-ng/session"
|
||||||
|
"github.com/evilsocket/bettercap-ng/tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RestAPI struct {
|
type RestAPI struct {
|
||||||
|
@ -16,6 +18,8 @@ type RestAPI struct {
|
||||||
server *http.Server
|
server *http.Server
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
|
certFile string
|
||||||
|
keyFile string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRestAPI(s *session.Session) *RestAPI {
|
func NewRestAPI(s *session.Session) *RestAPI {
|
||||||
|
@ -32,7 +36,7 @@ func NewRestAPI(s *session.Session) *RestAPI {
|
||||||
"Address to bind the API REST server to."))
|
"Address to bind the API REST server to."))
|
||||||
|
|
||||||
api.AddParam(session.NewIntParameter("api.rest.port",
|
api.AddParam(session.NewIntParameter("api.rest.port",
|
||||||
"8081",
|
"8083",
|
||||||
"Port to bind the API REST server to."))
|
"Port to bind the API REST server to."))
|
||||||
|
|
||||||
api.AddParam(session.NewStringParameter("api.rest.username",
|
api.AddParam(session.NewStringParameter("api.rest.username",
|
||||||
|
@ -40,6 +44,16 @@ func NewRestAPI(s *session.Session) *RestAPI {
|
||||||
"",
|
"",
|
||||||
"API authentication username."))
|
"API authentication username."))
|
||||||
|
|
||||||
|
api.AddParam(session.NewStringParameter("api.rest.certificate",
|
||||||
|
"~/.bettercap-ng.certificate.pem",
|
||||||
|
"",
|
||||||
|
"API TLS certificate."))
|
||||||
|
|
||||||
|
api.AddParam(session.NewStringParameter("api.rest.key",
|
||||||
|
"~/.bettercap-ng.key.pem",
|
||||||
|
"",
|
||||||
|
"API TLS key"))
|
||||||
|
|
||||||
api.AddParam(session.NewStringParameter("api.rest.password",
|
api.AddParam(session.NewStringParameter("api.rest.password",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
|
@ -229,6 +243,24 @@ func (api *RestAPI) Start() error {
|
||||||
port = v.(int)
|
port = v.(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err, v := api.Param("api.rest.certificate").Get(api.Session); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
api.certFile = v.(string)
|
||||||
|
if api.certFile, err = core.ExpandPath(api.certFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err, v := api.Param("api.rest.key").Get(api.Session); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
api.keyFile = v.(string)
|
||||||
|
if api.keyFile, err = core.ExpandPath(api.keyFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err, v := api.Param("api.rest.username").Get(api.Session); err != nil {
|
if err, v := api.Param("api.rest.username").Get(api.Session); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
|
@ -247,16 +279,25 @@ func (api *RestAPI) Start() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if core.Exists(api.certFile) == false || core.Exists(api.keyFile) == false {
|
||||||
|
api.Session.Events.Log(session.INFO, "Generating RSA key to %s", api.keyFile)
|
||||||
|
api.Session.Events.Log(session.INFO, "Generating TLS certificate to %s", api.certFile)
|
||||||
|
if err := tls.Generate(api.certFile, api.keyFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
api.Session.Events.Log(session.INFO, "Loading RSA key from %s", api.keyFile)
|
||||||
|
api.Session.Events.Log(session.INFO, "Loading TLS certificate from %s", api.certFile)
|
||||||
|
}
|
||||||
|
|
||||||
if api.Running() == false {
|
if api.Running() == false {
|
||||||
api.SetRunning(true)
|
api.SetRunning(true)
|
||||||
|
|
||||||
api.server.Addr = fmt.Sprintf("%s:%d", address, port)
|
api.server.Addr = fmt.Sprintf("%s:%d", address, port)
|
||||||
go func() {
|
go func() {
|
||||||
|
api.Session.Events.Log(session.INFO, "API server starting on https://%s", api.server.Addr)
|
||||||
api.Session.Events.Log(session.INFO, "API server starting on http://%s", api.server.Addr)
|
err := api.server.ListenAndServeTLS(api.certFile, api.keyFile)
|
||||||
err := api.server.ListenAndServe()
|
if err != nil && err != http.ErrServerClosed {
|
||||||
if err != nil {
|
panic(err)
|
||||||
api.Session.Events.Log(session.ERROR, "%s", err)
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
64
tls/cert.go
Normal file
64
tls/cert.go
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
package tls
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/pem"
|
||||||
|
"math/big"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Generate(certPath string, keyPath string) error {
|
||||||
|
keyfile, err := os.Create(keyPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer keyfile.Close()
|
||||||
|
|
||||||
|
certfile, err := os.Create(certPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer certfile.Close()
|
||||||
|
|
||||||
|
priv, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
notBefore := time.Now()
|
||||||
|
notAfter := notBefore.Add(time.Duration(24*365) * time.Hour)
|
||||||
|
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||||
|
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
template := x509.Certificate{
|
||||||
|
SerialNumber: serialNumber,
|
||||||
|
Subject: pkix.Name{
|
||||||
|
CommonName: "bettercap-ng",
|
||||||
|
Organization: []string{"bettercap-ng"},
|
||||||
|
OrganizationalUnit: []string{"RSA key generation module"},
|
||||||
|
},
|
||||||
|
NotBefore: notBefore,
|
||||||
|
NotAfter: notAfter,
|
||||||
|
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
||||||
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
|
||||||
|
BasicConstraintsValid: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
cert_raw, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := pem.Encode(keyfile, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pem.Encode(certfile, &pem.Block{Type: "CERTIFICATE", Bytes: cert_raw})
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue