You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

authorizedkeys.go 2.8KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package doctor
  5. import (
  6. "bufio"
  7. "bytes"
  8. "fmt"
  9. "os"
  10. "path/filepath"
  11. "strings"
  12. asymkey_model "code.gitea.io/gitea/models/asymkey"
  13. "code.gitea.io/gitea/modules/log"
  14. "code.gitea.io/gitea/modules/setting"
  15. )
  16. const tplCommentPrefix = `# gitea public key`
  17. func checkAuthorizedKeys(logger log.Logger, autofix bool) error {
  18. if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile {
  19. return nil
  20. }
  21. fPath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
  22. f, err := os.Open(fPath)
  23. if err != nil {
  24. if !autofix {
  25. logger.Critical("Unable to open authorized_keys file. ERROR: %v", err)
  26. return fmt.Errorf("Unable to open authorized_keys file. ERROR: %v", err)
  27. }
  28. logger.Warn("Unable to open authorized_keys. (ERROR: %v). Attempting to rewrite...", err)
  29. if err = asymkey_model.RewriteAllPublicKeys(); err != nil {
  30. logger.Critical("Unable to rewrite authorized_keys file. ERROR: %v", err)
  31. return fmt.Errorf("Unable to rewrite authorized_keys file. ERROR: %v", err)
  32. }
  33. }
  34. defer f.Close()
  35. linesInAuthorizedKeys := map[string]bool{}
  36. scanner := bufio.NewScanner(f)
  37. for scanner.Scan() {
  38. line := scanner.Text()
  39. if strings.HasPrefix(line, tplCommentPrefix) {
  40. continue
  41. }
  42. linesInAuthorizedKeys[line] = true
  43. }
  44. f.Close()
  45. // now we regenerate and check if there are any lines missing
  46. regenerated := &bytes.Buffer{}
  47. if err := asymkey_model.RegeneratePublicKeys(regenerated); err != nil {
  48. logger.Critical("Unable to regenerate authorized_keys file. ERROR: %v", err)
  49. return fmt.Errorf("Unable to regenerate authorized_keys file. ERROR: %v", err)
  50. }
  51. scanner = bufio.NewScanner(regenerated)
  52. for scanner.Scan() {
  53. line := scanner.Text()
  54. if strings.HasPrefix(line, tplCommentPrefix) {
  55. continue
  56. }
  57. if ok := linesInAuthorizedKeys[line]; ok {
  58. continue
  59. }
  60. if !autofix {
  61. logger.Critical(
  62. "authorized_keys file %q is out of date.\nRegenerate it with:\n\t\"%s\"\nor\n\t\"%s\"",
  63. fPath,
  64. "gitea admin regenerate keys",
  65. "gitea doctor --run authorized_keys --fix")
  66. return fmt.Errorf(`authorized_keys is out of date and should be regenerated with "gitea admin regenerate keys" or "gitea doctor --run authorized_keys --fix"`)
  67. }
  68. logger.Warn("authorized_keys is out of date. Attempting rewrite...")
  69. err = asymkey_model.RewriteAllPublicKeys()
  70. if err != nil {
  71. logger.Critical("Unable to rewrite authorized_keys file. ERROR: %v", err)
  72. return fmt.Errorf("Unable to rewrite authorized_keys file. ERROR: %v", err)
  73. }
  74. }
  75. return nil
  76. }
  77. func init() {
  78. Register(&Check{
  79. Title: "Check if OpenSSH authorized_keys file is up-to-date",
  80. Name: "authorized-keys",
  81. IsDefault: true,
  82. Run: checkAuthorizedKeys,
  83. Priority: 4,
  84. })
  85. }