yeah so as a temporary measure, i'm using ssh-keygen for now.
but i'll need to natively incorporate it still.
This commit is contained in:
parent
d7ffbea913
commit
7f98e7aa15
@ -31,7 +31,7 @@ import (
|
|||||||
"r00t2.io/sysutils/paths"
|
"r00t2.io/sysutils/paths"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConfig(config *[]byte) (bool, error) {
|
func ChkConfig(config *[]byte) (bool, error) {
|
||||||
var sysPaths []string
|
var sysPaths []string
|
||||||
var binPath string
|
var binPath string
|
||||||
var tmpConf *os.File
|
var tmpConf *os.File
|
||||||
|
138
dh/func_gen.go
138
dh/func_gen.go
@ -18,6 +18,17 @@
|
|||||||
|
|
||||||
package dh
|
package dh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Masterminds/semver"
|
||||||
|
"r00t2.io/sshsecure/moduli"
|
||||||
|
"r00t2.io/sshsecure/utils"
|
||||||
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
OpenSSH does prime generation and primality checking a *little* weird.
|
OpenSSH does prime generation and primality checking a *little* weird.
|
||||||
|
|
||||||
@ -35,4 +46,129 @@ package dh
|
|||||||
And that's why I'm a sad panda and porting moduli.c to native Golang.
|
And that's why I'm a sad panda and porting moduli.c to native Golang.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func SieveLarge()
|
// Generate builds a slice of moduli.Entry entries.
|
||||||
|
// TODO: DO THIS NATIVELY. Idealy with goroutines and a channel? buffer? for the primes and sieving.
|
||||||
|
func Generate() (moduliEntries []moduli.Entry, err error) {
|
||||||
|
|
||||||
|
var outFile *os.File
|
||||||
|
var filteredFile string
|
||||||
|
var raw []byte
|
||||||
|
var m *moduli.Moduli = new(moduli.Moduli)
|
||||||
|
|
||||||
|
if outFile, err = genPrimes(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if filteredFile, err = sieve(outFile); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if raw, err = ioutil.ReadFile(filteredFile); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = moduli.Unmarshal(raw, m); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
moduliEntries = m.Groups
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// genPrimes builds a slice of acceptable primes for sieve.
|
||||||
|
// TODO: DO THIS NATIVELY.
|
||||||
|
func genPrimes() (outFile *os.File, err error) {
|
||||||
|
|
||||||
|
var cmdStr []string = []string{"ssh-keygen", "-q"}
|
||||||
|
var cmdStr2 []string
|
||||||
|
var cmd *exec.Cmd
|
||||||
|
var sshVer utils.SshVerInfo
|
||||||
|
// These are various versions we need to compare against for determining features.
|
||||||
|
var ver81 *semver.Version
|
||||||
|
|
||||||
|
if outFile, err = ioutil.TempFile("", ".SSHSecure.moduli.*"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = outFile.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = os.Remove(outFile.Name()); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if sshVer, err = utils.GetSshVer(""); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// They changed the command syntax/options in 8.1. We need to determine if we're at or above that version or not.
|
||||||
|
if ver81, err = semver.NewVersion("8.1.0"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if sshVer.SemVer.Compare(ver81) >= 0 {
|
||||||
|
cmdStr2 = []string{
|
||||||
|
"-M", "generate",
|
||||||
|
"-O", "bits=4096",
|
||||||
|
outFile.Name(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cmdStr2 = []string{
|
||||||
|
"-b", "4096",
|
||||||
|
"-G", outFile.Name(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmdStr = append(cmdStr, cmdStr2...)
|
||||||
|
|
||||||
|
cmd = exec.Command(cmdStr[0], strings.Join(cmdStr[1:], " "))
|
||||||
|
if err = cmd.Run(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// sieve filters out unsuitable primes. See #1 and #2 in the comments at the top of this file.
|
||||||
|
// TODO: DO THIS NATIVELY.
|
||||||
|
func sieve(inFile *os.File) (newFile string, err error) {
|
||||||
|
|
||||||
|
var cmdStr []string = []string{"ssh-keygen", "-q"}
|
||||||
|
var cmdStr2 []string
|
||||||
|
var cmd *exec.Cmd
|
||||||
|
var sshVer utils.SshVerInfo
|
||||||
|
// These are various versions we need to compare against for determining features.
|
||||||
|
var ver81 *semver.Version
|
||||||
|
|
||||||
|
if sshVer, err = utils.GetSshVer(""); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
newFile = inFile.Name() + ".filtered"
|
||||||
|
|
||||||
|
// They changed the command syntax/options in 8.1. We need to determine if we're at or above that version or not.
|
||||||
|
if ver81, err = semver.NewVersion("8.1.0"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if sshVer.SemVer.Compare(ver81) >= 0 {
|
||||||
|
cmdStr2 = []string{
|
||||||
|
"-M", "screen",
|
||||||
|
"-O", "bits=4096",
|
||||||
|
"-f", inFile.Name(),
|
||||||
|
newFile,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cmdStr2 = []string{
|
||||||
|
"-T", newFile,
|
||||||
|
"-f", inFile.Name(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmdStr = append(cmdStr, cmdStr2...)
|
||||||
|
|
||||||
|
cmd = exec.Command(cmdStr[0], strings.Join(cmdStr[1:], " "))
|
||||||
|
if err = cmd.Run(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
1
go.mod
1
go.mod
@ -4,6 +4,7 @@ go 1.16
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Luzifer/go-dhparam v1.1.0
|
github.com/Luzifer/go-dhparam v1.1.0
|
||||||
|
github.com/Masterminds/semver v1.5.0
|
||||||
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a
|
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a
|
||||||
github.com/go-restruct/restruct v1.2.0-alpha
|
github.com/go-restruct/restruct v1.2.0-alpha
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
|
2
go.sum
2
go.sum
@ -1,5 +1,7 @@
|
|||||||
github.com/Luzifer/go-dhparam v1.1.0 h1:uJXDwqAVy1H4zWjmsYVmaa9yUD2Pm3SsdW4KU8d27zc=
|
github.com/Luzifer/go-dhparam v1.1.0 h1:uJXDwqAVy1H4zWjmsYVmaa9yUD2Pm3SsdW4KU8d27zc=
|
||||||
github.com/Luzifer/go-dhparam v1.1.0/go.mod h1:3Kuj59C67/G2EzQHjUzAryaAa70K5fqvStR2VkFLszU=
|
github.com/Luzifer/go-dhparam v1.1.0/go.mod h1:3Kuj59C67/G2EzQHjUzAryaAa70K5fqvStR2VkFLszU=
|
||||||
|
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||||
|
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a h1:saTgr5tMLFnmy/yg3qDTft4rE5DY2uJ/cCxCe3q0XTU=
|
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a h1:saTgr5tMLFnmy/yg3qDTft4rE5DY2uJ/cCxCe3q0XTU=
|
||||||
|
@ -24,14 +24,14 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
`time`
|
"time"
|
||||||
|
|
||||||
`github.com/Luzifer/go-dhparam`
|
"github.com/Luzifer/go-dhparam"
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewModuli returns a Moduli populated with Entry items.
|
// NewModuli returns a Moduli populated with Entry items.
|
||||||
func NewModuli(usePreGen ... bool) (m *Moduli, err error) {
|
func NewModuli(usePreGen ...bool) (m *Moduli, err error) {
|
||||||
|
|
||||||
var doPreGen bool
|
var doPreGen bool
|
||||||
|
|
||||||
@ -117,13 +117,13 @@ func Generate(m *Moduli) (err error) {
|
|||||||
var e Entry
|
var e Entry
|
||||||
|
|
||||||
e = Entry{
|
e = Entry{
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
Size: bitLen,
|
Size: bitLen,
|
||||||
Generator: uint8(generator),
|
Generator: uint8(generator),
|
||||||
/*
|
/*
|
||||||
Type: 0,
|
Type: 0,
|
||||||
Tests: 0,
|
Tests: 0,
|
||||||
Trials: 0,
|
Trials: 0,
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ func Generate(m *Moduli) (err error) {
|
|||||||
e.Modulus = *dh.P
|
e.Modulus = *dh.P
|
||||||
|
|
||||||
// TODO: https://stackoverflow.com/questions/18499352/golang-concurrency-how-to-append-to-the-same-slice-from-different-goroutines
|
// TODO: https://stackoverflow.com/questions/18499352/golang-concurrency-how-to-append-to-the-same-slice-from-different-goroutines
|
||||||
m.Params = append(m.Params, e)
|
m.Groups = append(m.Groups, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,13 +34,12 @@ var reSkipLine, _ = regexp.Compile(`^\s*(#.*)?$`)
|
|||||||
|
|
||||||
// Marshal returns the /etc/ssh/moduli format of m.
|
// Marshal returns the /etc/ssh/moduli format of m.
|
||||||
// Format of: Time Type Tests Tries Size Generator Modulus
|
// Format of: Time Type Tests Tries Size Generator Modulus
|
||||||
// TODO: remember to write newline at end
|
|
||||||
func (m *Moduli) Marshal() (bytesOut []byte, err error) {
|
func (m *Moduli) Marshal() (bytesOut []byte, err error) {
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
|
|
||||||
b.Write([]byte(header))
|
b.Write([]byte(header))
|
||||||
for _, i := range m.Params {
|
for _, i := range m.Groups {
|
||||||
line, err := i.marshalEntry()
|
line, err := i.marshalEntry()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -49,6 +48,8 @@ func (m *Moduli) Marshal() (bytesOut []byte, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.Write([]byte("\n"))
|
||||||
|
|
||||||
bytesOut = b.Bytes()
|
bytesOut = b.Bytes()
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -98,7 +99,7 @@ func Unmarshal(data []byte, m *Moduli) (err error) {
|
|||||||
entries = append(entries, e)
|
entries = append(entries, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Params = entries
|
m.Groups = entries
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -149,7 +150,7 @@ func (m *Moduli) Harden() (err error) {
|
|||||||
|
|
||||||
var entries []Entry
|
var entries []Entry
|
||||||
|
|
||||||
for _, e := range m.Params {
|
for _, e := range m.Groups {
|
||||||
|
|
||||||
e.Time = time.Now()
|
e.Time = time.Now()
|
||||||
|
|
||||||
@ -157,9 +158,9 @@ func (m *Moduli) Harden() (err error) {
|
|||||||
entries = append(entries, e)
|
entries = append(entries, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.Params = entries
|
m.Groups = entries
|
||||||
|
|
||||||
if len(m.Params) < recMinMod {
|
if len(m.Groups) < recMinMod {
|
||||||
err = errors.New("does not meet recommended minimum moduli")
|
err = errors.New("does not meet recommended minimum moduli")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -23,10 +23,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Moduli contains all data needed for generated /etc/ssh/moduli. of ModuliEntry entries.
|
// Moduli contains all data needed for generated /etc/ssh/moduli of Entry entries.
|
||||||
type Moduli struct {
|
type Moduli struct {
|
||||||
Header string
|
Header string
|
||||||
Params []Entry
|
Groups []Entry
|
||||||
}
|
}
|
||||||
|
|
||||||
// Entry is a struct reflecting the format of a single /etc/ssh/moduli entry. See moduli(5) for details.
|
// Entry is a struct reflecting the format of a single /etc/ssh/moduli entry. See moduli(5) for details.
|
||||||
|
143
utils/func.go
Normal file
143
utils/func.go
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Masterminds/semver"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetSshVer returns an SshVerInfo. If verStr is an empty string, get the version automatically.
|
||||||
|
func GetSshVer(verStr string) (ver SshVerInfo, err error) {
|
||||||
|
|
||||||
|
var newVerStr string
|
||||||
|
var sslVer OpenSslInfo
|
||||||
|
var sslVerStr string
|
||||||
|
var ptrn *regexp.Regexp
|
||||||
|
var matches []string
|
||||||
|
var verSlice [3]uint
|
||||||
|
var n int
|
||||||
|
var sver *semver.Version
|
||||||
|
|
||||||
|
if verStr == "" {
|
||||||
|
var out []byte
|
||||||
|
cmd := exec.Command("ssh", "-V")
|
||||||
|
if err = cmd.Run(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if out, err = cmd.Output(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
verStr = string(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ptrn, err = regexp.Compile(`^(?:Open|Sun_)SSH_(?P<sshver>[0-9.]+)(?:p?(?P<patchver>[0-9.]+))?,\s*(?P<sslverstr>.*)?$`); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
matches = ptrn.FindStringSubmatch(verStr)
|
||||||
|
|
||||||
|
// Reformat verStr to the combined version string.
|
||||||
|
newVerStr = fmt.Sprintf(
|
||||||
|
"%v.%v",
|
||||||
|
matches[ptrn.SubexpIndex("sshver")],
|
||||||
|
matches[ptrn.SubexpIndex("patchver")],
|
||||||
|
)
|
||||||
|
|
||||||
|
sslVerStr = matches[ptrn.SubexpIndex("sslverstr")]
|
||||||
|
|
||||||
|
if sslVer, err = GetSslVer(sslVerStr); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, s := range strings.Split(newVerStr, ".") {
|
||||||
|
if n, err = strconv.Atoi(s); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
verSlice[idx] = uint(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if sver, err = semver.NewVersion(newVerStr); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ver = SshVerInfo{
|
||||||
|
Major: verSlice[0],
|
||||||
|
Minor: verSlice[1],
|
||||||
|
Patch: verSlice[2],
|
||||||
|
Raw: verStr,
|
||||||
|
SslInfo: sslVer,
|
||||||
|
SemVer: *sver,
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSslVer returns an OpenSslInfo. If verStr is an empty string, get the version automatically.
|
||||||
|
func GetSslVer(verStr string) (ver OpenSslInfo, err error) {
|
||||||
|
|
||||||
|
var matches []string
|
||||||
|
var verSlice [3]uint
|
||||||
|
var newVerStr string
|
||||||
|
var ptrn *regexp.Regexp
|
||||||
|
var sver *semver.Version
|
||||||
|
// TODO: confirm the day is zero-padded.
|
||||||
|
var tfmt string = `02 Jan 2006`
|
||||||
|
var n int
|
||||||
|
var t time.Time
|
||||||
|
|
||||||
|
if verStr == "" {
|
||||||
|
var out []byte
|
||||||
|
cmd := exec.Command("openssl", "version")
|
||||||
|
if err = cmd.Run(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if out, err = cmd.Output(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
verStr = string(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ptrn, err = regexp.Compile(`^(?:Open|Sun_)SSL\s+(FIPS\s+)?(?P<sslver>[0-9.]+)(?P<sslrel>[A-Za-z]+)?\s+(?P<time>(?P<day>[0-9]{1,2})\s(?P<month>[A-Za-z]+)\s(?P<year>[0-9]{4}))$`); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
matches = ptrn.FindStringSubmatch(verStr)
|
||||||
|
|
||||||
|
for idx, s := range strings.Split(matches[ptrn.SubexpIndex("sslver")], ".") {
|
||||||
|
if n, err = strconv.Atoi(s); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
verSlice[idx] = uint(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if t, err = time.Parse(tfmt, matches[ptrn.SubexpIndex("time")]); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
newVerStr = fmt.Sprintf(
|
||||||
|
"%v-%v",
|
||||||
|
matches[ptrn.SubexpIndex("sslver")],
|
||||||
|
matches[ptrn.SubexpIndex("sslrel")],
|
||||||
|
)
|
||||||
|
|
||||||
|
if sver, err = semver.NewVersion(newVerStr); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ver = OpenSslInfo{
|
||||||
|
Major: verSlice[0],
|
||||||
|
Minor: verSlice[1],
|
||||||
|
Patch: verSlice[2],
|
||||||
|
Revision: matches[ptrn.SubexpIndex("sslrel")],
|
||||||
|
BuildDate: t,
|
||||||
|
Raw: verStr,
|
||||||
|
SemVer: *sver,
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
@ -2,9 +2,30 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Masterminds/semver"
|
||||||
)
|
)
|
||||||
|
|
||||||
type runInfo struct {
|
type runInfo struct {
|
||||||
TimeStarted time.Time
|
TimeStarted time.Time
|
||||||
Pid int
|
Pid int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SshVerInfo struct {
|
||||||
|
Major uint
|
||||||
|
Minor uint
|
||||||
|
Patch uint
|
||||||
|
Raw string
|
||||||
|
SemVer semver.Version
|
||||||
|
SslInfo OpenSslInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type OpenSslInfo struct {
|
||||||
|
Major uint
|
||||||
|
Minor uint
|
||||||
|
Patch uint
|
||||||
|
Revision string
|
||||||
|
BuildDate time.Time
|
||||||
|
Raw string
|
||||||
|
SemVer semver.Version
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user