summaryrefslogtreecommitdiffstats
path: root/models/asymkey/ssh_key_principals.go
diff options
context:
space:
mode:
Diffstat (limited to 'models/asymkey/ssh_key_principals.go')
-rw-r--r--models/asymkey/ssh_key_principals.go96
1 files changed, 96 insertions, 0 deletions
diff --git a/models/asymkey/ssh_key_principals.go b/models/asymkey/ssh_key_principals.go
new file mode 100644
index 0000000..4e7dee2
--- /dev/null
+++ b/models/asymkey/ssh_key_principals.go
@@ -0,0 +1,96 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package asymkey
+
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ "code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/models/perm"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/util"
+)
+
+// AddPrincipalKey adds new principal to database and authorized_principals file.
+func AddPrincipalKey(ctx context.Context, ownerID int64, content string, authSourceID int64) (*PublicKey, error) {
+ dbCtx, committer, err := db.TxContext(ctx)
+ if err != nil {
+ return nil, err
+ }
+ defer committer.Close()
+
+ // Principals cannot be duplicated.
+ has, err := db.GetEngine(dbCtx).
+ Where("content = ? AND type = ?", content, KeyTypePrincipal).
+ Get(new(PublicKey))
+ if err != nil {
+ return nil, err
+ } else if has {
+ return nil, ErrKeyAlreadyExist{0, "", content}
+ }
+
+ key := &PublicKey{
+ OwnerID: ownerID,
+ Name: content,
+ Content: content,
+ Mode: perm.AccessModeWrite,
+ Type: KeyTypePrincipal,
+ LoginSourceID: authSourceID,
+ }
+ if err = db.Insert(dbCtx, key); err != nil {
+ return nil, fmt.Errorf("addKey: %w", err)
+ }
+
+ if err = committer.Commit(); err != nil {
+ return nil, err
+ }
+
+ committer.Close()
+
+ return key, RewriteAllPrincipalKeys(ctx)
+}
+
+// CheckPrincipalKeyString strips spaces and returns an error if the given principal contains newlines
+func CheckPrincipalKeyString(ctx context.Context, user *user_model.User, content string) (_ string, err error) {
+ if setting.SSH.Disabled {
+ return "", db.ErrSSHDisabled{}
+ }
+
+ content = strings.TrimSpace(content)
+ if strings.ContainsAny(content, "\r\n") {
+ return "", util.NewInvalidArgumentErrorf("only a single line with a single principal please")
+ }
+
+ // check all the allowed principals, email, username or anything
+ // if any matches, return ok
+ for _, v := range setting.SSH.AuthorizedPrincipalsAllow {
+ switch v {
+ case "anything":
+ return content, nil
+ case "email":
+ emails, err := user_model.GetEmailAddresses(ctx, user.ID)
+ if err != nil {
+ return "", err
+ }
+ for _, email := range emails {
+ if !email.IsActivated {
+ continue
+ }
+ if content == email.Email {
+ return content, nil
+ }
+ }
+
+ case "username":
+ if content == user.Name {
+ return content, nil
+ }
+ }
+ }
+
+ return "", fmt.Errorf("didn't match allowed principals: %s", setting.SSH.AuthorizedPrincipalsAllow)
+}