SSHSecure/utils/func.go

144 lines
3.0 KiB
Go

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
}