@@ -17,30 +17,14 @@ import (
1717 "code.gitea.io/gitea/modules/log"
1818 "code.gitea.io/gitea/modules/setting"
1919 "code.gitea.io/gitea/modules/util"
20- )
2120
22- // _____ __ .__ .__ .___
23- // / _ \ __ ___/ |_| |__ ___________|__|_______ ____ __| _/
24- // / /_\ \| | \ __\ | \ / _ \_ __ \ \___ // __ \ / __ |
25- // / | \ | /| | | Y ( <_> ) | \/ |/ /\ ___// /_/ |
26- // \____|__ /____/ |__| |___| /\____/|__| |__/_____ \\___ >____ |
27- // \/ \/ \/ \/ \/
28- // ____ __.
29- // | |/ _|____ ___.__. ______
30- // | <_/ __ < | |/ ___/
31- // | | \ ___/\___ |\___ \
32- // |____|__ \___ > ____/____ >
33- // \/ \/\/ \/
34- //
35- // This file contains functions for creating authorized_keys files
36- //
37- // There is a dependence on the database within RegeneratePublicKeys however most of these functions probably belong in a module
38-
39- const (
40- tplCommentPrefix = `# gitea public key`
41- tplPublicKey = tplCommentPrefix + "\n " + `command=%s,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,no-user-rc,restrict %s` + "\n "
21+ "golang.org/x/crypto/ssh"
4222)
4323
24+ // AuthorizedStringCommentPrefix is a magic tag
25+ // some functions like RegeneratePublicKeys needs this tag to skip the keys generated by Gitea, while keep other keys
26+ const AuthorizedStringCommentPrefix = `# gitea public key`
27+
4428var sshOpLocker sync.Mutex
4529
4630func WithSSHOpLocker (f func () error ) error {
@@ -50,7 +34,8 @@ func WithSSHOpLocker(f func() error) error {
5034}
5135
5236// AuthorizedStringForKey creates the authorized keys string appropriate for the provided key
53- func AuthorizedStringForKey (key * PublicKey ) string {
37+ func AuthorizedStringForKey (key * PublicKey ) (string , error ) {
38+ const tpl = AuthorizedStringCommentPrefix + "\n " + `command=%s,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,no-user-rc,restrict %s %s` + "\n "
5439 sb := & strings.Builder {}
5540 _ = setting .SSH .AuthorizedKeysCommandTemplateTemplate .Execute (sb , map [string ]any {
5641 "AppPath" : util .ShellEscape (setting .AppPath ),
@@ -60,7 +45,14 @@ func AuthorizedStringForKey(key *PublicKey) string {
6045 "Key" : key ,
6146 })
6247
63- return fmt .Sprintf (tplPublicKey , util .ShellEscape (sb .String ()), key .Content )
48+ pubKey , _ , _ , _ , err := ssh .ParseAuthorizedKey ([]byte (key .Content ))
49+ if err != nil {
50+ return "" , fmt .Errorf ("invalid public key: %w" , err )
51+ }
52+ sshCommandEscaped := util .ShellEscape (sb .String ())
53+ sshKeyMarshalled := strings .TrimSpace (string (ssh .MarshalAuthorizedKey (pubKey )))
54+ sshKeyComment := fmt .Sprintf ("user-%d" , key .OwnerID )
55+ return fmt .Sprintf (tpl , sshCommandEscaped , sshKeyMarshalled , sshKeyComment ), nil
6456}
6557
6658// appendAuthorizedKeysToFile appends new SSH keys' content to authorized_keys file.
@@ -112,7 +104,12 @@ func appendAuthorizedKeysToFile(keys ...*PublicKey) error {
112104 if key .Type == KeyTypePrincipal {
113105 continue
114106 }
115- if _ , err = f .WriteString (key .AuthorizedString ()); err != nil {
107+ authorizedString , err := AuthorizedStringForKey (key )
108+ if err != nil {
109+ log .Debug ("AuthorizedStringForKey(%s): %v" , key , err )
110+ continue
111+ }
112+ if _ , err = f .WriteString (authorizedString ); err != nil {
116113 return err
117114 }
118115 }
@@ -122,7 +119,13 @@ func appendAuthorizedKeysToFile(keys ...*PublicKey) error {
122119// RegeneratePublicKeys regenerates the authorized_keys file
123120func RegeneratePublicKeys (ctx context.Context , t io.StringWriter ) error {
124121 if err := db .GetEngine (ctx ).Where ("type != ?" , KeyTypePrincipal ).Iterate (new (PublicKey ), func (idx int , bean any ) (err error ) {
125- _ , err = t .WriteString ((bean .(* PublicKey )).AuthorizedString ())
122+ key := bean .(* PublicKey )
123+ authorizedString , err := AuthorizedStringForKey (key )
124+ if err != nil {
125+ log .Debug ("AuthorizedStringForKey(%s): %v" , key , err )
126+ return nil
127+ }
128+ _ , err = t .WriteString (authorizedString )
126129 return err
127130 }); err != nil {
128131 return err
@@ -144,7 +147,7 @@ func RegeneratePublicKeys(ctx context.Context, t io.StringWriter) error {
144147 scanner := bufio .NewScanner (f )
145148 for scanner .Scan () {
146149 line := scanner .Text ()
147- if strings .HasPrefix (line , tplCommentPrefix ) {
150+ if strings .HasPrefix (line , AuthorizedStringCommentPrefix ) {
148151 scanner .Scan ()
149152 continue
150153 }
0 commit comments