144 lines
3.0 KiB
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
|
||
|
}
|