better messages when the user modifies the .authorized_keys file from
within the session.
This commit is contained in:
parent
d109c72f66
commit
d134f1e944
@ -329,9 +329,12 @@ func main() {
|
|||||||
|
|
||||||
// Authentiocation
|
// Authentiocation
|
||||||
|
|
||||||
authorizedKeys := NewAuthorizedPublicKeys(authorizedKeysFile)
|
authorizedKeys, err := NewAuthorizedPublicKeys(authorizedKeysFile)
|
||||||
|
if err != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
// initial check
|
// initial check
|
||||||
pubkeys := authorizedKeys.Parse()
|
pubkeys, _ := authorizedKeys.Parse()
|
||||||
if len(pubkeys) == 0 {
|
if len(pubkeys) == 0 {
|
||||||
log.Printf("No public keys found in '%s', exiting", authorizedKeysFile)
|
log.Printf("No public keys found in '%s', exiting", authorizedKeysFile)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
@ -26,15 +26,16 @@ func publicKeyHandler(ctx ssh.Context, key gossh.PublicKey, authorizedKey gossh.
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func readSshPublicKeys(fileName string) ([]ssh.PublicKey, error) {
|
func readSshPublicKeys(fileName string) ([]ssh.PublicKey, []string, error) {
|
||||||
file, err := os.Open(fileName)
|
file, err := os.Open(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to open file: '%s': %s", fileName, err)
|
return nil, nil, fmt.Errorf("Failed to open file: '%s': %s", fileName, err)
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
res := make([]ssh.PublicKey, 0)
|
res := make([]ssh.PublicKey, 0)
|
||||||
scanner := bufio.NewScanner(file)
|
scanner := bufio.NewScanner(file)
|
||||||
|
var errorKeys []string
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
lineText := scanner.Text()
|
lineText := scanner.Text()
|
||||||
ind := strings.Index(lineText, "#")
|
ind := strings.Index(lineText, "#")
|
||||||
@ -49,12 +50,13 @@ func readSshPublicKeys(fileName string) ([]ssh.PublicKey, error) {
|
|||||||
line := []byte(lineText)
|
line := []byte(lineText)
|
||||||
parsedKey, _, _, _, err := ssh.ParseAuthorizedKey(line)
|
parsedKey, _, _, _, err := ssh.ParseAuthorizedKey(line)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
errorKeys = append(errorKeys, lineText)
|
||||||
log.Printf("Failed to parse authorized key: %v", lineText)
|
log.Printf("Failed to parse authorized key: %v", lineText)
|
||||||
} else {
|
} else {
|
||||||
res = append(res, parsedKey)
|
res = append(res, parsedKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, errorKeys, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthorizedPublicKeys struct {
|
type AuthorizedPublicKeys struct {
|
||||||
@ -63,18 +65,18 @@ type AuthorizedPublicKeys struct {
|
|||||||
publicKeys []ssh.PublicKey
|
publicKeys []ssh.PublicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAuthorizedPublicKeys(authorizedKeysFile string) *AuthorizedPublicKeys {
|
func NewAuthorizedPublicKeys(authorizedKeysFile string) (*AuthorizedPublicKeys, error) {
|
||||||
pubkeys := AuthorizedPublicKeys{
|
pubkeys := AuthorizedPublicKeys{
|
||||||
authorizedKeysFile: authorizedKeysFile,
|
authorizedKeysFile: authorizedKeysFile,
|
||||||
mutex: sync.Mutex{},
|
mutex: sync.Mutex{},
|
||||||
publicKeys: nil,
|
publicKeys: nil,
|
||||||
}
|
}
|
||||||
|
pubkeys.publicKeys, _ = pubkeys.Parse()
|
||||||
|
if len(pubkeys.publicKeys) == 0 {
|
||||||
|
return nil, fmt.Errorf("No valid public keys found, login is impossible, exiting")
|
||||||
|
}
|
||||||
go pubkeys.monitorAuthorizedKeysFile(authorizedKeysFile)
|
go pubkeys.monitorAuthorizedKeysFile(authorizedKeysFile)
|
||||||
return &pubkeys
|
return &pubkeys, nil
|
||||||
}
|
|
||||||
|
|
||||||
func (pubkeys *AuthorizedPublicKeys) notifyUsers(message string) {
|
|
||||||
session.MessageUsers(message)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pubkeys *AuthorizedPublicKeys) setPubKeys(keys []ssh.PublicKey) {
|
func (pubkeys *AuthorizedPublicKeys) setPubKeys(keys []ssh.PublicKey) {
|
||||||
@ -106,30 +108,34 @@ func (pubkeys *AuthorizedPublicKeys) monitorAuthorizedKeysFile(authorizedPublicK
|
|||||||
select {
|
select {
|
||||||
case event, ok := <-watcher.Events:
|
case event, ok := <-watcher.Events:
|
||||||
if !ok {
|
if !ok {
|
||||||
pubkeys.notifyUsers(
|
session.MessageUsers(
|
||||||
fmt.Sprintf("Watching authorized keys file '%s' stopped", authorizedPublicKeysFile))
|
fmt.Sprintf("Watching authorized keys file '%s' stopped", authorizedPublicKeysFile))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
base := filepath.Base(event.Name)
|
base := filepath.Base(event.Name)
|
||||||
log.Println("CHANGE " + base + " " + authorizedPublicKeysFile + " " + filepath.Base(authorizedPublicKeysFile))
|
log.Println("CHANGE " + base + " " + authorizedPublicKeysFile + " " + filepath.Base(authorizedPublicKeysFile))
|
||||||
if base == filepath.Base(authorizedPublicKeysFile) {
|
if base == filepath.Base(authorizedPublicKeysFile) {
|
||||||
keys := pubkeys.Parse()
|
keys, errorKeys := pubkeys.Parse()
|
||||||
|
for _, errorKey := range errorKeys {
|
||||||
|
session.MessageUsers(fmt.Sprintf("Public key '%s' is invalid", errorKey))
|
||||||
|
}
|
||||||
|
|
||||||
if len(keys) == 0 {
|
if len(keys) == 0 {
|
||||||
pubkeys.notifyUsers(
|
session.MessageUsers(
|
||||||
fmt.Sprintf("Authorized keys file '%s' does not contain any valid keys, using last known configuration", authorizedPublicKeysFile))
|
fmt.Sprintf("Authorized keys file '%s' does not exist or does not contain any valid keys, using last known configuration", authorizedPublicKeysFile))
|
||||||
} else {
|
} else {
|
||||||
pubkeys.notifyUsers(fmt.Sprintf("Updated authorized keys, now %d valid keys", len(keys)))
|
session.MessageUsers(fmt.Sprintf("Updated authorized keys, now %d valid key(s)", len(keys)))
|
||||||
pubkeys.setPubKeys(keys)
|
pubkeys.setPubKeys(keys)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case err, ok := <-watcher.Errors:
|
case err, ok := <-watcher.Errors:
|
||||||
if ok {
|
if ok {
|
||||||
pubkeys.notifyUsers(fmt.Sprintf(
|
session.MessageUsers(fmt.Sprintf(
|
||||||
"Watching authorized keys file '%s' stopped",
|
"Watching authorized keys file '%s' stopped",
|
||||||
pubkeys.authorizedKeysFile))
|
pubkeys.authorizedKeysFile))
|
||||||
}
|
}
|
||||||
pubkeys.notifyUsers(fmt.Sprintf(
|
session.MessageUsers(fmt.Sprintf(
|
||||||
"Watching authorized keys file '%s' stopped: %v",
|
"Watching authorized keys file '%s' stopped: %v",
|
||||||
pubkeys.authorizedKeysFile, err))
|
pubkeys.authorizedKeysFile, err))
|
||||||
return
|
return
|
||||||
@ -137,24 +143,24 @@ func (pubkeys *AuthorizedPublicKeys) monitorAuthorizedKeysFile(authorizedPublicK
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pubkeys *AuthorizedPublicKeys) Parse() []ssh.PublicKey {
|
func (pubkeys *AuthorizedPublicKeys) Parse() ([]ssh.PublicKey, []string) {
|
||||||
if pubkeys.authorizedKeysFile == "" {
|
if pubkeys.authorizedKeysFile == "" {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
keys, err := readSshPublicKeys(pubkeys.authorizedKeysFile)
|
keys, errorKeys, err := readSshPublicKeys(pubkeys.authorizedKeysFile)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
log.Printf("Authorized keys file '%s' not found.", pubkeys.authorizedKeysFile)
|
log.Printf("Authorized keys file '%s' not found.", pubkeys.authorizedKeysFile)
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Public key authentication will not work since no public keys were found.")
|
log.Println("Public key authentication will not work since no public keys were found.")
|
||||||
}
|
}
|
||||||
return keys
|
return keys, errorKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
func (key *AuthorizedPublicKeys) authorize(ctx ssh.Context, userProvidedKey ssh.PublicKey) bool {
|
func (key *AuthorizedPublicKeys) authorize(ctx ssh.Context, userProvidedKey ssh.PublicKey) bool {
|
||||||
//
|
//
|
||||||
keys := key.Parse()
|
keys, _ := key.Parse()
|
||||||
if len(keys) == 0 {
|
if len(keys) == 0 {
|
||||||
keys = key.getPubKeys()
|
keys = key.getPubKeys()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user