mirror of
https://github.com/rwinkhart/libmutton.git
synced 2026-08-27 20:36:29 -04:00
Allow custom priv key bytes on all platforms
This commit is contained in:
@@ -24,6 +24,19 @@ type CfgT struct {
|
|||||||
ClientSpecific *map[string]any `json:"clientSpecific"`
|
ClientSpecific *map[string]any `json:"clientSpecific"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load loads libmuttoncfg.json and returns the configuration.
|
||||||
|
func Load() (*CfgT, error) {
|
||||||
|
cfgBytes, err := os.ReadFile(global.CfgPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("unable to load libmuttoncfg.json: " + err.Error())
|
||||||
|
}
|
||||||
|
var cfg CfgT
|
||||||
|
if err = json.Unmarshal(cfgBytes, &cfg); err != nil {
|
||||||
|
return nil, errors.New("unable to unmarshal libmuttoncfg.json: " + err.Error())
|
||||||
|
}
|
||||||
|
return &cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Write writes cfg to libmuttoncfg.json.
|
// Write writes cfg to libmuttoncfg.json.
|
||||||
// If used in append mode, any nil values in the
|
// If used in append mode, any nil values in the
|
||||||
// input cfg will be substituted with the existing values.
|
// input cfg will be substituted with the existing values.
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
//go:build !ios
|
|
||||||
|
|
||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/rwinkhart/libmutton/global"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Load loads libmuttoncfg.json and returns the configuration.
|
|
||||||
func Load() (*CfgT, error) {
|
|
||||||
cfgBytes, err := os.ReadFile(global.CfgPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("unable to load libmuttoncfg.json: " + err.Error())
|
|
||||||
}
|
|
||||||
var cfg CfgT
|
|
||||||
if err = json.Unmarshal(cfgBytes, &cfg); err != nil {
|
|
||||||
return nil, errors.New("unable to unmarshal libmuttoncfg.json: " + err.Error())
|
|
||||||
}
|
|
||||||
return &cfg, nil
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
//go:build ios
|
|
||||||
|
|
||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/rwinkhart/libmutton/global"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Load loads libmuttoncfg.json and returns the configuration.
|
|
||||||
func Load() (*CfgT, error) {
|
|
||||||
cfgBytes, err := os.ReadFile(global.CfgPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("unable to load libmuttoncfg.json: " + err.Error())
|
|
||||||
}
|
|
||||||
var cfg CfgT
|
|
||||||
if err = json.Unmarshal(cfgBytes, &cfg); err != nil {
|
|
||||||
return nil, errors.New("unable to unmarshal libmuttoncfg.json: " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// iOS stores a relative path to account for the ever-changing app UUID
|
|
||||||
cfg.Libmutton.SSHKeyPath = new(global.SSHDir + *cfg.Libmutton.SSHKeyPath)
|
|
||||||
return &cfg, nil
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
module github.com/rwinkhart/libmutton
|
module github.com/rwinkhart/libmutton
|
||||||
|
|
||||||
go 1.26rc3
|
go 1.25.7
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/pkg/sftp v1.13.10
|
github.com/pkg/sftp v1.13.10
|
||||||
github.com/pquerna/otp v1.5.0
|
github.com/pquerna/otp v1.5.0
|
||||||
github.com/rwinkhart/go-boilerplate v0.2.2
|
github.com/rwinkhart/go-boilerplate v0.2.3-0.20260208035402-e1bb0012a781
|
||||||
github.com/rwinkhart/rcw v0.2.5
|
github.com/rwinkhart/rcw v0.2.5
|
||||||
golang.org/x/crypto v0.47.0
|
golang.org/x/crypto v0.47.0
|
||||||
golang.org/x/sys v0.40.0
|
golang.org/x/sys v0.40.0
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
|
github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
|
||||||
github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||||
github.com/rwinkhart/go-boilerplate v0.2.2 h1:SVHTAQU+HWFivtUnDBcfrgClJV5ZmHyFS7/uERh7NKU=
|
github.com/rwinkhart/go-boilerplate v0.2.3-0.20260208035402-e1bb0012a781 h1:kMAM0fkWGPa8WK7A4a9rMX2oD2Lv198zJoD9LCUAzOA=
|
||||||
github.com/rwinkhart/go-boilerplate v0.2.2/go.mod h1:/NVRKGslU20E5xU5YOgXzWxA6aa94BMtv5MtHRTb5Ek=
|
github.com/rwinkhart/go-boilerplate v0.2.3-0.20260208035402-e1bb0012a781/go.mod h1:QcUlr4SMgONRMKD965m8oTuCa6ZJVAc17w27Qopyr+s=
|
||||||
github.com/rwinkhart/go-winio v0.1.0 h1:b72agLW+dETGmhR3VbcbwnStfgKfc5AfgJOXBJDkaHg=
|
github.com/rwinkhart/go-winio v0.1.0 h1:b72agLW+dETGmhR3VbcbwnStfgKfc5AfgJOXBJDkaHg=
|
||||||
github.com/rwinkhart/go-winio v0.1.0/go.mod h1:ZWa7ssZJT30CCDGJ7fk/2SBTq9BIQrrVjrcss0UW2s0=
|
github.com/rwinkhart/go-winio v0.1.0/go.mod h1:ZWa7ssZJT30CCDGJ7fk/2SBTq9BIQrrVjrcss0UW2s0=
|
||||||
github.com/rwinkhart/peercred-mini v0.1.2 h1:4cGWDbv0whvLeVvbUdx84V/9p+2fS+DEXgrA1KxlRFo=
|
github.com/rwinkhart/peercred-mini v0.1.2 h1:4cGWDbv0whvLeVvbUdx84V/9p+2fS+DEXgrA1KxlRFo=
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package privkey
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var keyBytesProvider = func(sshKeyPath *string) ([]byte, error) {
|
||||||
|
if sshKeyPath != nil {
|
||||||
|
key, err := os.ReadFile(*sshKeyPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("unable to read private key: " + *sshKeyPath)
|
||||||
|
}
|
||||||
|
return key, nil
|
||||||
|
} else {
|
||||||
|
return nil, errors.New("unable to identify private key location (nil config)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var providerMutex sync.RWMutex
|
||||||
|
|
||||||
|
// GetBytes returns the SSH private key bytes.
|
||||||
|
// On iOS, it calls the provider function that was set by the iOS app
|
||||||
|
// using SetKeyBytesProvider or SetKeyBytes.
|
||||||
|
func GetBytes(sshKeyPath *string) ([]byte, error) {
|
||||||
|
providerMutex.RLock()
|
||||||
|
provider := keyBytesProvider
|
||||||
|
providerMutex.RUnlock()
|
||||||
|
|
||||||
|
if provider == nil {
|
||||||
|
return nil, errors.New("key bytes provider not set - call SetKeyBytes first")
|
||||||
|
}
|
||||||
|
|
||||||
|
keyBytes, err := provider(sshKeyPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("unable to get key bytes from provider: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(keyBytes) == 0 {
|
||||||
|
return nil, errors.New("provider returned empty key bytes")
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyBytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBytes allows the iOS app to directly set the SSH key bytes.
|
||||||
|
func SetBytes(keyBytes []byte) {
|
||||||
|
providerMutex.Lock()
|
||||||
|
defer providerMutex.Unlock()
|
||||||
|
keyBytesProvider = func(*string) ([]byte, error) {
|
||||||
|
return keyBytes, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/rwinkhart/libmutton/age"
|
"github.com/rwinkhart/libmutton/age"
|
||||||
"github.com/rwinkhart/libmutton/config"
|
"github.com/rwinkhart/libmutton/config"
|
||||||
"github.com/rwinkhart/libmutton/global"
|
"github.com/rwinkhart/libmutton/global"
|
||||||
|
"github.com/rwinkhart/libmutton/privkey"
|
||||||
"github.com/rwinkhart/libmutton/synccommon"
|
"github.com/rwinkhart/libmutton/synccommon"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
"golang.org/x/crypto/ssh/knownhosts"
|
"golang.org/x/crypto/ssh/knownhosts"
|
||||||
@@ -41,10 +42,10 @@ func GetSSHClient() (*ssh.Client, bool, *bool, *string, *string, error) {
|
|||||||
return nil, true, nil, nil, nil, nil
|
return nil, true, nil, nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// read private key
|
// get private key
|
||||||
key, err := os.ReadFile(*cfg.Libmutton.SSHKeyPath)
|
key, err := privkey.GetBytes(cfg.Libmutton.SSHKeyPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, nil, nil, nil, errors.New("unable to read private key: " + *cfg.Libmutton.SSHKeyPath)
|
return nil, false, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse private key
|
// parse private key
|
||||||
@@ -55,7 +56,7 @@ func GetSSHClient() (*ssh.Client, bool, *bool, *string, *string, error) {
|
|||||||
parsedKey, err = ssh.ParsePrivateKeyWithPassphrase(key, global.GetPassword("Enter password for your SSH keyfile:"))
|
parsedKey, err = ssh.ParsePrivateKeyWithPassphrase(key, global.GetPassword("Enter password for your SSH keyfile:"))
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, nil, nil, nil, errors.New("unable to parse private key: " + *cfg.Libmutton.SSHKeyPath)
|
return nil, false, nil, nil, nil, errors.New("unable to parse private key: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// read known hosts file
|
// read known hosts file
|
||||||
|
|||||||
Reference in New Issue
Block a user