aboutsummaryrefslogtreecommitdiffstats
path: root/models/ssh_key.go
diff options
context:
space:
mode:
Diffstat (limited to 'models/ssh_key.go')
-rw-r--r--models/ssh_key.go101
1 files changed, 15 insertions, 86 deletions
diff --git a/models/ssh_key.go b/models/ssh_key.go
index 4fbc2e8d47..0925b9ba76 100644
--- a/models/ssh_key.go
+++ b/models/ssh_key.go
@@ -5,12 +5,10 @@
package models
import (
- "bufio"
"encoding/base64"
"encoding/binary"
"errors"
"fmt"
- "io"
"io/ioutil"
"math/big"
"os"
@@ -24,6 +22,7 @@ import (
"github.com/go-xorm/xorm"
"golang.org/x/crypto/ssh"
+ "github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/process"
"github.com/gogits/gogs/modules/setting"
@@ -457,96 +456,20 @@ func ListPublicKeys(uid int64) ([]*PublicKey, error) {
return keys, x.Where("owner_id = ?", uid).Find(&keys)
}
-// rewriteAuthorizedKeys finds and deletes corresponding line in authorized_keys file.
-func rewriteAuthorizedKeys(key *PublicKey, p, tmpP string) error {
- fr, err := os.Open(p)
- if err != nil {
- return err
- }
- defer fr.Close()
-
- fw, err := os.OpenFile(tmpP, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
- if err != nil {
- return err
- }
- defer fw.Close()
-
- isFound := false
- keyword := fmt.Sprintf("key-%d", key.ID)
- buf := bufio.NewReader(fr)
- for {
- line, errRead := buf.ReadString('\n')
- line = strings.TrimSpace(line)
-
- if errRead != nil {
- if errRead != io.EOF {
- return errRead
- }
-
- // Reached end of file, if nothing to read then break,
- // otherwise handle the last line.
- if len(line) == 0 {
- break
- }
- }
-
- // Found the line and copy rest of file.
- if !isFound && strings.Contains(line, keyword) && strings.Contains(line, key.Content) {
- isFound = true
- continue
- }
- // Still finding the line, copy the line that currently read.
- if _, err = fw.WriteString(line + "\n"); err != nil {
- return err
- }
-
- if errRead == io.EOF {
- break
- }
- }
-
- if !isFound {
- log.Warn("SSH key %d not found in authorized_keys file for deletion", key.ID)
- }
-
- return nil
-}
-
// UpdatePublicKey updates given public key.
func UpdatePublicKey(key *PublicKey) error {
_, err := x.Id(key.ID).AllCols().Update(key)
return err
}
-func deletePublicKey(e *xorm.Session, keyID int64) error {
- sshOpLocker.Lock()
- defer sshOpLocker.Unlock()
-
- key := &PublicKey{ID: keyID}
- has, err := e.Get(key)
- if err != nil {
- return err
- } else if !has {
+// deletePublicKeys does the actual key deletion but does not update authorized_keys file.
+func deletePublicKeys(e *xorm.Session, keyIDs ...int64) error {
+ if len(keyIDs) == 0 {
return nil
}
- if _, err = e.Id(key.ID).Delete(new(PublicKey)); err != nil {
- return err
- }
-
- // Don't need to rewrite this file if builtin SSH server is enabled.
- if setting.SSH.StartBuiltinServer {
- return nil
- }
-
- fpath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
- tmpPath := fpath + ".tmp"
- if err = rewriteAuthorizedKeys(key, fpath, tmpPath); err != nil {
- return err
- } else if err = os.Remove(fpath); err != nil {
- return err
- }
- return os.Rename(tmpPath, fpath)
+ _, err := e.In("id", strings.Join(base.Int64sToStrings(keyIDs), ",")).Delete(new(PublicKey))
+ return err
}
// DeletePublicKey deletes SSH key information both in database and authorized_keys file.
@@ -570,14 +493,20 @@ func DeletePublicKey(doer *User, id int64) (err error) {
return err
}
- if err = deletePublicKey(sess, id); err != nil {
+ if err = deletePublicKeys(sess, id); err != nil {
return err
}
- return sess.Commit()
+ if err = sess.Commit(); err != nil {
+ return err
+ }
+
+ return RewriteAllPublicKeys()
}
// RewriteAllPublicKeys removes any authorized key and rewrite all keys from database again.
+// Note: x.Iterate does not get latest data after insert/delete, so we have to call this function
+// outsite any session scope independently.
func RewriteAllPublicKeys() error {
sshOpLocker.Lock()
defer sshOpLocker.Unlock()
@@ -814,7 +743,7 @@ func DeleteDeployKey(doer *User, id int64) error {
if err != nil {
return err
} else if !has {
- if err = deletePublicKey(sess, key.KeyID); err != nil {
+ if err = deletePublicKeys(sess, key.KeyID); err != nil {
return err
}
}