mirror of
https://github.com/rwinkhart/libmutton.git
synced 2026-08-28 04:46:42 -04:00
Report panic details (stack trace w/args&stdin) to clients; drop synccycles.StringGen() (moved to go-boilerplate)
This commit is contained in:
@@ -5,7 +5,7 @@ go 1.25.5
|
|||||||
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.1.1-0.20251110055016-10ee4f91fcb6
|
github.com/rwinkhart/go-boilerplate v0.1.1-0.20251211171453-df1fb21b2366
|
||||||
github.com/rwinkhart/rcw v0.2.3
|
github.com/rwinkhart/rcw v0.2.3
|
||||||
golang.org/x/crypto v0.45.0
|
golang.org/x/crypto v0.45.0
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.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.1.1-0.20251110055016-10ee4f91fcb6 h1:tGGtw5Wr4laDrU7Ooe95g4E+O6c+oY18atamcMPaMY8=
|
github.com/rwinkhart/go-boilerplate v0.1.1-0.20251211171453-df1fb21b2366 h1:aKB7jcFstg11bRqDnjNzQIGM4+VA4JlE1HDNaPRpm8g=
|
||||||
github.com/rwinkhart/go-boilerplate v0.1.1-0.20251110055016-10ee4f91fcb6/go.mod h1:cnzIF45I0FCOvE4YIB+26pLCUx2kWyY2llKYZruNaRY=
|
github.com/rwinkhart/go-boilerplate v0.1.1-0.20251211171453-df1fb21b2366/go.mod h1:cnzIF45I0FCOvE4YIB+26pLCUx2kWyY2llKYZruNaRY=
|
||||||
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=
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime/debug"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/rwinkhart/go-boilerplate/back"
|
"github.com/rwinkhart/go-boilerplate/back"
|
||||||
@@ -33,6 +34,14 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allow reporting panic details to clients
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
fmt.Printf("{\"errMsg\":\"SERVER-SIDE PANIC OCCURRED!%sARGS: (%v)%sSTDIN: (%v)%sSTACK TRACE: %s\"}", global.FSSpace, os.Args, global.FSSpace, stdin, global.FSSpace, strings.ReplaceAll(strings.ReplaceAll(string(debug.Stack()), "\n", global.FSSpace), "\t", ""))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
switch args[1] {
|
switch args[1] {
|
||||||
case "fetch":
|
case "fetch":
|
||||||
// print all information needed for syncing to stdout for interpretation by the client
|
// print all information needed for syncing to stdout for interpretation by the client
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ func getRemoteDataFromClient(sshClient *ssh.Client) (map[string]int64, map[strin
|
|||||||
return nil, nil, nil, nil, 0, 0, errors.New("unable to unmarshal server fetch response: " + err.Error())
|
return nil, nil, nil, nil, 0, 0, errors.New("unable to unmarshal server fetch response: " + err.Error())
|
||||||
}
|
}
|
||||||
if fetchResp.ErrMsg != nil {
|
if fetchResp.ErrMsg != nil {
|
||||||
return nil, nil, nil, nil, 0, 0, errors.New("unable to complete fetch; server-side error occurred: " + *fetchResp.ErrMsg)
|
return nil, nil, nil, nil, 0, 0, errors.New("unable to complete fetch; server-side error occurred: " + strings.ReplaceAll(*fetchResp.ErrMsg, global.FSSpace, "\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
entryModMap := make(map[string]int64)
|
entryModMap := make(map[string]int64)
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ func ShearRemoteFromClient(vanityPath string, onlyShearAgeFile bool) error {
|
|||||||
return errors.New("unable to shear target remotely: " + err.Error())
|
return errors.New("unable to shear target remotely: " + err.Error())
|
||||||
}
|
}
|
||||||
if len(output) > 11 {
|
if len(output) > 11 {
|
||||||
return errors.New("unable to complete shear; server-side error occurred: " + string(output)[11:len(output)-2])
|
return errors.New("unable to complete shear; server-side error occurred: " + strings.ReplaceAll(string(output)[11:len(output)-2], global.FSSpace, "\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// close the SSH client
|
// close the SSH client
|
||||||
@@ -100,7 +100,7 @@ func RenameRemoteFromClient(oldVanityPath, newVanityPath string) error {
|
|||||||
return errors.New("unable to rename target remotely: " + err.Error())
|
return errors.New("unable to rename target remotely: " + err.Error())
|
||||||
}
|
}
|
||||||
if len(output) > 11 {
|
if len(output) > 11 {
|
||||||
return errors.New("unable to complete rename; server-side error occurred: " + string(output)[11:len(output)-2])
|
return errors.New("unable to complete rename; server-side error occurred: " + strings.ReplaceAll(string(output)[11:len(output)-2], global.FSSpace, "\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// close the SSH client
|
// close the SSH client
|
||||||
@@ -141,7 +141,7 @@ func AddFolderRemoteFromClient(vanityPath string) error {
|
|||||||
return errors.New("unable to add folder remotely: " + err.Error())
|
return errors.New("unable to add folder remotely: " + err.Error())
|
||||||
}
|
}
|
||||||
if len(output) > 11 {
|
if len(output) > 11 {
|
||||||
return errors.New("unable to complete addfolder; server-side error occurred: " + string(output)[11:len(output)-2])
|
return errors.New("unable to complete addfolder; server-side error occurred: " + strings.ReplaceAll(string(output)[11:len(output)-2], global.FSSpace, "\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// close the SSH client
|
// close the SSH client
|
||||||
|
|||||||
+4
-2
@@ -6,9 +6,11 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/rwinkhart/go-boilerplate/back"
|
"github.com/rwinkhart/go-boilerplate/back"
|
||||||
|
"github.com/rwinkhart/go-boilerplate/stringy"
|
||||||
"github.com/rwinkhart/libmutton/global"
|
"github.com/rwinkhart/libmutton/global"
|
||||||
"github.com/rwinkhart/libmutton/syncclient"
|
"github.com/rwinkhart/libmutton/syncclient"
|
||||||
"github.com/rwinkhart/libmutton/synccommon"
|
"github.com/rwinkhart/libmutton/synccommon"
|
||||||
@@ -24,7 +26,7 @@ func DeviceIDGen(oldDeviceID, prefix string) (string, string, string, error) {
|
|||||||
if prefix == "" {
|
if prefix == "" {
|
||||||
prefix, _ = os.Hostname()
|
prefix, _ = os.Hostname()
|
||||||
}
|
}
|
||||||
newDeviceID := prefix + "-" + StringGen(rand.Intn(32)+48, 0.2, 1) + "-" + strconv.FormatInt(time.Now().Unix(), 10)
|
newDeviceID := prefix + "-" + stringy.StringGen(rand.Intn(32)+48, 0.2, 1) + "-" + strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
|
|
||||||
// create new device ID file (locally)
|
// create new device ID file (locally)
|
||||||
newDeviceIDPath := global.ConfigDir + global.PathSeparator + "devices" + global.PathSeparator + newDeviceID
|
newDeviceIDPath := global.ConfigDir + global.PathSeparator + "devices" + global.PathSeparator + newDeviceID
|
||||||
@@ -68,7 +70,7 @@ func DeviceIDGen(oldDeviceID, prefix string) (string, string, string, error) {
|
|||||||
}
|
}
|
||||||
if registerResp.ErrMsg != nil {
|
if registerResp.ErrMsg != nil {
|
||||||
cleanupOnFail()
|
cleanupOnFail()
|
||||||
return "", "", "", errors.New("unable to complete register; server-side error occurred: " + *registerResp.ErrMsg)
|
return "", "", "", errors.New("unable to complete register; server-side error occurred: " + strings.ReplaceAll(*registerResp.ErrMsg, global.FSSpace, "\n"))
|
||||||
}
|
}
|
||||||
_ = sshClient.Close() // ignore error; non-critical/unlikely/not much could be done about it
|
_ = sshClient.Close() // ignore error; non-critical/unlikely/not much could be done about it
|
||||||
|
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
package synccycles
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"math/big"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// StringGen generates a random string of a specified length and complexity.
|
|
||||||
// Requires: complexity (minimum percentage of special characters to be returned in the generated string; set to 0 to generate a simple string),
|
|
||||||
// complexCharsetLevel (1 = safe for filenames, 2 = safe for most password entries, 3 = safe only for well-made password entries)
|
|
||||||
func StringGen(length int, complexity float64, complexCharsetLevel uint8) string {
|
|
||||||
var actualSpecialChars int // track the number of special characters in the generated string
|
|
||||||
var minSpecialChars int // track the minimum number of special characters to accept
|
|
||||||
var extendedCharset string // additions to character set used for complex strings
|
|
||||||
|
|
||||||
charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" // default character set used for all strings
|
|
||||||
const extendedCharsetFiles = "!#$%&+,-.;=@_~^()[]{}`'" // additional special characters for complex strings (safe in file names)
|
|
||||||
const extendedCharsetMostPassword = "*:><?|" // additional special characters for complex strings (NOT safe in file names)
|
|
||||||
const extendedCharsetSpecialPassword = "\"/\\" // additional special characters for complex strings (NOT safe in file names)
|
|
||||||
|
|
||||||
if complexity > 0 {
|
|
||||||
minSpecialChars = int(math.Round(float64(length) * complexity)) // determine minimum number of special characters to accept
|
|
||||||
switch complexCharsetLevel {
|
|
||||||
case 1:
|
|
||||||
extendedCharset = extendedCharsetFiles
|
|
||||||
case 2:
|
|
||||||
extendedCharset = extendedCharsetMostPassword + extendedCharsetFiles[:len(extendedCharsetFiles)-9]
|
|
||||||
case 3:
|
|
||||||
extendedCharset = extendedCharsetFiles + extendedCharsetMostPassword + extendedCharsetSpecialPassword
|
|
||||||
}
|
|
||||||
charset += extendedCharset
|
|
||||||
}
|
|
||||||
|
|
||||||
// loop until a string of the desired complexity is generated
|
|
||||||
for {
|
|
||||||
// generate a random string
|
|
||||||
result := make([]byte, length)
|
|
||||||
for i := range result {
|
|
||||||
val, _ := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))
|
|
||||||
result[i] = charset[val.Int64()]
|
|
||||||
}
|
|
||||||
|
|
||||||
// return early if the string is not complex
|
|
||||||
if complexity <= 0 {
|
|
||||||
return string(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// count the number of special characters in the generated string
|
|
||||||
for _, char := range string(result) {
|
|
||||||
if strings.ContainsRune(extendedCharset, char) {
|
|
||||||
actualSpecialChars++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the generated string if it contains enough special characters
|
|
||||||
if actualSpecialChars >= minSpecialChars {
|
|
||||||
return string(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset special character counter
|
|
||||||
fmt.Println("Regenerating string until desired complexity is achieved...")
|
|
||||||
actualSpecialChars = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user