1+ // Copyright 2014 The Gogs 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+
15package models
26
37import (
8+ "bufio"
49 "fmt"
10+ "io"
511 "os"
612 "os/exec"
713 "path/filepath"
14+ "strings"
15+ "sync"
816 "time"
917
1018 "github.com/Unknwon/com"
1119)
1220
1321var (
22+ sshOpLocker = sync.Mutex {}
1423 //publicKeyRootPath string
15- sshPath string
16- appPath string
17- tmplPublicKey = "### autogenerated by gitgos, DO NOT EDIT\n " +
18- "command=\" %s serv key-%d\" ,no-port-forwarding," +
24+ sshPath string
25+ appPath string
26+ // "### autogenerated by gitgos, DO NOT EDIT\n"
27+ tmplPublicKey = "command=\" %s serv key-%d\" ,no-port-forwarding," +
1928 "no-X11-forwarding,no-agent-forwarding,no-pty %s\n "
2029)
2130
@@ -77,9 +86,69 @@ func AddPublicKey(key *PublicKey) error {
7786 return nil
7887}
7988
80- func DeletePublicKey (key * PublicKey ) error {
81- _ , err := orm .Delete (key )
82- return err
89+ // DeletePublicKey deletes SSH key information both in database and authorized_keys file.
90+ func DeletePublicKey (key * PublicKey ) (err error ) {
91+ if _ , err = orm .Delete (key ); err != nil {
92+ return err
93+ }
94+
95+ sshOpLocker .Lock ()
96+ defer sshOpLocker .Unlock ()
97+
98+ p := filepath .Join (sshPath , "authorized_keys" )
99+ tmpP := filepath .Join (sshPath , "authorized_keys.tmp" )
100+ fr , err := os .Open (p )
101+ if err != nil {
102+ return err
103+ }
104+ defer fr .Close ()
105+
106+ fw , err := os .Create (tmpP )
107+ if err != nil {
108+ return err
109+ }
110+ defer fw .Close ()
111+
112+ buf := bufio .NewReader (fr )
113+ for {
114+ line , errRead := buf .ReadString ('\n' )
115+ line = strings .TrimSpace (line )
116+
117+ if errRead != nil {
118+ if errRead != io .EOF {
119+ return errRead
120+ }
121+
122+ // Reached end of file, if nothing to read then break,
123+ // otherwise handle the last line.
124+ if len (line ) == 0 {
125+ break
126+ }
127+ }
128+
129+ // Found the line and copy rest of file.
130+ if strings .Contains (line , key .Content ) {
131+ if _ , err = io .Copy (fw , fr ); err != nil {
132+ return err
133+ }
134+ break
135+ }
136+
137+ // Still finding the line, copy the line that currently read.
138+ if _ , err = fw .WriteString (line + "\n " ); err != nil {
139+ return err
140+ }
141+
142+ if errRead == io .EOF {
143+ break
144+ }
145+ }
146+
147+ if err = os .Remove (p ); err != nil {
148+ return err
149+ }
150+
151+ return os .Rename (tmpP , p )
83152}
84153
85154func ListPublicKey (userId int64 ) ([]PublicKey , error ) {
@@ -89,11 +158,16 @@ func ListPublicKey(userId int64) ([]PublicKey, error) {
89158}
90159
91160func SaveAuthorizedKeyFile (key * PublicKey ) error {
161+ sshOpLocker .Lock ()
162+ defer sshOpLocker .Unlock ()
163+
92164 p := filepath .Join (sshPath , "authorized_keys" )
93165 f , err := os .OpenFile (p , os .O_CREATE | os .O_WRONLY | os .O_APPEND , 0600 )
94166 if err != nil {
95167 return err
96168 }
169+ defer f .Close ()
170+
97171 //os.Chmod(p, 0600)
98172 _ , err = f .WriteString (GenAuthorizedKey (key .Id , key .Content ))
99173 return err
0 commit comments