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.

ssh_key.go 38KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Copyright 2019 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package models
  6. import (
  7. "bufio"
  8. "crypto/rsa"
  9. "crypto/x509"
  10. "encoding/asn1"
  11. "encoding/base64"
  12. "encoding/binary"
  13. "encoding/pem"
  14. "errors"
  15. "fmt"
  16. "io"
  17. "io/ioutil"
  18. "math/big"
  19. "os"
  20. "path/filepath"
  21. "strconv"
  22. "strings"
  23. "sync"
  24. "time"
  25. "code.gitea.io/gitea/modules/log"
  26. "code.gitea.io/gitea/modules/process"
  27. "code.gitea.io/gitea/modules/setting"
  28. "code.gitea.io/gitea/modules/timeutil"
  29. "code.gitea.io/gitea/modules/util"
  30. "golang.org/x/crypto/ssh"
  31. "xorm.io/builder"
  32. "xorm.io/xorm"
  33. )
  34. const (
  35. tplCommentPrefix = `# gitea public key`
  36. tplPublicKey = tplCommentPrefix + "\n" + `command=%s,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s` + "\n"
  37. authorizedPrincipalsFile = "authorized_principals"
  38. )
  39. var sshOpLocker sync.Mutex
  40. // KeyType specifies the key type
  41. type KeyType int
  42. const (
  43. // KeyTypeUser specifies the user key
  44. KeyTypeUser = iota + 1
  45. // KeyTypeDeploy specifies the deploy key
  46. KeyTypeDeploy
  47. // KeyTypePrincipal specifies the authorized principal key
  48. KeyTypePrincipal
  49. )
  50. // PublicKey represents a user or deploy SSH public key.
  51. type PublicKey struct {
  52. ID int64 `xorm:"pk autoincr"`
  53. OwnerID int64 `xorm:"INDEX NOT NULL"`
  54. Name string `xorm:"NOT NULL"`
  55. Fingerprint string `xorm:"INDEX NOT NULL"`
  56. Content string `xorm:"TEXT NOT NULL"`
  57. Mode AccessMode `xorm:"NOT NULL DEFAULT 2"`
  58. Type KeyType `xorm:"NOT NULL DEFAULT 1"`
  59. LoginSourceID int64 `xorm:"NOT NULL DEFAULT 0"`
  60. CreatedUnix timeutil.TimeStamp `xorm:"created"`
  61. UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
  62. HasRecentActivity bool `xorm:"-"`
  63. HasUsed bool `xorm:"-"`
  64. }
  65. // AfterLoad is invoked from XORM after setting the values of all fields of this object.
  66. func (key *PublicKey) AfterLoad() {
  67. key.HasUsed = key.UpdatedUnix > key.CreatedUnix
  68. key.HasRecentActivity = key.UpdatedUnix.AddDuration(7*24*time.Hour) > timeutil.TimeStampNow()
  69. }
  70. // OmitEmail returns content of public key without email address.
  71. func (key *PublicKey) OmitEmail() string {
  72. return strings.Join(strings.Split(key.Content, " ")[:2], " ")
  73. }
  74. // AuthorizedString returns formatted public key string for authorized_keys file.
  75. func (key *PublicKey) AuthorizedString() string {
  76. sb := &strings.Builder{}
  77. _ = setting.SSH.AuthorizedKeysCommandTemplateTemplate.Execute(sb, map[string]interface{}{
  78. "AppPath": util.ShellEscape(setting.AppPath),
  79. "AppWorkPath": util.ShellEscape(setting.AppWorkPath),
  80. "CustomConf": util.ShellEscape(setting.CustomConf),
  81. "CustomPath": util.ShellEscape(setting.CustomPath),
  82. "Key": key,
  83. })
  84. return fmt.Sprintf(tplPublicKey, util.ShellEscape(sb.String()), key.Content)
  85. }
  86. func extractTypeFromBase64Key(key string) (string, error) {
  87. b, err := base64.StdEncoding.DecodeString(key)
  88. if err != nil || len(b) < 4 {
  89. return "", fmt.Errorf("invalid key format: %v", err)
  90. }
  91. keyLength := int(binary.BigEndian.Uint32(b))
  92. if len(b) < 4+keyLength {
  93. return "", fmt.Errorf("invalid key format: not enough length %d", keyLength)
  94. }
  95. return string(b[4 : 4+keyLength]), nil
  96. }
  97. const ssh2keyStart = "---- BEGIN SSH2 PUBLIC KEY ----"
  98. // parseKeyString parses any key string in OpenSSH or SSH2 format to clean OpenSSH string (RFC4253).
  99. func parseKeyString(content string) (string, error) {
  100. // remove whitespace at start and end
  101. content = strings.TrimSpace(content)
  102. var keyType, keyContent, keyComment string
  103. if strings.HasPrefix(content, ssh2keyStart) {
  104. // Parse SSH2 file format.
  105. // Transform all legal line endings to a single "\n".
  106. content = strings.NewReplacer("\r\n", "\n", "\r", "\n").Replace(content)
  107. lines := strings.Split(content, "\n")
  108. continuationLine := false
  109. for _, line := range lines {
  110. // Skip lines that:
  111. // 1) are a continuation of the previous line,
  112. // 2) contain ":" as that are comment lines
  113. // 3) contain "-" as that are begin and end tags
  114. if continuationLine || strings.ContainsAny(line, ":-") {
  115. continuationLine = strings.HasSuffix(line, "\\")
  116. } else {
  117. keyContent += line
  118. }
  119. }
  120. t, err := extractTypeFromBase64Key(keyContent)
  121. if err != nil {
  122. return "", fmt.Errorf("extractTypeFromBase64Key: %v", err)
  123. }
  124. keyType = t
  125. } else {
  126. if strings.Contains(content, "-----BEGIN") {
  127. // Convert PEM Keys to OpenSSH format
  128. // Transform all legal line endings to a single "\n".
  129. content = strings.NewReplacer("\r\n", "\n", "\r", "\n").Replace(content)
  130. block, _ := pem.Decode([]byte(content))
  131. if block == nil {
  132. return "", fmt.Errorf("failed to parse PEM block containing the public key")
  133. }
  134. pub, err := x509.ParsePKIXPublicKey(block.Bytes)
  135. if err != nil {
  136. var pk rsa.PublicKey
  137. _, err2 := asn1.Unmarshal(block.Bytes, &pk)
  138. if err2 != nil {
  139. return "", fmt.Errorf("failed to parse DER encoded public key as either PKIX or PEM RSA Key: %v %v", err, err2)
  140. }
  141. pub = &pk
  142. }
  143. sshKey, err := ssh.NewPublicKey(pub)
  144. if err != nil {
  145. return "", fmt.Errorf("unable to convert to ssh public key: %v", err)
  146. }
  147. content = string(ssh.MarshalAuthorizedKey(sshKey))
  148. }
  149. // Parse OpenSSH format.
  150. // Remove all newlines
  151. content = strings.NewReplacer("\r\n", "", "\n", "").Replace(content)
  152. parts := strings.SplitN(content, " ", 3)
  153. switch len(parts) {
  154. case 0:
  155. return "", errors.New("empty key")
  156. case 1:
  157. keyContent = parts[0]
  158. case 2:
  159. keyType = parts[0]
  160. keyContent = parts[1]
  161. default:
  162. keyType = parts[0]
  163. keyContent = parts[1]
  164. keyComment = parts[2]
  165. }
  166. // If keyType is not given, extract it from content. If given, validate it.
  167. t, err := extractTypeFromBase64Key(keyContent)
  168. if err != nil {
  169. return "", fmt.Errorf("extractTypeFromBase64Key: %v", err)
  170. }
  171. if len(keyType) == 0 {
  172. keyType = t
  173. } else if keyType != t {
  174. return "", fmt.Errorf("key type and content does not match: %s - %s", keyType, t)
  175. }
  176. }
  177. // Finally we need to check whether we can actually read the proposed key:
  178. _, _, _, _, err := ssh.ParseAuthorizedKey([]byte(keyType + " " + keyContent + " " + keyComment))
  179. if err != nil {
  180. return "", fmt.Errorf("invalid ssh public key: %v", err)
  181. }
  182. return keyType + " " + keyContent + " " + keyComment, nil
  183. }
  184. // writeTmpKeyFile writes key content to a temporary file
  185. // and returns the name of that file, along with any possible errors.
  186. func writeTmpKeyFile(content string) (string, error) {
  187. tmpFile, err := ioutil.TempFile(setting.SSH.KeyTestPath, "gitea_keytest")
  188. if err != nil {
  189. return "", fmt.Errorf("TempFile: %v", err)
  190. }
  191. defer tmpFile.Close()
  192. if _, err = tmpFile.WriteString(content); err != nil {
  193. return "", fmt.Errorf("WriteString: %v", err)
  194. }
  195. return tmpFile.Name(), nil
  196. }
  197. // SSHKeyGenParsePublicKey extracts key type and length using ssh-keygen.
  198. func SSHKeyGenParsePublicKey(key string) (string, int, error) {
  199. tmpName, err := writeTmpKeyFile(key)
  200. if err != nil {
  201. return "", 0, fmt.Errorf("writeTmpKeyFile: %v", err)
  202. }
  203. defer func() {
  204. if err := util.Remove(tmpName); err != nil {
  205. log.Warn("Unable to remove temporary key file: %s: Error: %v", tmpName, err)
  206. }
  207. }()
  208. stdout, stderr, err := process.GetManager().Exec("SSHKeyGenParsePublicKey", setting.SSH.KeygenPath, "-lf", tmpName)
  209. if err != nil {
  210. return "", 0, fmt.Errorf("fail to parse public key: %s - %s", err, stderr)
  211. }
  212. if strings.Contains(stdout, "is not a public key file") {
  213. return "", 0, ErrKeyUnableVerify{stdout}
  214. }
  215. fields := strings.Split(stdout, " ")
  216. if len(fields) < 4 {
  217. return "", 0, fmt.Errorf("invalid public key line: %s", stdout)
  218. }
  219. keyType := strings.Trim(fields[len(fields)-1], "()\r\n")
  220. length, err := strconv.ParseInt(fields[0], 10, 32)
  221. if err != nil {
  222. return "", 0, err
  223. }
  224. return strings.ToLower(keyType), int(length), nil
  225. }
  226. // SSHNativeParsePublicKey extracts the key type and length using the golang SSH library.
  227. func SSHNativeParsePublicKey(keyLine string) (string, int, error) {
  228. fields := strings.Fields(keyLine)
  229. if len(fields) < 2 {
  230. return "", 0, fmt.Errorf("not enough fields in public key line: %s", keyLine)
  231. }
  232. raw, err := base64.StdEncoding.DecodeString(fields[1])
  233. if err != nil {
  234. return "", 0, err
  235. }
  236. pkey, err := ssh.ParsePublicKey(raw)
  237. if err != nil {
  238. if strings.Contains(err.Error(), "ssh: unknown key algorithm") {
  239. return "", 0, ErrKeyUnableVerify{err.Error()}
  240. }
  241. return "", 0, fmt.Errorf("ParsePublicKey: %v", err)
  242. }
  243. // The ssh library can parse the key, so next we find out what key exactly we have.
  244. switch pkey.Type() {
  245. case ssh.KeyAlgoDSA:
  246. rawPub := struct {
  247. Name string
  248. P, Q, G, Y *big.Int
  249. }{}
  250. if err := ssh.Unmarshal(pkey.Marshal(), &rawPub); err != nil {
  251. return "", 0, err
  252. }
  253. // as per https://bugzilla.mindrot.org/show_bug.cgi?id=1647 we should never
  254. // see dsa keys != 1024 bit, but as it seems to work, we will not check here
  255. return "dsa", rawPub.P.BitLen(), nil // use P as per crypto/dsa/dsa.go (is L)
  256. case ssh.KeyAlgoRSA:
  257. rawPub := struct {
  258. Name string
  259. E *big.Int
  260. N *big.Int
  261. }{}
  262. if err := ssh.Unmarshal(pkey.Marshal(), &rawPub); err != nil {
  263. return "", 0, err
  264. }
  265. return "rsa", rawPub.N.BitLen(), nil // use N as per crypto/rsa/rsa.go (is bits)
  266. case ssh.KeyAlgoECDSA256:
  267. return "ecdsa", 256, nil
  268. case ssh.KeyAlgoECDSA384:
  269. return "ecdsa", 384, nil
  270. case ssh.KeyAlgoECDSA521:
  271. return "ecdsa", 521, nil
  272. case ssh.KeyAlgoED25519:
  273. return "ed25519", 256, nil
  274. case ssh.KeyAlgoSKECDSA256:
  275. return "ecdsa-sk", 256, nil
  276. case ssh.KeyAlgoSKED25519:
  277. return "ed25519-sk", 256, nil
  278. }
  279. return "", 0, fmt.Errorf("unsupported key length detection for type: %s", pkey.Type())
  280. }
  281. // CheckPublicKeyString checks if the given public key string is recognized by SSH.
  282. // It returns the actual public key line on success.
  283. func CheckPublicKeyString(content string) (_ string, err error) {
  284. if setting.SSH.Disabled {
  285. return "", ErrSSHDisabled{}
  286. }
  287. content, err = parseKeyString(content)
  288. if err != nil {
  289. return "", err
  290. }
  291. content = strings.TrimRight(content, "\n\r")
  292. if strings.ContainsAny(content, "\n\r") {
  293. return "", errors.New("only a single line with a single key please")
  294. }
  295. // remove any unnecessary whitespace now
  296. content = strings.TrimSpace(content)
  297. if !setting.SSH.MinimumKeySizeCheck {
  298. return content, nil
  299. }
  300. var (
  301. fnName string
  302. keyType string
  303. length int
  304. )
  305. if setting.SSH.StartBuiltinServer {
  306. fnName = "SSHNativeParsePublicKey"
  307. keyType, length, err = SSHNativeParsePublicKey(content)
  308. } else {
  309. fnName = "SSHKeyGenParsePublicKey"
  310. keyType, length, err = SSHKeyGenParsePublicKey(content)
  311. }
  312. if err != nil {
  313. return "", fmt.Errorf("%s: %v", fnName, err)
  314. }
  315. log.Trace("Key info [native: %v]: %s-%d", setting.SSH.StartBuiltinServer, keyType, length)
  316. if minLen, found := setting.SSH.MinimumKeySizes[keyType]; found && length >= minLen {
  317. return content, nil
  318. } else if found && length < minLen {
  319. return "", fmt.Errorf("key length is not enough: got %d, needs %d", length, minLen)
  320. }
  321. return "", fmt.Errorf("key type is not allowed: %s", keyType)
  322. }
  323. // appendAuthorizedKeysToFile appends new SSH keys' content to authorized_keys file.
  324. func appendAuthorizedKeysToFile(keys ...*PublicKey) error {
  325. // Don't need to rewrite this file if builtin SSH server is enabled.
  326. if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile {
  327. return nil
  328. }
  329. sshOpLocker.Lock()
  330. defer sshOpLocker.Unlock()
  331. if setting.SSH.RootPath != "" {
  332. // First of ensure that the RootPath is present, and if not make it with 0700 permissions
  333. // This of course doesn't guarantee that this is the right directory for authorized_keys
  334. // but at least if it's supposed to be this directory and it doesn't exist and we're the
  335. // right user it will at least be created properly.
  336. err := os.MkdirAll(setting.SSH.RootPath, 0o700)
  337. if err != nil {
  338. log.Error("Unable to MkdirAll(%s): %v", setting.SSH.RootPath, err)
  339. return err
  340. }
  341. }
  342. fPath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
  343. f, err := os.OpenFile(fPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o600)
  344. if err != nil {
  345. return err
  346. }
  347. defer f.Close()
  348. // Note: chmod command does not support in Windows.
  349. if !setting.IsWindows {
  350. fi, err := f.Stat()
  351. if err != nil {
  352. return err
  353. }
  354. // .ssh directory should have mode 700, and authorized_keys file should have mode 600.
  355. if fi.Mode().Perm() > 0o600 {
  356. log.Error("authorized_keys file has unusual permission flags: %s - setting to -rw-------", fi.Mode().Perm().String())
  357. if err = f.Chmod(0o600); err != nil {
  358. return err
  359. }
  360. }
  361. }
  362. for _, key := range keys {
  363. if key.Type == KeyTypePrincipal {
  364. continue
  365. }
  366. if _, err = f.WriteString(key.AuthorizedString()); err != nil {
  367. return err
  368. }
  369. }
  370. return nil
  371. }
  372. // checkKeyFingerprint only checks if key fingerprint has been used as public key,
  373. // it is OK to use same key as deploy key for multiple repositories/users.
  374. func checkKeyFingerprint(e Engine, fingerprint string) error {
  375. has, err := e.Get(&PublicKey{
  376. Fingerprint: fingerprint,
  377. })
  378. if err != nil {
  379. return err
  380. } else if has {
  381. return ErrKeyAlreadyExist{0, fingerprint, ""}
  382. }
  383. return nil
  384. }
  385. func calcFingerprintSSHKeygen(publicKeyContent string) (string, error) {
  386. // Calculate fingerprint.
  387. tmpPath, err := writeTmpKeyFile(publicKeyContent)
  388. if err != nil {
  389. return "", err
  390. }
  391. defer func() {
  392. if err := util.Remove(tmpPath); err != nil {
  393. log.Warn("Unable to remove temporary key file: %s: Error: %v", tmpPath, err)
  394. }
  395. }()
  396. stdout, stderr, err := process.GetManager().Exec("AddPublicKey", "ssh-keygen", "-lf", tmpPath)
  397. if err != nil {
  398. if strings.Contains(stderr, "is not a public key file") {
  399. return "", ErrKeyUnableVerify{stderr}
  400. }
  401. return "", fmt.Errorf("'ssh-keygen -lf %s' failed with error '%s': %s", tmpPath, err, stderr)
  402. } else if len(stdout) < 2 {
  403. return "", errors.New("not enough output for calculating fingerprint: " + stdout)
  404. }
  405. return strings.Split(stdout, " ")[1], nil
  406. }
  407. func calcFingerprintNative(publicKeyContent string) (string, error) {
  408. // Calculate fingerprint.
  409. pk, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKeyContent))
  410. if err != nil {
  411. return "", err
  412. }
  413. return ssh.FingerprintSHA256(pk), nil
  414. }
  415. func calcFingerprint(publicKeyContent string) (string, error) {
  416. // Call the method based on configuration
  417. var (
  418. fnName, fp string
  419. err error
  420. )
  421. if setting.SSH.StartBuiltinServer {
  422. fnName = "calcFingerprintNative"
  423. fp, err = calcFingerprintNative(publicKeyContent)
  424. } else {
  425. fnName = "calcFingerprintSSHKeygen"
  426. fp, err = calcFingerprintSSHKeygen(publicKeyContent)
  427. }
  428. if err != nil {
  429. if IsErrKeyUnableVerify(err) {
  430. log.Info("%s", publicKeyContent)
  431. return "", err
  432. }
  433. return "", fmt.Errorf("%s: %v", fnName, err)
  434. }
  435. return fp, nil
  436. }
  437. func addKey(e Engine, key *PublicKey) (err error) {
  438. if len(key.Fingerprint) == 0 {
  439. key.Fingerprint, err = calcFingerprint(key.Content)
  440. if err != nil {
  441. return err
  442. }
  443. }
  444. // Save SSH key.
  445. if _, err = e.Insert(key); err != nil {
  446. return err
  447. }
  448. return appendAuthorizedKeysToFile(key)
  449. }
  450. // AddPublicKey adds new public key to database and authorized_keys file.
  451. func AddPublicKey(ownerID int64, name, content string, loginSourceID int64) (*PublicKey, error) {
  452. log.Trace(content)
  453. fingerprint, err := calcFingerprint(content)
  454. if err != nil {
  455. return nil, err
  456. }
  457. sess := x.NewSession()
  458. defer sess.Close()
  459. if err = sess.Begin(); err != nil {
  460. return nil, err
  461. }
  462. if err := checkKeyFingerprint(sess, fingerprint); err != nil {
  463. return nil, err
  464. }
  465. // Key name of same user cannot be duplicated.
  466. has, err := sess.
  467. Where("owner_id = ? AND name = ?", ownerID, name).
  468. Get(new(PublicKey))
  469. if err != nil {
  470. return nil, err
  471. } else if has {
  472. return nil, ErrKeyNameAlreadyUsed{ownerID, name}
  473. }
  474. key := &PublicKey{
  475. OwnerID: ownerID,
  476. Name: name,
  477. Fingerprint: fingerprint,
  478. Content: content,
  479. Mode: AccessModeWrite,
  480. Type: KeyTypeUser,
  481. LoginSourceID: loginSourceID,
  482. }
  483. if err = addKey(sess, key); err != nil {
  484. return nil, fmt.Errorf("addKey: %v", err)
  485. }
  486. return key, sess.Commit()
  487. }
  488. // GetPublicKeyByID returns public key by given ID.
  489. func GetPublicKeyByID(keyID int64) (*PublicKey, error) {
  490. key := new(PublicKey)
  491. has, err := x.
  492. ID(keyID).
  493. Get(key)
  494. if err != nil {
  495. return nil, err
  496. } else if !has {
  497. return nil, ErrKeyNotExist{keyID}
  498. }
  499. return key, nil
  500. }
  501. func searchPublicKeyByContentWithEngine(e Engine, content string) (*PublicKey, error) {
  502. key := new(PublicKey)
  503. has, err := e.
  504. Where("content like ?", content+"%").
  505. Get(key)
  506. if err != nil {
  507. return nil, err
  508. } else if !has {
  509. return nil, ErrKeyNotExist{}
  510. }
  511. return key, nil
  512. }
  513. // SearchPublicKeyByContent searches content as prefix (leak e-mail part)
  514. // and returns public key found.
  515. func SearchPublicKeyByContent(content string) (*PublicKey, error) {
  516. return searchPublicKeyByContentWithEngine(x, content)
  517. }
  518. func searchPublicKeyByContentExactWithEngine(e Engine, content string) (*PublicKey, error) {
  519. key := new(PublicKey)
  520. has, err := e.
  521. Where("content = ?", content).
  522. Get(key)
  523. if err != nil {
  524. return nil, err
  525. } else if !has {
  526. return nil, ErrKeyNotExist{}
  527. }
  528. return key, nil
  529. }
  530. // SearchPublicKeyByContentExact searches content
  531. // and returns public key found.
  532. func SearchPublicKeyByContentExact(content string) (*PublicKey, error) {
  533. return searchPublicKeyByContentExactWithEngine(x, content)
  534. }
  535. // SearchPublicKey returns a list of public keys matching the provided arguments.
  536. func SearchPublicKey(uid int64, fingerprint string) ([]*PublicKey, error) {
  537. keys := make([]*PublicKey, 0, 5)
  538. cond := builder.NewCond()
  539. if uid != 0 {
  540. cond = cond.And(builder.Eq{"owner_id": uid})
  541. }
  542. if fingerprint != "" {
  543. cond = cond.And(builder.Eq{"fingerprint": fingerprint})
  544. }
  545. return keys, x.Where(cond).Find(&keys)
  546. }
  547. // ListPublicKeys returns a list of public keys belongs to given user.
  548. func ListPublicKeys(uid int64, listOptions ListOptions) ([]*PublicKey, error) {
  549. sess := x.Where("owner_id = ? AND type != ?", uid, KeyTypePrincipal)
  550. if listOptions.Page != 0 {
  551. sess = listOptions.setSessionPagination(sess)
  552. keys := make([]*PublicKey, 0, listOptions.PageSize)
  553. return keys, sess.Find(&keys)
  554. }
  555. keys := make([]*PublicKey, 0, 5)
  556. return keys, sess.Find(&keys)
  557. }
  558. // ListPublicLdapSSHKeys returns a list of synchronized public ldap ssh keys belongs to given user and login source.
  559. func ListPublicLdapSSHKeys(uid, loginSourceID int64) ([]*PublicKey, error) {
  560. keys := make([]*PublicKey, 0, 5)
  561. return keys, x.
  562. Where("owner_id = ? AND login_source_id = ?", uid, loginSourceID).
  563. Find(&keys)
  564. }
  565. // UpdatePublicKeyUpdated updates public key use time.
  566. func UpdatePublicKeyUpdated(id int64) error {
  567. // Check if key exists before update as affected rows count is unreliable
  568. // and will return 0 affected rows if two updates are made at the same time
  569. if cnt, err := x.ID(id).Count(&PublicKey{}); err != nil {
  570. return err
  571. } else if cnt != 1 {
  572. return ErrKeyNotExist{id}
  573. }
  574. _, err := x.ID(id).Cols("updated_unix").Update(&PublicKey{
  575. UpdatedUnix: timeutil.TimeStampNow(),
  576. })
  577. if err != nil {
  578. return err
  579. }
  580. return nil
  581. }
  582. // deletePublicKeys does the actual key deletion but does not update authorized_keys file.
  583. func deletePublicKeys(e Engine, keyIDs ...int64) error {
  584. if len(keyIDs) == 0 {
  585. return nil
  586. }
  587. _, err := e.In("id", keyIDs).Delete(new(PublicKey))
  588. return err
  589. }
  590. // PublicKeysAreExternallyManaged returns whether the provided KeyID represents an externally managed Key
  591. func PublicKeysAreExternallyManaged(keys []*PublicKey) ([]bool, error) {
  592. sources := make([]*LoginSource, 0, 5)
  593. externals := make([]bool, len(keys))
  594. keyloop:
  595. for i, key := range keys {
  596. if key.LoginSourceID == 0 {
  597. externals[i] = false
  598. continue keyloop
  599. }
  600. var source *LoginSource
  601. sourceloop:
  602. for _, s := range sources {
  603. if s.ID == key.LoginSourceID {
  604. source = s
  605. break sourceloop
  606. }
  607. }
  608. if source == nil {
  609. var err error
  610. source, err = GetLoginSourceByID(key.LoginSourceID)
  611. if err != nil {
  612. if IsErrLoginSourceNotExist(err) {
  613. externals[i] = false
  614. sources[i] = &LoginSource{
  615. ID: key.LoginSourceID,
  616. }
  617. continue keyloop
  618. }
  619. return nil, err
  620. }
  621. }
  622. ldapSource := source.LDAP()
  623. if ldapSource != nil &&
  624. source.IsSyncEnabled &&
  625. (source.Type == LoginLDAP || source.Type == LoginDLDAP) &&
  626. len(strings.TrimSpace(ldapSource.AttributeSSHPublicKey)) > 0 {
  627. // Disable setting SSH keys for this user
  628. externals[i] = true
  629. }
  630. }
  631. return externals, nil
  632. }
  633. // PublicKeyIsExternallyManaged returns whether the provided KeyID represents an externally managed Key
  634. func PublicKeyIsExternallyManaged(id int64) (bool, error) {
  635. key, err := GetPublicKeyByID(id)
  636. if err != nil {
  637. return false, err
  638. }
  639. if key.LoginSourceID == 0 {
  640. return false, nil
  641. }
  642. source, err := GetLoginSourceByID(key.LoginSourceID)
  643. if err != nil {
  644. if IsErrLoginSourceNotExist(err) {
  645. return false, nil
  646. }
  647. return false, err
  648. }
  649. ldapSource := source.LDAP()
  650. if ldapSource != nil &&
  651. source.IsSyncEnabled &&
  652. (source.Type == LoginLDAP || source.Type == LoginDLDAP) &&
  653. len(strings.TrimSpace(ldapSource.AttributeSSHPublicKey)) > 0 {
  654. // Disable setting SSH keys for this user
  655. return true, nil
  656. }
  657. return false, nil
  658. }
  659. // DeletePublicKey deletes SSH key information both in database and authorized_keys file.
  660. func DeletePublicKey(doer *User, id int64) (err error) {
  661. key, err := GetPublicKeyByID(id)
  662. if err != nil {
  663. return err
  664. }
  665. // Check if user has access to delete this key.
  666. if !doer.IsAdmin && doer.ID != key.OwnerID {
  667. return ErrKeyAccessDenied{doer.ID, key.ID, "public"}
  668. }
  669. sess := x.NewSession()
  670. defer sess.Close()
  671. if err = sess.Begin(); err != nil {
  672. return err
  673. }
  674. if err = deletePublicKeys(sess, id); err != nil {
  675. return err
  676. }
  677. if err = sess.Commit(); err != nil {
  678. return err
  679. }
  680. sess.Close()
  681. if key.Type == KeyTypePrincipal {
  682. return RewriteAllPrincipalKeys()
  683. }
  684. return RewriteAllPublicKeys()
  685. }
  686. // RewriteAllPublicKeys removes any authorized key and rewrite all keys from database again.
  687. // Note: x.Iterate does not get latest data after insert/delete, so we have to call this function
  688. // outside any session scope independently.
  689. func RewriteAllPublicKeys() error {
  690. return rewriteAllPublicKeys(x)
  691. }
  692. func rewriteAllPublicKeys(e Engine) error {
  693. // Don't rewrite key if internal server
  694. if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile {
  695. return nil
  696. }
  697. sshOpLocker.Lock()
  698. defer sshOpLocker.Unlock()
  699. if setting.SSH.RootPath != "" {
  700. // First of ensure that the RootPath is present, and if not make it with 0700 permissions
  701. // This of course doesn't guarantee that this is the right directory for authorized_keys
  702. // but at least if it's supposed to be this directory and it doesn't exist and we're the
  703. // right user it will at least be created properly.
  704. err := os.MkdirAll(setting.SSH.RootPath, 0o700)
  705. if err != nil {
  706. log.Error("Unable to MkdirAll(%s): %v", setting.SSH.RootPath, err)
  707. return err
  708. }
  709. }
  710. fPath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
  711. tmpPath := fPath + ".tmp"
  712. t, err := os.OpenFile(tmpPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o600)
  713. if err != nil {
  714. return err
  715. }
  716. defer func() {
  717. t.Close()
  718. if err := util.Remove(tmpPath); err != nil {
  719. log.Warn("Unable to remove temporary authorized keys file: %s: Error: %v", tmpPath, err)
  720. }
  721. }()
  722. if setting.SSH.AuthorizedKeysBackup {
  723. isExist, err := util.IsExist(fPath)
  724. if err != nil {
  725. log.Error("Unable to check if %s exists. Error: %v", fPath, err)
  726. return err
  727. }
  728. if isExist {
  729. bakPath := fmt.Sprintf("%s_%d.gitea_bak", fPath, time.Now().Unix())
  730. if err = util.CopyFile(fPath, bakPath); err != nil {
  731. return err
  732. }
  733. }
  734. }
  735. if err := regeneratePublicKeys(e, t); err != nil {
  736. return err
  737. }
  738. t.Close()
  739. return util.Rename(tmpPath, fPath)
  740. }
  741. // RegeneratePublicKeys regenerates the authorized_keys file
  742. func RegeneratePublicKeys(t io.StringWriter) error {
  743. return regeneratePublicKeys(x, t)
  744. }
  745. func regeneratePublicKeys(e Engine, t io.StringWriter) error {
  746. if err := e.Where("type != ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
  747. _, err = t.WriteString((bean.(*PublicKey)).AuthorizedString())
  748. return err
  749. }); err != nil {
  750. return err
  751. }
  752. fPath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
  753. isExist, err := util.IsExist(fPath)
  754. if err != nil {
  755. log.Error("Unable to check if %s exists. Error: %v", fPath, err)
  756. return err
  757. }
  758. if isExist {
  759. f, err := os.Open(fPath)
  760. if err != nil {
  761. return err
  762. }
  763. scanner := bufio.NewScanner(f)
  764. for scanner.Scan() {
  765. line := scanner.Text()
  766. if strings.HasPrefix(line, tplCommentPrefix) {
  767. scanner.Scan()
  768. continue
  769. }
  770. _, err = t.WriteString(line + "\n")
  771. if err != nil {
  772. f.Close()
  773. return err
  774. }
  775. }
  776. f.Close()
  777. }
  778. return nil
  779. }
  780. // ________ .__ ____ __.
  781. // \______ \ ____ ______ | | ____ ___.__.| |/ _|____ ___.__.
  782. // | | \_/ __ \\____ \| | / _ < | || <_/ __ < | |
  783. // | ` \ ___/| |_> > |_( <_> )___ || | \ ___/\___ |
  784. // /_______ /\___ > __/|____/\____// ____||____|__ \___ > ____|
  785. // \/ \/|__| \/ \/ \/\/
  786. // DeployKey represents deploy key information and its relation with repository.
  787. type DeployKey struct {
  788. ID int64 `xorm:"pk autoincr"`
  789. KeyID int64 `xorm:"UNIQUE(s) INDEX"`
  790. RepoID int64 `xorm:"UNIQUE(s) INDEX"`
  791. Name string
  792. Fingerprint string
  793. Content string `xorm:"-"`
  794. Mode AccessMode `xorm:"NOT NULL DEFAULT 1"`
  795. CreatedUnix timeutil.TimeStamp `xorm:"created"`
  796. UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
  797. HasRecentActivity bool `xorm:"-"`
  798. HasUsed bool `xorm:"-"`
  799. }
  800. // AfterLoad is invoked from XORM after setting the values of all fields of this object.
  801. func (key *DeployKey) AfterLoad() {
  802. key.HasUsed = key.UpdatedUnix > key.CreatedUnix
  803. key.HasRecentActivity = key.UpdatedUnix.AddDuration(7*24*time.Hour) > timeutil.TimeStampNow()
  804. }
  805. // GetContent gets associated public key content.
  806. func (key *DeployKey) GetContent() error {
  807. pkey, err := GetPublicKeyByID(key.KeyID)
  808. if err != nil {
  809. return err
  810. }
  811. key.Content = pkey.Content
  812. return nil
  813. }
  814. // IsReadOnly checks if the key can only be used for read operations
  815. func (key *DeployKey) IsReadOnly() bool {
  816. return key.Mode == AccessModeRead
  817. }
  818. func checkDeployKey(e Engine, keyID, repoID int64, name string) error {
  819. // Note: We want error detail, not just true or false here.
  820. has, err := e.
  821. Where("key_id = ? AND repo_id = ?", keyID, repoID).
  822. Get(new(DeployKey))
  823. if err != nil {
  824. return err
  825. } else if has {
  826. return ErrDeployKeyAlreadyExist{keyID, repoID}
  827. }
  828. has, err = e.
  829. Where("repo_id = ? AND name = ?", repoID, name).
  830. Get(new(DeployKey))
  831. if err != nil {
  832. return err
  833. } else if has {
  834. return ErrDeployKeyNameAlreadyUsed{repoID, name}
  835. }
  836. return nil
  837. }
  838. // addDeployKey adds new key-repo relation.
  839. func addDeployKey(e *xorm.Session, keyID, repoID int64, name, fingerprint string, mode AccessMode) (*DeployKey, error) {
  840. if err := checkDeployKey(e, keyID, repoID, name); err != nil {
  841. return nil, err
  842. }
  843. key := &DeployKey{
  844. KeyID: keyID,
  845. RepoID: repoID,
  846. Name: name,
  847. Fingerprint: fingerprint,
  848. Mode: mode,
  849. }
  850. _, err := e.Insert(key)
  851. return key, err
  852. }
  853. // HasDeployKey returns true if public key is a deploy key of given repository.
  854. func HasDeployKey(keyID, repoID int64) bool {
  855. has, _ := x.
  856. Where("key_id = ? AND repo_id = ?", keyID, repoID).
  857. Get(new(DeployKey))
  858. return has
  859. }
  860. // AddDeployKey add new deploy key to database and authorized_keys file.
  861. func AddDeployKey(repoID int64, name, content string, readOnly bool) (*DeployKey, error) {
  862. fingerprint, err := calcFingerprint(content)
  863. if err != nil {
  864. return nil, err
  865. }
  866. accessMode := AccessModeRead
  867. if !readOnly {
  868. accessMode = AccessModeWrite
  869. }
  870. sess := x.NewSession()
  871. defer sess.Close()
  872. if err = sess.Begin(); err != nil {
  873. return nil, err
  874. }
  875. pkey := &PublicKey{
  876. Fingerprint: fingerprint,
  877. }
  878. has, err := sess.Get(pkey)
  879. if err != nil {
  880. return nil, err
  881. }
  882. if has {
  883. if pkey.Type != KeyTypeDeploy {
  884. return nil, ErrKeyAlreadyExist{0, fingerprint, ""}
  885. }
  886. } else {
  887. // First time use this deploy key.
  888. pkey.Mode = accessMode
  889. pkey.Type = KeyTypeDeploy
  890. pkey.Content = content
  891. pkey.Name = name
  892. if err = addKey(sess, pkey); err != nil {
  893. return nil, fmt.Errorf("addKey: %v", err)
  894. }
  895. }
  896. key, err := addDeployKey(sess, pkey.ID, repoID, name, pkey.Fingerprint, accessMode)
  897. if err != nil {
  898. return nil, err
  899. }
  900. return key, sess.Commit()
  901. }
  902. // GetDeployKeyByID returns deploy key by given ID.
  903. func GetDeployKeyByID(id int64) (*DeployKey, error) {
  904. return getDeployKeyByID(x, id)
  905. }
  906. func getDeployKeyByID(e Engine, id int64) (*DeployKey, error) {
  907. key := new(DeployKey)
  908. has, err := e.ID(id).Get(key)
  909. if err != nil {
  910. return nil, err
  911. } else if !has {
  912. return nil, ErrDeployKeyNotExist{id, 0, 0}
  913. }
  914. return key, nil
  915. }
  916. // GetDeployKeyByRepo returns deploy key by given public key ID and repository ID.
  917. func GetDeployKeyByRepo(keyID, repoID int64) (*DeployKey, error) {
  918. return getDeployKeyByRepo(x, keyID, repoID)
  919. }
  920. func getDeployKeyByRepo(e Engine, keyID, repoID int64) (*DeployKey, error) {
  921. key := &DeployKey{
  922. KeyID: keyID,
  923. RepoID: repoID,
  924. }
  925. has, err := e.Get(key)
  926. if err != nil {
  927. return nil, err
  928. } else if !has {
  929. return nil, ErrDeployKeyNotExist{0, keyID, repoID}
  930. }
  931. return key, nil
  932. }
  933. // UpdateDeployKeyCols updates deploy key information in the specified columns.
  934. func UpdateDeployKeyCols(key *DeployKey, cols ...string) error {
  935. _, err := x.ID(key.ID).Cols(cols...).Update(key)
  936. return err
  937. }
  938. // UpdateDeployKey updates deploy key information.
  939. func UpdateDeployKey(key *DeployKey) error {
  940. _, err := x.ID(key.ID).AllCols().Update(key)
  941. return err
  942. }
  943. // DeleteDeployKey deletes deploy key from its repository authorized_keys file if needed.
  944. func DeleteDeployKey(doer *User, id int64) error {
  945. sess := x.NewSession()
  946. defer sess.Close()
  947. if err := sess.Begin(); err != nil {
  948. return err
  949. }
  950. if err := deleteDeployKey(sess, doer, id); err != nil {
  951. return err
  952. }
  953. return sess.Commit()
  954. }
  955. func deleteDeployKey(sess Engine, doer *User, id int64) error {
  956. key, err := getDeployKeyByID(sess, id)
  957. if err != nil {
  958. if IsErrDeployKeyNotExist(err) {
  959. return nil
  960. }
  961. return fmt.Errorf("GetDeployKeyByID: %v", err)
  962. }
  963. // Check if user has access to delete this key.
  964. if !doer.IsAdmin {
  965. repo, err := getRepositoryByID(sess, key.RepoID)
  966. if err != nil {
  967. return fmt.Errorf("GetRepositoryByID: %v", err)
  968. }
  969. has, err := isUserRepoAdmin(sess, repo, doer)
  970. if err != nil {
  971. return fmt.Errorf("GetUserRepoPermission: %v", err)
  972. } else if !has {
  973. return ErrKeyAccessDenied{doer.ID, key.ID, "deploy"}
  974. }
  975. }
  976. if _, err = sess.ID(key.ID).Delete(new(DeployKey)); err != nil {
  977. return fmt.Errorf("delete deploy key [%d]: %v", key.ID, err)
  978. }
  979. // Check if this is the last reference to same key content.
  980. has, err := sess.
  981. Where("key_id = ?", key.KeyID).
  982. Get(new(DeployKey))
  983. if err != nil {
  984. return err
  985. } else if !has {
  986. if err = deletePublicKeys(sess, key.KeyID); err != nil {
  987. return err
  988. }
  989. // after deleted the public keys, should rewrite the public keys file
  990. if err = rewriteAllPublicKeys(sess); err != nil {
  991. return err
  992. }
  993. }
  994. return nil
  995. }
  996. // ListDeployKeys returns all deploy keys by given repository ID.
  997. func ListDeployKeys(repoID int64, listOptions ListOptions) ([]*DeployKey, error) {
  998. return listDeployKeys(x, repoID, listOptions)
  999. }
  1000. func listDeployKeys(e Engine, repoID int64, listOptions ListOptions) ([]*DeployKey, error) {
  1001. sess := e.Where("repo_id = ?", repoID)
  1002. if listOptions.Page != 0 {
  1003. sess = listOptions.setSessionPagination(sess)
  1004. keys := make([]*DeployKey, 0, listOptions.PageSize)
  1005. return keys, sess.Find(&keys)
  1006. }
  1007. keys := make([]*DeployKey, 0, 5)
  1008. return keys, sess.Find(&keys)
  1009. }
  1010. // SearchDeployKeys returns a list of deploy keys matching the provided arguments.
  1011. func SearchDeployKeys(repoID, keyID int64, fingerprint string) ([]*DeployKey, error) {
  1012. keys := make([]*DeployKey, 0, 5)
  1013. cond := builder.NewCond()
  1014. if repoID != 0 {
  1015. cond = cond.And(builder.Eq{"repo_id": repoID})
  1016. }
  1017. if keyID != 0 {
  1018. cond = cond.And(builder.Eq{"key_id": keyID})
  1019. }
  1020. if fingerprint != "" {
  1021. cond = cond.And(builder.Eq{"fingerprint": fingerprint})
  1022. }
  1023. return keys, x.Where(cond).Find(&keys)
  1024. }
  1025. // __________ .__ .__ .__
  1026. // \______ _______|__| ____ ____ |_____________ | | ______
  1027. // | ___\_ __ | |/ \_/ ___\| \____ \__ \ | | / ___/
  1028. // | | | | \| | | \ \___| | |_> / __ \| |__\___ \
  1029. // |____| |__| |__|___| /\___ |__| __(____ |____/____ >
  1030. // \/ \/ |__| \/ \/
  1031. // AddPrincipalKey adds new principal to database and authorized_principals file.
  1032. func AddPrincipalKey(ownerID int64, content string, loginSourceID int64) (*PublicKey, error) {
  1033. sess := x.NewSession()
  1034. defer sess.Close()
  1035. if err := sess.Begin(); err != nil {
  1036. return nil, err
  1037. }
  1038. // Principals cannot be duplicated.
  1039. has, err := sess.
  1040. Where("content = ? AND type = ?", content, KeyTypePrincipal).
  1041. Get(new(PublicKey))
  1042. if err != nil {
  1043. return nil, err
  1044. } else if has {
  1045. return nil, ErrKeyAlreadyExist{0, "", content}
  1046. }
  1047. key := &PublicKey{
  1048. OwnerID: ownerID,
  1049. Name: content,
  1050. Content: content,
  1051. Mode: AccessModeWrite,
  1052. Type: KeyTypePrincipal,
  1053. LoginSourceID: loginSourceID,
  1054. }
  1055. if err = addPrincipalKey(sess, key); err != nil {
  1056. return nil, fmt.Errorf("addKey: %v", err)
  1057. }
  1058. if err = sess.Commit(); err != nil {
  1059. return nil, err
  1060. }
  1061. sess.Close()
  1062. return key, RewriteAllPrincipalKeys()
  1063. }
  1064. func addPrincipalKey(e Engine, key *PublicKey) (err error) {
  1065. // Save Key representing a principal.
  1066. if _, err = e.Insert(key); err != nil {
  1067. return err
  1068. }
  1069. return nil
  1070. }
  1071. // CheckPrincipalKeyString strips spaces and returns an error if the given principal contains newlines
  1072. func CheckPrincipalKeyString(user *User, content string) (_ string, err error) {
  1073. if setting.SSH.Disabled {
  1074. return "", ErrSSHDisabled{}
  1075. }
  1076. content = strings.TrimSpace(content)
  1077. if strings.ContainsAny(content, "\r\n") {
  1078. return "", errors.New("only a single line with a single principal please")
  1079. }
  1080. // check all the allowed principals, email, username or anything
  1081. // if any matches, return ok
  1082. for _, v := range setting.SSH.AuthorizedPrincipalsAllow {
  1083. switch v {
  1084. case "anything":
  1085. return content, nil
  1086. case "email":
  1087. emails, err := GetEmailAddresses(user.ID)
  1088. if err != nil {
  1089. return "", err
  1090. }
  1091. for _, email := range emails {
  1092. if !email.IsActivated {
  1093. continue
  1094. }
  1095. if content == email.Email {
  1096. return content, nil
  1097. }
  1098. }
  1099. case "username":
  1100. if content == user.Name {
  1101. return content, nil
  1102. }
  1103. }
  1104. }
  1105. return "", fmt.Errorf("didn't match allowed principals: %s", setting.SSH.AuthorizedPrincipalsAllow)
  1106. }
  1107. // RewriteAllPrincipalKeys removes any authorized principal and rewrite all keys from database again.
  1108. // Note: x.Iterate does not get latest data after insert/delete, so we have to call this function
  1109. // outside any session scope independently.
  1110. func RewriteAllPrincipalKeys() error {
  1111. return rewriteAllPrincipalKeys(x)
  1112. }
  1113. func rewriteAllPrincipalKeys(e Engine) error {
  1114. // Don't rewrite key if internal server
  1115. if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedPrincipalsFile {
  1116. return nil
  1117. }
  1118. sshOpLocker.Lock()
  1119. defer sshOpLocker.Unlock()
  1120. if setting.SSH.RootPath != "" {
  1121. // First of ensure that the RootPath is present, and if not make it with 0700 permissions
  1122. // This of course doesn't guarantee that this is the right directory for authorized_keys
  1123. // but at least if it's supposed to be this directory and it doesn't exist and we're the
  1124. // right user it will at least be created properly.
  1125. err := os.MkdirAll(setting.SSH.RootPath, 0o700)
  1126. if err != nil {
  1127. log.Error("Unable to MkdirAll(%s): %v", setting.SSH.RootPath, err)
  1128. return err
  1129. }
  1130. }
  1131. fPath := filepath.Join(setting.SSH.RootPath, authorizedPrincipalsFile)
  1132. tmpPath := fPath + ".tmp"
  1133. t, err := os.OpenFile(tmpPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o600)
  1134. if err != nil {
  1135. return err
  1136. }
  1137. defer func() {
  1138. t.Close()
  1139. os.Remove(tmpPath)
  1140. }()
  1141. if setting.SSH.AuthorizedPrincipalsBackup {
  1142. isExist, err := util.IsExist(fPath)
  1143. if err != nil {
  1144. log.Error("Unable to check if %s exists. Error: %v", fPath, err)
  1145. return err
  1146. }
  1147. if isExist {
  1148. bakPath := fmt.Sprintf("%s_%d.gitea_bak", fPath, time.Now().Unix())
  1149. if err = util.CopyFile(fPath, bakPath); err != nil {
  1150. return err
  1151. }
  1152. }
  1153. }
  1154. if err := regeneratePrincipalKeys(e, t); err != nil {
  1155. return err
  1156. }
  1157. t.Close()
  1158. return util.Rename(tmpPath, fPath)
  1159. }
  1160. // ListPrincipalKeys returns a list of principals belongs to given user.
  1161. func ListPrincipalKeys(uid int64, listOptions ListOptions) ([]*PublicKey, error) {
  1162. sess := x.Where("owner_id = ? AND type = ?", uid, KeyTypePrincipal)
  1163. if listOptions.Page != 0 {
  1164. sess = listOptions.setSessionPagination(sess)
  1165. keys := make([]*PublicKey, 0, listOptions.PageSize)
  1166. return keys, sess.Find(&keys)
  1167. }
  1168. keys := make([]*PublicKey, 0, 5)
  1169. return keys, sess.Find(&keys)
  1170. }
  1171. // RegeneratePrincipalKeys regenerates the authorized_principals file
  1172. func RegeneratePrincipalKeys(t io.StringWriter) error {
  1173. return regeneratePrincipalKeys(x, t)
  1174. }
  1175. func regeneratePrincipalKeys(e Engine, t io.StringWriter) error {
  1176. if err := e.Where("type = ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
  1177. _, err = t.WriteString((bean.(*PublicKey)).AuthorizedString())
  1178. return err
  1179. }); err != nil {
  1180. return err
  1181. }
  1182. fPath := filepath.Join(setting.SSH.RootPath, authorizedPrincipalsFile)
  1183. isExist, err := util.IsExist(fPath)
  1184. if err != nil {
  1185. log.Error("Unable to check if %s exists. Error: %v", fPath, err)
  1186. return err
  1187. }
  1188. if isExist {
  1189. f, err := os.Open(fPath)
  1190. if err != nil {
  1191. return err
  1192. }
  1193. scanner := bufio.NewScanner(f)
  1194. for scanner.Scan() {
  1195. line := scanner.Text()
  1196. if strings.HasPrefix(line, tplCommentPrefix) {
  1197. scanner.Scan()
  1198. continue
  1199. }
  1200. _, err = t.WriteString(line + "\n")
  1201. if err != nil {
  1202. f.Close()
  1203. return err
  1204. }
  1205. }
  1206. f.Close()
  1207. }
  1208. return nil
  1209. }