code.gitea.io/gitea@v1.21.7/routers/web/user/setting/keys.go (about) 1 // Copyright 2014 The Gogs Authors. All rights reserved. 2 // Copyright 2018 The Gitea Authors. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 5 package setting 6 7 import ( 8 "net/http" 9 10 asymkey_model "code.gitea.io/gitea/models/asymkey" 11 "code.gitea.io/gitea/models/db" 12 "code.gitea.io/gitea/modules/base" 13 "code.gitea.io/gitea/modules/context" 14 "code.gitea.io/gitea/modules/setting" 15 "code.gitea.io/gitea/modules/web" 16 asymkey_service "code.gitea.io/gitea/services/asymkey" 17 "code.gitea.io/gitea/services/forms" 18 ) 19 20 const ( 21 tplSettingsKeys base.TplName = "user/settings/keys" 22 ) 23 24 // Keys render user's SSH/GPG public keys page 25 func Keys(ctx *context.Context) { 26 ctx.Data["Title"] = ctx.Tr("settings.ssh_gpg_keys") 27 ctx.Data["PageIsSettingsKeys"] = true 28 ctx.Data["DisableSSH"] = setting.SSH.Disabled 29 ctx.Data["BuiltinSSH"] = setting.SSH.StartBuiltinServer 30 ctx.Data["AllowPrincipals"] = setting.SSH.AuthorizedPrincipalsEnabled 31 32 loadKeysData(ctx) 33 34 ctx.HTML(http.StatusOK, tplSettingsKeys) 35 } 36 37 // KeysPost response for change user's SSH/GPG keys 38 func KeysPost(ctx *context.Context) { 39 form := web.GetForm(ctx).(*forms.AddKeyForm) 40 ctx.Data["Title"] = ctx.Tr("settings") 41 ctx.Data["PageIsSettingsKeys"] = true 42 ctx.Data["DisableSSH"] = setting.SSH.Disabled 43 ctx.Data["BuiltinSSH"] = setting.SSH.StartBuiltinServer 44 ctx.Data["AllowPrincipals"] = setting.SSH.AuthorizedPrincipalsEnabled 45 46 if ctx.HasError() { 47 loadKeysData(ctx) 48 49 ctx.HTML(http.StatusOK, tplSettingsKeys) 50 return 51 } 52 switch form.Type { 53 case "principal": 54 content, err := asymkey_model.CheckPrincipalKeyString(ctx, ctx.Doer, form.Content) 55 if err != nil { 56 if db.IsErrSSHDisabled(err) { 57 ctx.Flash.Info(ctx.Tr("settings.ssh_disabled")) 58 } else { 59 ctx.Flash.Error(ctx.Tr("form.invalid_ssh_principal", err.Error())) 60 } 61 ctx.Redirect(setting.AppSubURL + "/user/settings/keys") 62 return 63 } 64 if _, err = asymkey_model.AddPrincipalKey(ctx.Doer.ID, content, 0); err != nil { 65 ctx.Data["HasPrincipalError"] = true 66 switch { 67 case asymkey_model.IsErrKeyAlreadyExist(err), asymkey_model.IsErrKeyNameAlreadyUsed(err): 68 loadKeysData(ctx) 69 70 ctx.Data["Err_Content"] = true 71 ctx.RenderWithErr(ctx.Tr("settings.ssh_principal_been_used"), tplSettingsKeys, &form) 72 default: 73 ctx.ServerError("AddPrincipalKey", err) 74 } 75 return 76 } 77 ctx.Flash.Success(ctx.Tr("settings.add_principal_success", form.Content)) 78 ctx.Redirect(setting.AppSubURL + "/user/settings/keys") 79 case "gpg": 80 token := asymkey_model.VerificationToken(ctx.Doer, 1) 81 lastToken := asymkey_model.VerificationToken(ctx.Doer, 0) 82 83 keys, err := asymkey_model.AddGPGKey(ctx, ctx.Doer.ID, form.Content, token, form.Signature) 84 if err != nil && asymkey_model.IsErrGPGInvalidTokenSignature(err) { 85 keys, err = asymkey_model.AddGPGKey(ctx, ctx.Doer.ID, form.Content, lastToken, form.Signature) 86 } 87 if err != nil { 88 ctx.Data["HasGPGError"] = true 89 switch { 90 case asymkey_model.IsErrGPGKeyParsing(err): 91 ctx.Flash.Error(ctx.Tr("form.invalid_gpg_key", err.Error())) 92 ctx.Redirect(setting.AppSubURL + "/user/settings/keys") 93 case asymkey_model.IsErrGPGKeyIDAlreadyUsed(err): 94 loadKeysData(ctx) 95 96 ctx.Data["Err_Content"] = true 97 ctx.RenderWithErr(ctx.Tr("settings.gpg_key_id_used"), tplSettingsKeys, &form) 98 case asymkey_model.IsErrGPGInvalidTokenSignature(err): 99 loadKeysData(ctx) 100 ctx.Data["Err_Content"] = true 101 ctx.Data["Err_Signature"] = true 102 keyID := err.(asymkey_model.ErrGPGInvalidTokenSignature).ID 103 ctx.Data["KeyID"] = keyID 104 ctx.Data["PaddedKeyID"] = asymkey_model.PaddedKeyID(keyID) 105 ctx.RenderWithErr(ctx.Tr("settings.gpg_invalid_token_signature"), tplSettingsKeys, &form) 106 case asymkey_model.IsErrGPGNoEmailFound(err): 107 loadKeysData(ctx) 108 109 ctx.Data["Err_Content"] = true 110 ctx.Data["Err_Signature"] = true 111 keyID := err.(asymkey_model.ErrGPGNoEmailFound).ID 112 ctx.Data["KeyID"] = keyID 113 ctx.Data["PaddedKeyID"] = asymkey_model.PaddedKeyID(keyID) 114 ctx.RenderWithErr(ctx.Tr("settings.gpg_no_key_email_found"), tplSettingsKeys, &form) 115 default: 116 ctx.ServerError("AddPublicKey", err) 117 } 118 return 119 } 120 keyIDs := "" 121 for _, key := range keys { 122 keyIDs += key.KeyID 123 keyIDs += ", " 124 } 125 if len(keyIDs) > 0 { 126 keyIDs = keyIDs[:len(keyIDs)-2] 127 } 128 ctx.Flash.Success(ctx.Tr("settings.add_gpg_key_success", keyIDs)) 129 ctx.Redirect(setting.AppSubURL + "/user/settings/keys") 130 case "verify_gpg": 131 token := asymkey_model.VerificationToken(ctx.Doer, 1) 132 lastToken := asymkey_model.VerificationToken(ctx.Doer, 0) 133 134 keyID, err := asymkey_model.VerifyGPGKey(ctx.Doer.ID, form.KeyID, token, form.Signature) 135 if err != nil && asymkey_model.IsErrGPGInvalidTokenSignature(err) { 136 keyID, err = asymkey_model.VerifyGPGKey(ctx.Doer.ID, form.KeyID, lastToken, form.Signature) 137 } 138 if err != nil { 139 ctx.Data["HasGPGVerifyError"] = true 140 switch { 141 case asymkey_model.IsErrGPGInvalidTokenSignature(err): 142 loadKeysData(ctx) 143 ctx.Data["VerifyingID"] = form.KeyID 144 ctx.Data["Err_Signature"] = true 145 keyID := err.(asymkey_model.ErrGPGInvalidTokenSignature).ID 146 ctx.Data["KeyID"] = keyID 147 ctx.Data["PaddedKeyID"] = asymkey_model.PaddedKeyID(keyID) 148 ctx.RenderWithErr(ctx.Tr("settings.gpg_invalid_token_signature"), tplSettingsKeys, &form) 149 default: 150 ctx.ServerError("VerifyGPG", err) 151 } 152 } 153 ctx.Flash.Success(ctx.Tr("settings.verify_gpg_key_success", keyID)) 154 ctx.Redirect(setting.AppSubURL + "/user/settings/keys") 155 case "ssh": 156 content, err := asymkey_model.CheckPublicKeyString(form.Content) 157 if err != nil { 158 if db.IsErrSSHDisabled(err) { 159 ctx.Flash.Info(ctx.Tr("settings.ssh_disabled")) 160 } else if asymkey_model.IsErrKeyUnableVerify(err) { 161 ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key")) 162 } else if err == asymkey_model.ErrKeyIsPrivate { 163 ctx.Flash.Error(ctx.Tr("form.must_use_public_key")) 164 } else { 165 ctx.Flash.Error(ctx.Tr("form.invalid_ssh_key", err.Error())) 166 } 167 ctx.Redirect(setting.AppSubURL + "/user/settings/keys") 168 return 169 } 170 171 if _, err = asymkey_model.AddPublicKey(ctx.Doer.ID, form.Title, content, 0); err != nil { 172 ctx.Data["HasSSHError"] = true 173 switch { 174 case asymkey_model.IsErrKeyAlreadyExist(err): 175 loadKeysData(ctx) 176 177 ctx.Data["Err_Content"] = true 178 ctx.RenderWithErr(ctx.Tr("settings.ssh_key_been_used"), tplSettingsKeys, &form) 179 case asymkey_model.IsErrKeyNameAlreadyUsed(err): 180 loadKeysData(ctx) 181 182 ctx.Data["Err_Title"] = true 183 ctx.RenderWithErr(ctx.Tr("settings.ssh_key_name_used"), tplSettingsKeys, &form) 184 case asymkey_model.IsErrKeyUnableVerify(err): 185 ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key")) 186 ctx.Redirect(setting.AppSubURL + "/user/settings/keys") 187 default: 188 ctx.ServerError("AddPublicKey", err) 189 } 190 return 191 } 192 ctx.Flash.Success(ctx.Tr("settings.add_key_success", form.Title)) 193 ctx.Redirect(setting.AppSubURL + "/user/settings/keys") 194 case "verify_ssh": 195 token := asymkey_model.VerificationToken(ctx.Doer, 1) 196 lastToken := asymkey_model.VerificationToken(ctx.Doer, 0) 197 198 fingerprint, err := asymkey_model.VerifySSHKey(ctx.Doer.ID, form.Fingerprint, token, form.Signature) 199 if err != nil && asymkey_model.IsErrSSHInvalidTokenSignature(err) { 200 fingerprint, err = asymkey_model.VerifySSHKey(ctx.Doer.ID, form.Fingerprint, lastToken, form.Signature) 201 } 202 if err != nil { 203 ctx.Data["HasSSHVerifyError"] = true 204 switch { 205 case asymkey_model.IsErrSSHInvalidTokenSignature(err): 206 loadKeysData(ctx) 207 ctx.Data["Err_Signature"] = true 208 ctx.Data["Fingerprint"] = err.(asymkey_model.ErrSSHInvalidTokenSignature).Fingerprint 209 ctx.RenderWithErr(ctx.Tr("settings.ssh_invalid_token_signature"), tplSettingsKeys, &form) 210 default: 211 ctx.ServerError("VerifySSH", err) 212 } 213 } 214 ctx.Flash.Success(ctx.Tr("settings.verify_ssh_key_success", fingerprint)) 215 ctx.Redirect(setting.AppSubURL + "/user/settings/keys") 216 217 default: 218 ctx.Flash.Warning("Function not implemented") 219 ctx.Redirect(setting.AppSubURL + "/user/settings/keys") 220 } 221 } 222 223 // DeleteKey response for delete user's SSH/GPG key 224 func DeleteKey(ctx *context.Context) { 225 switch ctx.FormString("type") { 226 case "gpg": 227 if err := asymkey_model.DeleteGPGKey(ctx, ctx.Doer, ctx.FormInt64("id")); err != nil { 228 ctx.Flash.Error("DeleteGPGKey: " + err.Error()) 229 } else { 230 ctx.Flash.Success(ctx.Tr("settings.gpg_key_deletion_success")) 231 } 232 case "ssh": 233 keyID := ctx.FormInt64("id") 234 external, err := asymkey_model.PublicKeyIsExternallyManaged(keyID) 235 if err != nil { 236 ctx.ServerError("sshKeysExternalManaged", err) 237 return 238 } 239 if external { 240 ctx.Flash.Error(ctx.Tr("settings.ssh_externally_managed")) 241 ctx.Redirect(setting.AppSubURL + "/user/settings/keys") 242 return 243 } 244 if err := asymkey_service.DeletePublicKey(ctx, ctx.Doer, keyID); err != nil { 245 ctx.Flash.Error("DeletePublicKey: " + err.Error()) 246 } else { 247 ctx.Flash.Success(ctx.Tr("settings.ssh_key_deletion_success")) 248 } 249 case "principal": 250 if err := asymkey_service.DeletePublicKey(ctx, ctx.Doer, ctx.FormInt64("id")); err != nil { 251 ctx.Flash.Error("DeletePublicKey: " + err.Error()) 252 } else { 253 ctx.Flash.Success(ctx.Tr("settings.ssh_principal_deletion_success")) 254 } 255 default: 256 ctx.Flash.Warning("Function not implemented") 257 ctx.Redirect(setting.AppSubURL + "/user/settings/keys") 258 } 259 ctx.JSONRedirect(setting.AppSubURL + "/user/settings/keys") 260 } 261 262 func loadKeysData(ctx *context.Context) { 263 keys, err := asymkey_model.ListPublicKeys(ctx.Doer.ID, db.ListOptions{}) 264 if err != nil { 265 ctx.ServerError("ListPublicKeys", err) 266 return 267 } 268 ctx.Data["Keys"] = keys 269 270 externalKeys, err := asymkey_model.PublicKeysAreExternallyManaged(keys) 271 if err != nil { 272 ctx.ServerError("ListPublicKeys", err) 273 return 274 } 275 ctx.Data["ExternalKeys"] = externalKeys 276 277 gpgkeys, err := asymkey_model.ListGPGKeys(ctx, ctx.Doer.ID, db.ListOptions{}) 278 if err != nil { 279 ctx.ServerError("ListGPGKeys", err) 280 return 281 } 282 ctx.Data["GPGKeys"] = gpgkeys 283 tokenToSign := asymkey_model.VerificationToken(ctx.Doer, 1) 284 285 // generate a new aes cipher using the csrfToken 286 ctx.Data["TokenToSign"] = tokenToSign 287 288 principals, err := asymkey_model.ListPrincipalKeys(ctx.Doer.ID, db.ListOptions{}) 289 if err != nil { 290 ctx.ServerError("ListPrincipalKeys", err) 291 return 292 } 293 ctx.Data["Principals"] = principals 294 295 ctx.Data["VerifyingID"] = ctx.FormString("verify_gpg") 296 ctx.Data["VerifyingFingerprint"] = ctx.FormString("verify_ssh") 297 }