mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Change all license headers to comply with REUSE specification. Fix #16132 Co-authored-by: flynnnnnnnnnn <flynnnnnnnnnn@github> Co-authored-by: John Olheiser <john.olheiser@gmail.com>
		
			
				
	
	
		
			97 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2020 The Gitea Authors. All rights reserved.
 | 
						|
// SPDX-License-Identifier: MIT
 | 
						|
 | 
						|
package doctor
 | 
						|
 | 
						|
import (
 | 
						|
	"bufio"
 | 
						|
	"bytes"
 | 
						|
	"context"
 | 
						|
	"fmt"
 | 
						|
	"os"
 | 
						|
	"path/filepath"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	asymkey_model "code.gitea.io/gitea/models/asymkey"
 | 
						|
	"code.gitea.io/gitea/modules/container"
 | 
						|
	"code.gitea.io/gitea/modules/log"
 | 
						|
	"code.gitea.io/gitea/modules/setting"
 | 
						|
)
 | 
						|
 | 
						|
const tplCommentPrefix = `# gitea public key`
 | 
						|
 | 
						|
func checkAuthorizedKeys(ctx context.Context, logger log.Logger, autofix bool) error {
 | 
						|
	if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
 | 
						|
	fPath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
 | 
						|
	f, err := os.Open(fPath)
 | 
						|
	if err != nil {
 | 
						|
		if !autofix {
 | 
						|
			logger.Critical("Unable to open authorized_keys file. ERROR: %v", err)
 | 
						|
			return fmt.Errorf("Unable to open authorized_keys file. ERROR: %w", err)
 | 
						|
		}
 | 
						|
		logger.Warn("Unable to open authorized_keys. (ERROR: %v). Attempting to rewrite...", err)
 | 
						|
		if err = asymkey_model.RewriteAllPublicKeys(); err != nil {
 | 
						|
			logger.Critical("Unable to rewrite authorized_keys file. ERROR: %v", err)
 | 
						|
			return fmt.Errorf("Unable to rewrite authorized_keys file. ERROR: %w", err)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	defer f.Close()
 | 
						|
 | 
						|
	linesInAuthorizedKeys := make(container.Set[string])
 | 
						|
 | 
						|
	scanner := bufio.NewScanner(f)
 | 
						|
	for scanner.Scan() {
 | 
						|
		line := scanner.Text()
 | 
						|
		if strings.HasPrefix(line, tplCommentPrefix) {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		linesInAuthorizedKeys.Add(line)
 | 
						|
	}
 | 
						|
	f.Close()
 | 
						|
 | 
						|
	// now we regenerate and check if there are any lines missing
 | 
						|
	regenerated := &bytes.Buffer{}
 | 
						|
	if err := asymkey_model.RegeneratePublicKeys(ctx, regenerated); err != nil {
 | 
						|
		logger.Critical("Unable to regenerate authorized_keys file. ERROR: %v", err)
 | 
						|
		return fmt.Errorf("Unable to regenerate authorized_keys file. ERROR: %w", err)
 | 
						|
	}
 | 
						|
	scanner = bufio.NewScanner(regenerated)
 | 
						|
	for scanner.Scan() {
 | 
						|
		line := scanner.Text()
 | 
						|
		if strings.HasPrefix(line, tplCommentPrefix) {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		if linesInAuthorizedKeys.Contains(line) {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		if !autofix {
 | 
						|
			logger.Critical(
 | 
						|
				"authorized_keys file %q is out of date.\nRegenerate it with:\n\t\"%s\"\nor\n\t\"%s\"",
 | 
						|
				fPath,
 | 
						|
				"gitea admin regenerate keys",
 | 
						|
				"gitea doctor --run authorized-keys --fix")
 | 
						|
			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"`)
 | 
						|
		}
 | 
						|
		logger.Warn("authorized_keys is out of date. Attempting rewrite...")
 | 
						|
		err = asymkey_model.RewriteAllPublicKeys()
 | 
						|
		if err != nil {
 | 
						|
			logger.Critical("Unable to rewrite authorized_keys file. ERROR: %v", err)
 | 
						|
			return fmt.Errorf("Unable to rewrite authorized_keys file. ERROR: %w", err)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func init() {
 | 
						|
	Register(&Check{
 | 
						|
		Title:     "Check if OpenSSH authorized_keys file is up-to-date",
 | 
						|
		Name:      "authorized-keys",
 | 
						|
		IsDefault: true,
 | 
						|
		Run:       checkAuthorizedKeys,
 | 
						|
		Priority:  4,
 | 
						|
	})
 | 
						|
}
 |