You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

ssh_key.go 37 kB

11 years ago
11 years ago
Add ssh certificate support (#12281) * Add ssh certificate support * Add ssh certificate support to builtin ssh * Write trusted-user-ca-keys.pem based on configuration * Update app.example.ini * Update templates/user/settings/keys_principal.tmpl Co-authored-by: silverwind <me@silverwind.io> * Remove unused locale string * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * Add missing creation of SSH.Rootpath * Update cheatsheet, example and locale strings * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go * Optimizations based on feedback * Validate CA keys for external sshd * Add filename option and change default filename Add a SSH_TRUSTED_USER_CA_KEYS_FILENAME option which default is RUN_USER/.ssh/gitea-trusted-user-ca-keys.pem Do not write a file when SSH_TRUSTED_USER_CA_KEYS is empty. Add some more documentation. * Remove unneeded principalkey functions * Add blank line * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * Add SSH_AUTHORIZED_PRINCIPALS_ALLOW option This adds a SSH_AUTHORIZED_PRINCIPALS_ALLOW which is default email,username this means that users only can add the principals that match their email or username. To allow anything the admin need to set the option anything. This allows for a safe default in gitea which protects against malicious users using other user's prinicipals. (before that user could set it). This commit also has some small other fixes from the last code review. * Rewrite principal keys file on user deletion * Use correct rewrite method * Set correct AuthorizedPrincipalsBackup default setting * Rewrite principalsfile when adding principals * Add update authorized_principals option to admin dashboard * Handle non-primary emails Signed-off-by: Andrew Thornton <art27@cantab.net> * Add the command actually to the dashboard template * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * By default do not show principal options unless there are CA keys set or they are explicitly set Signed-off-by: Andrew Thornton <art27@cantab.net> * allow settings when enabled * Fix typos in TrustedUserCAKeys path * Allow every CASignatureAlgorithms algorithm As this depends on the content of TrustedUserCAKeys we should allow all signature algorithms as admins can choose the specific algorithm on their signing CA * Update models/ssh_key.go Co-authored-by: Lauris BH <lauris@nix.lv> * Fix linting issue Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
4 years ago
11 years ago
8 years ago
8 years ago
Add ssh certificate support (#12281) * Add ssh certificate support * Add ssh certificate support to builtin ssh * Write trusted-user-ca-keys.pem based on configuration * Update app.example.ini * Update templates/user/settings/keys_principal.tmpl Co-authored-by: silverwind <me@silverwind.io> * Remove unused locale string * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * Add missing creation of SSH.Rootpath * Update cheatsheet, example and locale strings * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go * Optimizations based on feedback * Validate CA keys for external sshd * Add filename option and change default filename Add a SSH_TRUSTED_USER_CA_KEYS_FILENAME option which default is RUN_USER/.ssh/gitea-trusted-user-ca-keys.pem Do not write a file when SSH_TRUSTED_USER_CA_KEYS is empty. Add some more documentation. * Remove unneeded principalkey functions * Add blank line * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * Add SSH_AUTHORIZED_PRINCIPALS_ALLOW option This adds a SSH_AUTHORIZED_PRINCIPALS_ALLOW which is default email,username this means that users only can add the principals that match their email or username. To allow anything the admin need to set the option anything. This allows for a safe default in gitea which protects against malicious users using other user's prinicipals. (before that user could set it). This commit also has some small other fixes from the last code review. * Rewrite principal keys file on user deletion * Use correct rewrite method * Set correct AuthorizedPrincipalsBackup default setting * Rewrite principalsfile when adding principals * Add update authorized_principals option to admin dashboard * Handle non-primary emails Signed-off-by: Andrew Thornton <art27@cantab.net> * Add the command actually to the dashboard template * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * By default do not show principal options unless there are CA keys set or they are explicitly set Signed-off-by: Andrew Thornton <art27@cantab.net> * allow settings when enabled * Fix typos in TrustedUserCAKeys path * Allow every CASignatureAlgorithms algorithm As this depends on the content of TrustedUserCAKeys we should allow all signature algorithms as admins can choose the specific algorithm on their signing CA * Update models/ssh_key.go Co-authored-by: Lauris BH <lauris@nix.lv> * Fix linting issue Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
4 years ago
10 years ago
10 years ago
Better logging (#6038) (#6095) * Panic don't fatal on create new logger Fixes #5854 Signed-off-by: Andrew Thornton <art27@cantab.net> * partial broken * Update the logging infrastrcture Signed-off-by: Andrew Thornton <art27@cantab.net> * Reset the skip levels for Fatal and Error Signed-off-by: Andrew Thornton <art27@cantab.net> * broken ncsa * More log.Error fixes Signed-off-by: Andrew Thornton <art27@cantab.net> * Remove nal * set log-levels to lowercase * Make console_test test all levels * switch to lowercased levels * OK now working * Fix vetting issues * Fix lint * Fix tests * change default logging to match current gitea * Improve log testing Signed-off-by: Andrew Thornton <art27@cantab.net> * reset error skip levels to 0 * Update documentation and access logger configuration * Redirect the router log back to gitea if redirect macaron log but also allow setting the log level - i.e. TRACE * Fix broken level caching * Refactor the router log * Add Router logger * Add colorizing options * Adjust router colors * Only create logger if they will be used * update app.ini.sample * rename Attribute ColorAttribute * Change from white to green for function * Set fatal/error levels * Restore initial trace logger * Fix Trace arguments in modules/auth/auth.go * Properly handle XORMLogger * Improve admin/config page * fix fmt * Add auto-compression of old logs * Update error log levels * Remove the unnecessary skip argument from Error, Fatal and Critical * Add stacktrace support * Fix tests * Remove x/sync from vendors? * Add stderr option to console logger * Use filepath.ToSlash to protect against Windows in tests * Remove prefixed underscores from names in colors.go * Remove not implemented database logger This was removed from Gogs on 4 Mar 2016 but left in the configuration since then. * Ensure that log paths are relative to ROOT_PATH * use path.Join * rename jsonConfig to logConfig * Rename "config" to "jsonConfig" to make it clearer * Requested changes * Requested changes: XormLogger * Try to color the windows terminal If successful default to colorizing the console logs * fixup * Colorize initially too * update vendor * Colorize logs on default and remove if this is not a colorizing logger * Fix documentation * fix test * Use go-isatty to detect if on windows we are on msys or cygwin * Fix spelling mistake * Add missing vendors * More changes * Rationalise the ANSI writer protection * Adjust colors on advice from @0x5c * Make Flags a comma separated list * Move to use the windows constant for ENABLE_VIRTUAL_TERMINAL_PROCESSING * Ensure matching is done on the non-colored message - to simpify EXPRESSION
6 years ago
Add ssh certificate support (#12281) * Add ssh certificate support * Add ssh certificate support to builtin ssh * Write trusted-user-ca-keys.pem based on configuration * Update app.example.ini * Update templates/user/settings/keys_principal.tmpl Co-authored-by: silverwind <me@silverwind.io> * Remove unused locale string * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * Add missing creation of SSH.Rootpath * Update cheatsheet, example and locale strings * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go * Optimizations based on feedback * Validate CA keys for external sshd * Add filename option and change default filename Add a SSH_TRUSTED_USER_CA_KEYS_FILENAME option which default is RUN_USER/.ssh/gitea-trusted-user-ca-keys.pem Do not write a file when SSH_TRUSTED_USER_CA_KEYS is empty. Add some more documentation. * Remove unneeded principalkey functions * Add blank line * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * Add SSH_AUTHORIZED_PRINCIPALS_ALLOW option This adds a SSH_AUTHORIZED_PRINCIPALS_ALLOW which is default email,username this means that users only can add the principals that match their email or username. To allow anything the admin need to set the option anything. This allows for a safe default in gitea which protects against malicious users using other user's prinicipals. (before that user could set it). This commit also has some small other fixes from the last code review. * Rewrite principal keys file on user deletion * Use correct rewrite method * Set correct AuthorizedPrincipalsBackup default setting * Rewrite principalsfile when adding principals * Add update authorized_principals option to admin dashboard * Handle non-primary emails Signed-off-by: Andrew Thornton <art27@cantab.net> * Add the command actually to the dashboard template * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * By default do not show principal options unless there are CA keys set or they are explicitly set Signed-off-by: Andrew Thornton <art27@cantab.net> * allow settings when enabled * Fix typos in TrustedUserCAKeys path * Allow every CASignatureAlgorithms algorithm As this depends on the content of TrustedUserCAKeys we should allow all signature algorithms as admins can choose the specific algorithm on their signing CA * Update models/ssh_key.go Co-authored-by: Lauris BH <lauris@nix.lv> * Fix linting issue Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
4 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
Add ssh certificate support (#12281) * Add ssh certificate support * Add ssh certificate support to builtin ssh * Write trusted-user-ca-keys.pem based on configuration * Update app.example.ini * Update templates/user/settings/keys_principal.tmpl Co-authored-by: silverwind <me@silverwind.io> * Remove unused locale string * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * Add missing creation of SSH.Rootpath * Update cheatsheet, example and locale strings * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go * Optimizations based on feedback * Validate CA keys for external sshd * Add filename option and change default filename Add a SSH_TRUSTED_USER_CA_KEYS_FILENAME option which default is RUN_USER/.ssh/gitea-trusted-user-ca-keys.pem Do not write a file when SSH_TRUSTED_USER_CA_KEYS is empty. Add some more documentation. * Remove unneeded principalkey functions * Add blank line * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * Add SSH_AUTHORIZED_PRINCIPALS_ALLOW option This adds a SSH_AUTHORIZED_PRINCIPALS_ALLOW which is default email,username this means that users only can add the principals that match their email or username. To allow anything the admin need to set the option anything. This allows for a safe default in gitea which protects against malicious users using other user's prinicipals. (before that user could set it). This commit also has some small other fixes from the last code review. * Rewrite principal keys file on user deletion * Use correct rewrite method * Set correct AuthorizedPrincipalsBackup default setting * Rewrite principalsfile when adding principals * Add update authorized_principals option to admin dashboard * Handle non-primary emails Signed-off-by: Andrew Thornton <art27@cantab.net> * Add the command actually to the dashboard template * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * By default do not show principal options unless there are CA keys set or they are explicitly set Signed-off-by: Andrew Thornton <art27@cantab.net> * allow settings when enabled * Fix typos in TrustedUserCAKeys path * Allow every CASignatureAlgorithms algorithm As this depends on the content of TrustedUserCAKeys we should allow all signature algorithms as admins can choose the specific algorithm on their signing CA * Update models/ssh_key.go Co-authored-by: Lauris BH <lauris@nix.lv> * Fix linting issue Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
4 years ago
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
5 years ago
Add ssh certificate support (#12281) * Add ssh certificate support * Add ssh certificate support to builtin ssh * Write trusted-user-ca-keys.pem based on configuration * Update app.example.ini * Update templates/user/settings/keys_principal.tmpl Co-authored-by: silverwind <me@silverwind.io> * Remove unused locale string * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * Add missing creation of SSH.Rootpath * Update cheatsheet, example and locale strings * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go * Optimizations based on feedback * Validate CA keys for external sshd * Add filename option and change default filename Add a SSH_TRUSTED_USER_CA_KEYS_FILENAME option which default is RUN_USER/.ssh/gitea-trusted-user-ca-keys.pem Do not write a file when SSH_TRUSTED_USER_CA_KEYS is empty. Add some more documentation. * Remove unneeded principalkey functions * Add blank line * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * Add SSH_AUTHORIZED_PRINCIPALS_ALLOW option This adds a SSH_AUTHORIZED_PRINCIPALS_ALLOW which is default email,username this means that users only can add the principals that match their email or username. To allow anything the admin need to set the option anything. This allows for a safe default in gitea which protects against malicious users using other user's prinicipals. (before that user could set it). This commit also has some small other fixes from the last code review. * Rewrite principal keys file on user deletion * Use correct rewrite method * Set correct AuthorizedPrincipalsBackup default setting * Rewrite principalsfile when adding principals * Add update authorized_principals option to admin dashboard * Handle non-primary emails Signed-off-by: Andrew Thornton <art27@cantab.net> * Add the command actually to the dashboard template * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * By default do not show principal options unless there are CA keys set or they are explicitly set Signed-off-by: Andrew Thornton <art27@cantab.net> * allow settings when enabled * Fix typos in TrustedUserCAKeys path * Allow every CASignatureAlgorithms algorithm As this depends on the content of TrustedUserCAKeys we should allow all signature algorithms as admins can choose the specific algorithm on their signing CA * Update models/ssh_key.go Co-authored-by: Lauris BH <lauris@nix.lv> * Fix linting issue Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
4 years ago
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
5 years ago
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
5 years ago
9 years ago
9 years ago
Add ssh certificate support (#12281) * Add ssh certificate support * Add ssh certificate support to builtin ssh * Write trusted-user-ca-keys.pem based on configuration * Update app.example.ini * Update templates/user/settings/keys_principal.tmpl Co-authored-by: silverwind <me@silverwind.io> * Remove unused locale string * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * Add missing creation of SSH.Rootpath * Update cheatsheet, example and locale strings * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go * Optimizations based on feedback * Validate CA keys for external sshd * Add filename option and change default filename Add a SSH_TRUSTED_USER_CA_KEYS_FILENAME option which default is RUN_USER/.ssh/gitea-trusted-user-ca-keys.pem Do not write a file when SSH_TRUSTED_USER_CA_KEYS is empty. Add some more documentation. * Remove unneeded principalkey functions * Add blank line * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * Add SSH_AUTHORIZED_PRINCIPALS_ALLOW option This adds a SSH_AUTHORIZED_PRINCIPALS_ALLOW which is default email,username this means that users only can add the principals that match their email or username. To allow anything the admin need to set the option anything. This allows for a safe default in gitea which protects against malicious users using other user's prinicipals. (before that user could set it). This commit also has some small other fixes from the last code review. * Rewrite principal keys file on user deletion * Use correct rewrite method * Set correct AuthorizedPrincipalsBackup default setting * Rewrite principalsfile when adding principals * Add update authorized_principals option to admin dashboard * Handle non-primary emails Signed-off-by: Andrew Thornton <art27@cantab.net> * Add the command actually to the dashboard template * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * By default do not show principal options unless there are CA keys set or they are explicitly set Signed-off-by: Andrew Thornton <art27@cantab.net> * allow settings when enabled * Fix typos in TrustedUserCAKeys path * Allow every CASignatureAlgorithms algorithm As this depends on the content of TrustedUserCAKeys we should allow all signature algorithms as admins can choose the specific algorithm on their signing CA * Update models/ssh_key.go Co-authored-by: Lauris BH <lauris@nix.lv> * Fix linting issue Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
4 years ago
Add ssh certificate support (#12281) * Add ssh certificate support * Add ssh certificate support to builtin ssh * Write trusted-user-ca-keys.pem based on configuration * Update app.example.ini * Update templates/user/settings/keys_principal.tmpl Co-authored-by: silverwind <me@silverwind.io> * Remove unused locale string * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * Add missing creation of SSH.Rootpath * Update cheatsheet, example and locale strings * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go * Optimizations based on feedback * Validate CA keys for external sshd * Add filename option and change default filename Add a SSH_TRUSTED_USER_CA_KEYS_FILENAME option which default is RUN_USER/.ssh/gitea-trusted-user-ca-keys.pem Do not write a file when SSH_TRUSTED_USER_CA_KEYS is empty. Add some more documentation. * Remove unneeded principalkey functions * Add blank line * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * Add SSH_AUTHORIZED_PRINCIPALS_ALLOW option This adds a SSH_AUTHORIZED_PRINCIPALS_ALLOW which is default email,username this means that users only can add the principals that match their email or username. To allow anything the admin need to set the option anything. This allows for a safe default in gitea which protects against malicious users using other user's prinicipals. (before that user could set it). This commit also has some small other fixes from the last code review. * Rewrite principal keys file on user deletion * Use correct rewrite method * Set correct AuthorizedPrincipalsBackup default setting * Rewrite principalsfile when adding principals * Add update authorized_principals option to admin dashboard * Handle non-primary emails Signed-off-by: Andrew Thornton <art27@cantab.net> * Add the command actually to the dashboard template * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * By default do not show principal options unless there are CA keys set or they are explicitly set Signed-off-by: Andrew Thornton <art27@cantab.net> * allow settings when enabled * Fix typos in TrustedUserCAKeys path * Allow every CASignatureAlgorithms algorithm As this depends on the content of TrustedUserCAKeys we should allow all signature algorithms as admins can choose the specific algorithm on their signing CA * Update models/ssh_key.go Co-authored-by: Lauris BH <lauris@nix.lv> * Fix linting issue Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
4 years ago
Add ssh certificate support (#12281) * Add ssh certificate support * Add ssh certificate support to builtin ssh * Write trusted-user-ca-keys.pem based on configuration * Update app.example.ini * Update templates/user/settings/keys_principal.tmpl Co-authored-by: silverwind <me@silverwind.io> * Remove unused locale string * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * Add missing creation of SSH.Rootpath * Update cheatsheet, example and locale strings * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go * Optimizations based on feedback * Validate CA keys for external sshd * Add filename option and change default filename Add a SSH_TRUSTED_USER_CA_KEYS_FILENAME option which default is RUN_USER/.ssh/gitea-trusted-user-ca-keys.pem Do not write a file when SSH_TRUSTED_USER_CA_KEYS is empty. Add some more documentation. * Remove unneeded principalkey functions * Add blank line * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * Add SSH_AUTHORIZED_PRINCIPALS_ALLOW option This adds a SSH_AUTHORIZED_PRINCIPALS_ALLOW which is default email,username this means that users only can add the principals that match their email or username. To allow anything the admin need to set the option anything. This allows for a safe default in gitea which protects against malicious users using other user's prinicipals. (before that user could set it). This commit also has some small other fixes from the last code review. * Rewrite principal keys file on user deletion * Use correct rewrite method * Set correct AuthorizedPrincipalsBackup default setting * Rewrite principalsfile when adding principals * Add update authorized_principals option to admin dashboard * Handle non-primary emails Signed-off-by: Andrew Thornton <art27@cantab.net> * Add the command actually to the dashboard template * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * By default do not show principal options unless there are CA keys set or they are explicitly set Signed-off-by: Andrew Thornton <art27@cantab.net> * allow settings when enabled * Fix typos in TrustedUserCAKeys path * Allow every CASignatureAlgorithms algorithm As this depends on the content of TrustedUserCAKeys we should allow all signature algorithms as admins can choose the specific algorithm on their signing CA * Update models/ssh_key.go Co-authored-by: Lauris BH <lauris@nix.lv> * Fix linting issue Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
4 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
5 years ago
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
5 years ago
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
5 years ago
Add ssh certificate support (#12281) * Add ssh certificate support * Add ssh certificate support to builtin ssh * Write trusted-user-ca-keys.pem based on configuration * Update app.example.ini * Update templates/user/settings/keys_principal.tmpl Co-authored-by: silverwind <me@silverwind.io> * Remove unused locale string * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * Add missing creation of SSH.Rootpath * Update cheatsheet, example and locale strings * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go * Optimizations based on feedback * Validate CA keys for external sshd * Add filename option and change default filename Add a SSH_TRUSTED_USER_CA_KEYS_FILENAME option which default is RUN_USER/.ssh/gitea-trusted-user-ca-keys.pem Do not write a file when SSH_TRUSTED_USER_CA_KEYS is empty. Add some more documentation. * Remove unneeded principalkey functions * Add blank line * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * Add SSH_AUTHORIZED_PRINCIPALS_ALLOW option This adds a SSH_AUTHORIZED_PRINCIPALS_ALLOW which is default email,username this means that users only can add the principals that match their email or username. To allow anything the admin need to set the option anything. This allows for a safe default in gitea which protects against malicious users using other user's prinicipals. (before that user could set it). This commit also has some small other fixes from the last code review. * Rewrite principal keys file on user deletion * Use correct rewrite method * Set correct AuthorizedPrincipalsBackup default setting * Rewrite principalsfile when adding principals * Add update authorized_principals option to admin dashboard * Handle non-primary emails Signed-off-by: Andrew Thornton <art27@cantab.net> * Add the command actually to the dashboard template * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * By default do not show principal options unless there are CA keys set or they are explicitly set Signed-off-by: Andrew Thornton <art27@cantab.net> * allow settings when enabled * Fix typos in TrustedUserCAKeys path * Allow every CASignatureAlgorithms algorithm As this depends on the content of TrustedUserCAKeys we should allow all signature algorithms as admins can choose the specific algorithm on their signing CA * Update models/ssh_key.go Co-authored-by: Lauris BH <lauris@nix.lv> * Fix linting issue Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
4 years ago
Add ssh certificate support (#12281) * Add ssh certificate support * Add ssh certificate support to builtin ssh * Write trusted-user-ca-keys.pem based on configuration * Update app.example.ini * Update templates/user/settings/keys_principal.tmpl Co-authored-by: silverwind <me@silverwind.io> * Remove unused locale string * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * Add missing creation of SSH.Rootpath * Update cheatsheet, example and locale strings * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go * Optimizations based on feedback * Validate CA keys for external sshd * Add filename option and change default filename Add a SSH_TRUSTED_USER_CA_KEYS_FILENAME option which default is RUN_USER/.ssh/gitea-trusted-user-ca-keys.pem Do not write a file when SSH_TRUSTED_USER_CA_KEYS is empty. Add some more documentation. * Remove unneeded principalkey functions * Add blank line * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * Add SSH_AUTHORIZED_PRINCIPALS_ALLOW option This adds a SSH_AUTHORIZED_PRINCIPALS_ALLOW which is default email,username this means that users only can add the principals that match their email or username. To allow anything the admin need to set the option anything. This allows for a safe default in gitea which protects against malicious users using other user's prinicipals. (before that user could set it). This commit also has some small other fixes from the last code review. * Rewrite principal keys file on user deletion * Use correct rewrite method * Set correct AuthorizedPrincipalsBackup default setting * Rewrite principalsfile when adding principals * Add update authorized_principals option to admin dashboard * Handle non-primary emails Signed-off-by: Andrew Thornton <art27@cantab.net> * Add the command actually to the dashboard template * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * By default do not show principal options unless there are CA keys set or they are explicitly set Signed-off-by: Andrew Thornton <art27@cantab.net> * allow settings when enabled * Fix typos in TrustedUserCAKeys path * Allow every CASignatureAlgorithms algorithm As this depends on the content of TrustedUserCAKeys we should allow all signature algorithms as admins can choose the specific algorithm on their signing CA * Update models/ssh_key.go Co-authored-by: Lauris BH <lauris@nix.lv> * Fix linting issue Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
4 years ago
Add ssh certificate support (#12281) * Add ssh certificate support * Add ssh certificate support to builtin ssh * Write trusted-user-ca-keys.pem based on configuration * Update app.example.ini * Update templates/user/settings/keys_principal.tmpl Co-authored-by: silverwind <me@silverwind.io> * Remove unused locale string * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * Add missing creation of SSH.Rootpath * Update cheatsheet, example and locale strings * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go * Optimizations based on feedback * Validate CA keys for external sshd * Add filename option and change default filename Add a SSH_TRUSTED_USER_CA_KEYS_FILENAME option which default is RUN_USER/.ssh/gitea-trusted-user-ca-keys.pem Do not write a file when SSH_TRUSTED_USER_CA_KEYS is empty. Add some more documentation. * Remove unneeded principalkey functions * Add blank line * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * Add SSH_AUTHORIZED_PRINCIPALS_ALLOW option This adds a SSH_AUTHORIZED_PRINCIPALS_ALLOW which is default email,username this means that users only can add the principals that match their email or username. To allow anything the admin need to set the option anything. This allows for a safe default in gitea which protects against malicious users using other user's prinicipals. (before that user could set it). This commit also has some small other fixes from the last code review. * Rewrite principal keys file on user deletion * Use correct rewrite method * Set correct AuthorizedPrincipalsBackup default setting * Rewrite principalsfile when adding principals * Add update authorized_principals option to admin dashboard * Handle non-primary emails Signed-off-by: Andrew Thornton <art27@cantab.net> * Add the command actually to the dashboard template * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * By default do not show principal options unless there are CA keys set or they are explicitly set Signed-off-by: Andrew Thornton <art27@cantab.net> * allow settings when enabled * Fix typos in TrustedUserCAKeys path * Allow every CASignatureAlgorithms algorithm As this depends on the content of TrustedUserCAKeys we should allow all signature algorithms as admins can choose the specific algorithm on their signing CA * Update models/ssh_key.go Co-authored-by: Lauris BH <lauris@nix.lv> * Fix linting issue Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
4 years ago
Add ssh certificate support (#12281) * Add ssh certificate support * Add ssh certificate support to builtin ssh * Write trusted-user-ca-keys.pem based on configuration * Update app.example.ini * Update templates/user/settings/keys_principal.tmpl Co-authored-by: silverwind <me@silverwind.io> * Remove unused locale string * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update options/locale/locale_en-US.ini Co-authored-by: silverwind <me@silverwind.io> * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * Add missing creation of SSH.Rootpath * Update cheatsheet, example and locale strings * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go Co-authored-by: zeripath <art27@cantab.net> * Update models/ssh_key.go * Optimizations based on feedback * Validate CA keys for external sshd * Add filename option and change default filename Add a SSH_TRUSTED_USER_CA_KEYS_FILENAME option which default is RUN_USER/.ssh/gitea-trusted-user-ca-keys.pem Do not write a file when SSH_TRUSTED_USER_CA_KEYS is empty. Add some more documentation. * Remove unneeded principalkey functions * Add blank line * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * Add SSH_AUTHORIZED_PRINCIPALS_ALLOW option This adds a SSH_AUTHORIZED_PRINCIPALS_ALLOW which is default email,username this means that users only can add the principals that match their email or username. To allow anything the admin need to set the option anything. This allows for a safe default in gitea which protects against malicious users using other user's prinicipals. (before that user could set it). This commit also has some small other fixes from the last code review. * Rewrite principal keys file on user deletion * Use correct rewrite method * Set correct AuthorizedPrincipalsBackup default setting * Rewrite principalsfile when adding principals * Add update authorized_principals option to admin dashboard * Handle non-primary emails Signed-off-by: Andrew Thornton <art27@cantab.net> * Add the command actually to the dashboard template * Update models/ssh_key.go Co-authored-by: silverwind <me@silverwind.io> * By default do not show principal options unless there are CA keys set or they are explicitly set Signed-off-by: Andrew Thornton <art27@cantab.net> * allow settings when enabled * Fix typos in TrustedUserCAKeys path * Allow every CASignatureAlgorithms algorithm As this depends on the content of TrustedUserCAKeys we should allow all signature algorithms as admins can choose the specific algorithm on their signing CA * Update models/ssh_key.go Co-authored-by: Lauris BH <lauris@nix.lv> * Fix linting issue Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
4 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297
  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. "strings"
  22. "sync"
  23. "time"
  24. "code.gitea.io/gitea/modules/log"
  25. "code.gitea.io/gitea/modules/process"
  26. "code.gitea.io/gitea/modules/setting"
  27. "code.gitea.io/gitea/modules/timeutil"
  28. "code.gitea.io/gitea/modules/util"
  29. "github.com/unknwon/com"
  30. "golang.org/x/crypto/ssh"
  31. "xorm.io/builder"
  32. "xorm.io/xorm"
  33. )
  34. const (
  35. tplCommentPrefix = `# gitea public key`
  36. tplCommand = "%s --config=%s serv key-%d"
  37. tplPublicKey = tplCommentPrefix + "\n" + `command=%s,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s` + "\n"
  38. authorizedPrincipalsFile = "authorized_principals"
  39. )
  40. var sshOpLocker sync.Mutex
  41. // KeyType specifies the key type
  42. type KeyType int
  43. const (
  44. // KeyTypeUser specifies the user key
  45. KeyTypeUser = iota + 1
  46. // KeyTypeDeploy specifies the deploy key
  47. KeyTypeDeploy
  48. // KeyTypePrincipal specifies the authorized principal key
  49. KeyTypePrincipal
  50. )
  51. // PublicKey represents a user or deploy SSH public key.
  52. type PublicKey struct {
  53. ID int64 `xorm:"pk autoincr"`
  54. OwnerID int64 `xorm:"INDEX NOT NULL"`
  55. Name string `xorm:"NOT NULL"`
  56. Fingerprint string `xorm:"INDEX NOT NULL"`
  57. Content string `xorm:"TEXT NOT NULL"`
  58. Mode AccessMode `xorm:"NOT NULL DEFAULT 2"`
  59. Type KeyType `xorm:"NOT NULL DEFAULT 1"`
  60. LoginSourceID int64 `xorm:"NOT NULL DEFAULT 0"`
  61. CreatedUnix timeutil.TimeStamp `xorm:"created"`
  62. UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
  63. HasRecentActivity bool `xorm:"-"`
  64. HasUsed bool `xorm:"-"`
  65. }
  66. // AfterLoad is invoked from XORM after setting the values of all fields of this object.
  67. func (key *PublicKey) AfterLoad() {
  68. key.HasUsed = key.UpdatedUnix > key.CreatedUnix
  69. key.HasRecentActivity = key.UpdatedUnix.AddDuration(7*24*time.Hour) > timeutil.TimeStampNow()
  70. }
  71. // OmitEmail returns content of public key without email address.
  72. func (key *PublicKey) OmitEmail() string {
  73. return strings.Join(strings.Split(key.Content, " ")[:2], " ")
  74. }
  75. // AuthorizedString returns formatted public key string for authorized_keys file.
  76. func (key *PublicKey) AuthorizedString() string {
  77. return fmt.Sprintf(tplPublicKey, util.ShellEscape(fmt.Sprintf(tplCommand, util.ShellEscape(setting.AppPath), util.ShellEscape(setting.CustomConf), key.ID)), key.Content)
  78. }
  79. func extractTypeFromBase64Key(key string) (string, error) {
  80. b, err := base64.StdEncoding.DecodeString(key)
  81. if err != nil || len(b) < 4 {
  82. return "", fmt.Errorf("invalid key format: %v", err)
  83. }
  84. keyLength := int(binary.BigEndian.Uint32(b))
  85. if len(b) < 4+keyLength {
  86. return "", fmt.Errorf("invalid key format: not enough length %d", keyLength)
  87. }
  88. return string(b[4 : 4+keyLength]), nil
  89. }
  90. const ssh2keyStart = "---- BEGIN SSH2 PUBLIC KEY ----"
  91. // parseKeyString parses any key string in OpenSSH or SSH2 format to clean OpenSSH string (RFC4253).
  92. func parseKeyString(content string) (string, error) {
  93. // remove whitespace at start and end
  94. content = strings.TrimSpace(content)
  95. var keyType, keyContent, keyComment string
  96. if strings.HasPrefix(content, ssh2keyStart) {
  97. // Parse SSH2 file format.
  98. // Transform all legal line endings to a single "\n".
  99. content = strings.NewReplacer("\r\n", "\n", "\r", "\n").Replace(content)
  100. lines := strings.Split(content, "\n")
  101. continuationLine := false
  102. for _, line := range lines {
  103. // Skip lines that:
  104. // 1) are a continuation of the previous line,
  105. // 2) contain ":" as that are comment lines
  106. // 3) contain "-" as that are begin and end tags
  107. if continuationLine || strings.ContainsAny(line, ":-") {
  108. continuationLine = strings.HasSuffix(line, "\\")
  109. } else {
  110. keyContent += line
  111. }
  112. }
  113. t, err := extractTypeFromBase64Key(keyContent)
  114. if err != nil {
  115. return "", fmt.Errorf("extractTypeFromBase64Key: %v", err)
  116. }
  117. keyType = t
  118. } else {
  119. if strings.Contains(content, "-----BEGIN") {
  120. // Convert PEM Keys to OpenSSH format
  121. // Transform all legal line endings to a single "\n".
  122. content = strings.NewReplacer("\r\n", "\n", "\r", "\n").Replace(content)
  123. block, _ := pem.Decode([]byte(content))
  124. if block == nil {
  125. return "", fmt.Errorf("failed to parse PEM block containing the public key")
  126. }
  127. pub, err := x509.ParsePKIXPublicKey(block.Bytes)
  128. if err != nil {
  129. var pk rsa.PublicKey
  130. _, err2 := asn1.Unmarshal(block.Bytes, &pk)
  131. if err2 != nil {
  132. return "", fmt.Errorf("failed to parse DER encoded public key as either PKIX or PEM RSA Key: %v %v", err, err2)
  133. }
  134. pub = &pk
  135. }
  136. sshKey, err := ssh.NewPublicKey(pub)
  137. if err != nil {
  138. return "", fmt.Errorf("unable to convert to ssh public key: %v", err)
  139. }
  140. content = string(ssh.MarshalAuthorizedKey(sshKey))
  141. }
  142. // Parse OpenSSH format.
  143. // Remove all newlines
  144. content = strings.NewReplacer("\r\n", "", "\n", "").Replace(content)
  145. parts := strings.SplitN(content, " ", 3)
  146. switch len(parts) {
  147. case 0:
  148. return "", errors.New("empty key")
  149. case 1:
  150. keyContent = parts[0]
  151. case 2:
  152. keyType = parts[0]
  153. keyContent = parts[1]
  154. default:
  155. keyType = parts[0]
  156. keyContent = parts[1]
  157. keyComment = parts[2]
  158. }
  159. // If keyType is not given, extract it from content. If given, validate it.
  160. t, err := extractTypeFromBase64Key(keyContent)
  161. if err != nil {
  162. return "", fmt.Errorf("extractTypeFromBase64Key: %v", err)
  163. }
  164. if len(keyType) == 0 {
  165. keyType = t
  166. } else if keyType != t {
  167. return "", fmt.Errorf("key type and content does not match: %s - %s", keyType, t)
  168. }
  169. }
  170. // Finally we need to check whether we can actually read the proposed key:
  171. _, _, _, _, err := ssh.ParseAuthorizedKey([]byte(keyType + " " + keyContent + " " + keyComment))
  172. if err != nil {
  173. return "", fmt.Errorf("invalid ssh public key: %v", err)
  174. }
  175. return keyType + " " + keyContent + " " + keyComment, nil
  176. }
  177. // writeTmpKeyFile writes key content to a temporary file
  178. // and returns the name of that file, along with any possible errors.
  179. func writeTmpKeyFile(content string) (string, error) {
  180. tmpFile, err := ioutil.TempFile(setting.SSH.KeyTestPath, "gitea_keytest")
  181. if err != nil {
  182. return "", fmt.Errorf("TempFile: %v", err)
  183. }
  184. defer tmpFile.Close()
  185. if _, err = tmpFile.WriteString(content); err != nil {
  186. return "", fmt.Errorf("WriteString: %v", err)
  187. }
  188. return tmpFile.Name(), nil
  189. }
  190. // SSHKeyGenParsePublicKey extracts key type and length using ssh-keygen.
  191. func SSHKeyGenParsePublicKey(key string) (string, int, error) {
  192. // The ssh-keygen in Windows does not print key type, so no need go further.
  193. if setting.IsWindows {
  194. return "", 0, nil
  195. }
  196. tmpName, err := writeTmpKeyFile(key)
  197. if err != nil {
  198. return "", 0, fmt.Errorf("writeTmpKeyFile: %v", err)
  199. }
  200. defer func() {
  201. if err := util.Remove(tmpName); err != nil {
  202. log.Warn("Unable to remove temporary key file: %s: Error: %v", tmpName, err)
  203. }
  204. }()
  205. stdout, stderr, err := process.GetManager().Exec("SSHKeyGenParsePublicKey", setting.SSH.KeygenPath, "-lf", tmpName)
  206. if err != nil {
  207. return "", 0, fmt.Errorf("fail to parse public key: %s - %s", err, stderr)
  208. }
  209. if strings.Contains(stdout, "is not a public key file") {
  210. return "", 0, ErrKeyUnableVerify{stdout}
  211. }
  212. fields := strings.Split(stdout, " ")
  213. if len(fields) < 4 {
  214. return "", 0, fmt.Errorf("invalid public key line: %s", stdout)
  215. }
  216. keyType := strings.Trim(fields[len(fields)-1], "()\r\n")
  217. return strings.ToLower(keyType), com.StrTo(fields[0]).MustInt(), nil
  218. }
  219. // SSHNativeParsePublicKey extracts the key type and length using the golang SSH library.
  220. func SSHNativeParsePublicKey(keyLine string) (string, int, error) {
  221. fields := strings.Fields(keyLine)
  222. if len(fields) < 2 {
  223. return "", 0, fmt.Errorf("not enough fields in public key line: %s", keyLine)
  224. }
  225. raw, err := base64.StdEncoding.DecodeString(fields[1])
  226. if err != nil {
  227. return "", 0, err
  228. }
  229. pkey, err := ssh.ParsePublicKey(raw)
  230. if err != nil {
  231. if strings.Contains(err.Error(), "ssh: unknown key algorithm") {
  232. return "", 0, ErrKeyUnableVerify{err.Error()}
  233. }
  234. return "", 0, fmt.Errorf("ParsePublicKey: %v", err)
  235. }
  236. // The ssh library can parse the key, so next we find out what key exactly we have.
  237. switch pkey.Type() {
  238. case ssh.KeyAlgoDSA:
  239. rawPub := struct {
  240. Name string
  241. P, Q, G, Y *big.Int
  242. }{}
  243. if err := ssh.Unmarshal(pkey.Marshal(), &rawPub); err != nil {
  244. return "", 0, err
  245. }
  246. // as per https://bugzilla.mindrot.org/show_bug.cgi?id=1647 we should never
  247. // see dsa keys != 1024 bit, but as it seems to work, we will not check here
  248. return "dsa", rawPub.P.BitLen(), nil // use P as per crypto/dsa/dsa.go (is L)
  249. case ssh.KeyAlgoRSA:
  250. rawPub := struct {
  251. Name string
  252. E *big.Int
  253. N *big.Int
  254. }{}
  255. if err := ssh.Unmarshal(pkey.Marshal(), &rawPub); err != nil {
  256. return "", 0, err
  257. }
  258. return "rsa", rawPub.N.BitLen(), nil // use N as per crypto/rsa/rsa.go (is bits)
  259. case ssh.KeyAlgoECDSA256:
  260. return "ecdsa", 256, nil
  261. case ssh.KeyAlgoECDSA384:
  262. return "ecdsa", 384, nil
  263. case ssh.KeyAlgoECDSA521:
  264. return "ecdsa", 521, nil
  265. case ssh.KeyAlgoED25519:
  266. return "ed25519", 256, nil
  267. }
  268. return "", 0, fmt.Errorf("unsupported key length detection for type: %s", pkey.Type())
  269. }
  270. // CheckPublicKeyString checks if the given public key string is recognized by SSH.
  271. // It returns the actual public key line on success.
  272. func CheckPublicKeyString(content string) (_ string, err error) {
  273. if setting.SSH.Disabled {
  274. return "", ErrSSHDisabled{}
  275. }
  276. content, err = parseKeyString(content)
  277. if err != nil {
  278. return "", err
  279. }
  280. content = strings.TrimRight(content, "\n\r")
  281. if strings.ContainsAny(content, "\n\r") {
  282. return "", errors.New("only a single line with a single key please")
  283. }
  284. // remove any unnecessary whitespace now
  285. content = strings.TrimSpace(content)
  286. if !setting.SSH.MinimumKeySizeCheck {
  287. return content, nil
  288. }
  289. var (
  290. fnName string
  291. keyType string
  292. length int
  293. )
  294. if setting.SSH.StartBuiltinServer {
  295. fnName = "SSHNativeParsePublicKey"
  296. keyType, length, err = SSHNativeParsePublicKey(content)
  297. } else {
  298. fnName = "SSHKeyGenParsePublicKey"
  299. keyType, length, err = SSHKeyGenParsePublicKey(content)
  300. }
  301. if err != nil {
  302. return "", fmt.Errorf("%s: %v", fnName, err)
  303. }
  304. log.Trace("Key info [native: %v]: %s-%d", setting.SSH.StartBuiltinServer, keyType, length)
  305. if minLen, found := setting.SSH.MinimumKeySizes[keyType]; found && length >= minLen {
  306. return content, nil
  307. } else if found && length < minLen {
  308. return "", fmt.Errorf("key length is not enough: got %d, needs %d", length, minLen)
  309. }
  310. return "", fmt.Errorf("key type is not allowed: %s", keyType)
  311. }
  312. // appendAuthorizedKeysToFile appends new SSH keys' content to authorized_keys file.
  313. func appendAuthorizedKeysToFile(keys ...*PublicKey) error {
  314. // Don't need to rewrite this file if builtin SSH server is enabled.
  315. if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile {
  316. return nil
  317. }
  318. sshOpLocker.Lock()
  319. defer sshOpLocker.Unlock()
  320. if setting.SSH.RootPath != "" {
  321. // First of ensure that the RootPath is present, and if not make it with 0700 permissions
  322. // This of course doesn't guarantee that this is the right directory for authorized_keys
  323. // but at least if it's supposed to be this directory and it doesn't exist and we're the
  324. // right user it will at least be created properly.
  325. err := os.MkdirAll(setting.SSH.RootPath, 0700)
  326. if err != nil {
  327. log.Error("Unable to MkdirAll(%s): %v", setting.SSH.RootPath, err)
  328. return err
  329. }
  330. }
  331. fPath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
  332. f, err := os.OpenFile(fPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
  333. if err != nil {
  334. return err
  335. }
  336. defer f.Close()
  337. // Note: chmod command does not support in Windows.
  338. if !setting.IsWindows {
  339. fi, err := f.Stat()
  340. if err != nil {
  341. return err
  342. }
  343. // .ssh directory should have mode 700, and authorized_keys file should have mode 600.
  344. if fi.Mode().Perm() > 0600 {
  345. log.Error("authorized_keys file has unusual permission flags: %s - setting to -rw-------", fi.Mode().Perm().String())
  346. if err = f.Chmod(0600); err != nil {
  347. return err
  348. }
  349. }
  350. }
  351. for _, key := range keys {
  352. if key.Type == KeyTypePrincipal {
  353. continue
  354. }
  355. if _, err = f.WriteString(key.AuthorizedString()); err != nil {
  356. return err
  357. }
  358. }
  359. return nil
  360. }
  361. // checkKeyFingerprint only checks if key fingerprint has been used as public key,
  362. // it is OK to use same key as deploy key for multiple repositories/users.
  363. func checkKeyFingerprint(e Engine, fingerprint string) error {
  364. has, err := e.Get(&PublicKey{
  365. Fingerprint: fingerprint,
  366. })
  367. if err != nil {
  368. return err
  369. } else if has {
  370. return ErrKeyAlreadyExist{0, fingerprint, ""}
  371. }
  372. return nil
  373. }
  374. func calcFingerprintSSHKeygen(publicKeyContent string) (string, error) {
  375. // Calculate fingerprint.
  376. tmpPath, err := writeTmpKeyFile(publicKeyContent)
  377. if err != nil {
  378. return "", err
  379. }
  380. defer func() {
  381. if err := util.Remove(tmpPath); err != nil {
  382. log.Warn("Unable to remove temporary key file: %s: Error: %v", tmpPath, err)
  383. }
  384. }()
  385. stdout, stderr, err := process.GetManager().Exec("AddPublicKey", "ssh-keygen", "-lf", tmpPath)
  386. if err != nil {
  387. if strings.Contains(stderr, "is not a public key file") {
  388. return "", ErrKeyUnableVerify{stderr}
  389. }
  390. return "", fmt.Errorf("'ssh-keygen -lf %s' failed with error '%s': %s", tmpPath, err, stderr)
  391. } else if len(stdout) < 2 {
  392. return "", errors.New("not enough output for calculating fingerprint: " + stdout)
  393. }
  394. return strings.Split(stdout, " ")[1], nil
  395. }
  396. func calcFingerprintNative(publicKeyContent string) (string, error) {
  397. // Calculate fingerprint.
  398. pk, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKeyContent))
  399. if err != nil {
  400. return "", err
  401. }
  402. return ssh.FingerprintSHA256(pk), nil
  403. }
  404. func calcFingerprint(publicKeyContent string) (string, error) {
  405. //Call the method based on configuration
  406. var (
  407. fnName, fp string
  408. err error
  409. )
  410. if setting.SSH.StartBuiltinServer {
  411. fnName = "calcFingerprintNative"
  412. fp, err = calcFingerprintNative(publicKeyContent)
  413. } else {
  414. fnName = "calcFingerprintSSHKeygen"
  415. fp, err = calcFingerprintSSHKeygen(publicKeyContent)
  416. }
  417. if err != nil {
  418. if IsErrKeyUnableVerify(err) {
  419. log.Info("%s", publicKeyContent)
  420. return "", err
  421. }
  422. return "", fmt.Errorf("%s: %v", fnName, err)
  423. }
  424. return fp, nil
  425. }
  426. func addKey(e Engine, key *PublicKey) (err error) {
  427. if len(key.Fingerprint) == 0 {
  428. key.Fingerprint, err = calcFingerprint(key.Content)
  429. if err != nil {
  430. return err
  431. }
  432. }
  433. // Save SSH key.
  434. if _, err = e.Insert(key); err != nil {
  435. return err
  436. }
  437. return appendAuthorizedKeysToFile(key)
  438. }
  439. // AddPublicKey adds new public key to database and authorized_keys file.
  440. func AddPublicKey(ownerID int64, name, content string, loginSourceID int64) (*PublicKey, error) {
  441. log.Trace(content)
  442. fingerprint, err := calcFingerprint(content)
  443. if err != nil {
  444. return nil, err
  445. }
  446. sess := x.NewSession()
  447. defer sess.Close()
  448. if err = sess.Begin(); err != nil {
  449. return nil, err
  450. }
  451. if err := checkKeyFingerprint(sess, fingerprint); err != nil {
  452. return nil, err
  453. }
  454. // Key name of same user cannot be duplicated.
  455. has, err := sess.
  456. Where("owner_id = ? AND name = ?", ownerID, name).
  457. Get(new(PublicKey))
  458. if err != nil {
  459. return nil, err
  460. } else if has {
  461. return nil, ErrKeyNameAlreadyUsed{ownerID, name}
  462. }
  463. key := &PublicKey{
  464. OwnerID: ownerID,
  465. Name: name,
  466. Fingerprint: fingerprint,
  467. Content: content,
  468. Mode: AccessModeWrite,
  469. Type: KeyTypeUser,
  470. LoginSourceID: loginSourceID,
  471. }
  472. if err = addKey(sess, key); err != nil {
  473. return nil, fmt.Errorf("addKey: %v", err)
  474. }
  475. return key, sess.Commit()
  476. }
  477. // GetPublicKeyByID returns public key by given ID.
  478. func GetPublicKeyByID(keyID int64) (*PublicKey, error) {
  479. key := new(PublicKey)
  480. has, err := x.
  481. ID(keyID).
  482. Get(key)
  483. if err != nil {
  484. return nil, err
  485. } else if !has {
  486. return nil, ErrKeyNotExist{keyID}
  487. }
  488. return key, nil
  489. }
  490. func searchPublicKeyByContentWithEngine(e Engine, content string) (*PublicKey, error) {
  491. key := new(PublicKey)
  492. has, err := e.
  493. Where("content like ?", content+"%").
  494. Get(key)
  495. if err != nil {
  496. return nil, err
  497. } else if !has {
  498. return nil, ErrKeyNotExist{}
  499. }
  500. return key, nil
  501. }
  502. // SearchPublicKeyByContent searches content as prefix (leak e-mail part)
  503. // and returns public key found.
  504. func SearchPublicKeyByContent(content string) (*PublicKey, error) {
  505. return searchPublicKeyByContentWithEngine(x, content)
  506. }
  507. func searchPublicKeyByContentExactWithEngine(e Engine, content string) (*PublicKey, error) {
  508. key := new(PublicKey)
  509. has, err := e.
  510. Where("content = ?", content).
  511. Get(key)
  512. if err != nil {
  513. return nil, err
  514. } else if !has {
  515. return nil, ErrKeyNotExist{}
  516. }
  517. return key, nil
  518. }
  519. // SearchPublicKeyByContentExact searches content
  520. // and returns public key found.
  521. func SearchPublicKeyByContentExact(content string) (*PublicKey, error) {
  522. return searchPublicKeyByContentExactWithEngine(x, content)
  523. }
  524. // SearchPublicKey returns a list of public keys matching the provided arguments.
  525. func SearchPublicKey(uid int64, fingerprint string) ([]*PublicKey, error) {
  526. keys := make([]*PublicKey, 0, 5)
  527. cond := builder.NewCond()
  528. if uid != 0 {
  529. cond = cond.And(builder.Eq{"owner_id": uid})
  530. }
  531. if fingerprint != "" {
  532. cond = cond.And(builder.Eq{"fingerprint": fingerprint})
  533. }
  534. return keys, x.Where(cond).Find(&keys)
  535. }
  536. // ListPublicKeys returns a list of public keys belongs to given user.
  537. func ListPublicKeys(uid int64, listOptions ListOptions) ([]*PublicKey, error) {
  538. sess := x.Where("owner_id = ? AND type != ?", uid, KeyTypePrincipal)
  539. if listOptions.Page != 0 {
  540. sess = listOptions.setSessionPagination(sess)
  541. keys := make([]*PublicKey, 0, listOptions.PageSize)
  542. return keys, sess.Find(&keys)
  543. }
  544. keys := make([]*PublicKey, 0, 5)
  545. return keys, sess.Find(&keys)
  546. }
  547. // ListPublicLdapSSHKeys returns a list of synchronized public ldap ssh keys belongs to given user and login source.
  548. func ListPublicLdapSSHKeys(uid int64, loginSourceID int64) ([]*PublicKey, error) {
  549. keys := make([]*PublicKey, 0, 5)
  550. return keys, x.
  551. Where("owner_id = ? AND login_source_id = ?", uid, loginSourceID).
  552. Find(&keys)
  553. }
  554. // UpdatePublicKeyUpdated updates public key use time.
  555. func UpdatePublicKeyUpdated(id int64) error {
  556. // Check if key exists before update as affected rows count is unreliable
  557. // and will return 0 affected rows if two updates are made at the same time
  558. if cnt, err := x.ID(id).Count(&PublicKey{}); err != nil {
  559. return err
  560. } else if cnt != 1 {
  561. return ErrKeyNotExist{id}
  562. }
  563. _, err := x.ID(id).Cols("updated_unix").Update(&PublicKey{
  564. UpdatedUnix: timeutil.TimeStampNow(),
  565. })
  566. if err != nil {
  567. return err
  568. }
  569. return nil
  570. }
  571. // deletePublicKeys does the actual key deletion but does not update authorized_keys file.
  572. func deletePublicKeys(e Engine, keyIDs ...int64) error {
  573. if len(keyIDs) == 0 {
  574. return nil
  575. }
  576. _, err := e.In("id", keyIDs).Delete(new(PublicKey))
  577. return err
  578. }
  579. // DeletePublicKey deletes SSH key information both in database and authorized_keys file.
  580. func DeletePublicKey(doer *User, id int64) (err error) {
  581. key, err := GetPublicKeyByID(id)
  582. if err != nil {
  583. return err
  584. }
  585. // Check if user has access to delete this key.
  586. if !doer.IsAdmin && doer.ID != key.OwnerID {
  587. return ErrKeyAccessDenied{doer.ID, key.ID, "public"}
  588. }
  589. sess := x.NewSession()
  590. defer sess.Close()
  591. if err = sess.Begin(); err != nil {
  592. return err
  593. }
  594. if err = deletePublicKeys(sess, id); err != nil {
  595. return err
  596. }
  597. if err = sess.Commit(); err != nil {
  598. return err
  599. }
  600. sess.Close()
  601. if key.Type == KeyTypePrincipal {
  602. return RewriteAllPrincipalKeys()
  603. }
  604. return RewriteAllPublicKeys()
  605. }
  606. // RewriteAllPublicKeys removes any authorized key and rewrite all keys from database again.
  607. // Note: x.Iterate does not get latest data after insert/delete, so we have to call this function
  608. // outside any session scope independently.
  609. func RewriteAllPublicKeys() error {
  610. return rewriteAllPublicKeys(x)
  611. }
  612. func rewriteAllPublicKeys(e Engine) error {
  613. //Don't rewrite key if internal server
  614. if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile {
  615. return nil
  616. }
  617. sshOpLocker.Lock()
  618. defer sshOpLocker.Unlock()
  619. if setting.SSH.RootPath != "" {
  620. // First of ensure that the RootPath is present, and if not make it with 0700 permissions
  621. // This of course doesn't guarantee that this is the right directory for authorized_keys
  622. // but at least if it's supposed to be this directory and it doesn't exist and we're the
  623. // right user it will at least be created properly.
  624. err := os.MkdirAll(setting.SSH.RootPath, 0700)
  625. if err != nil {
  626. log.Error("Unable to MkdirAll(%s): %v", setting.SSH.RootPath, err)
  627. return err
  628. }
  629. }
  630. fPath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
  631. tmpPath := fPath + ".tmp"
  632. t, err := os.OpenFile(tmpPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
  633. if err != nil {
  634. return err
  635. }
  636. defer func() {
  637. t.Close()
  638. if err := util.Remove(tmpPath); err != nil {
  639. log.Warn("Unable to remove temporary authorized keys file: %s: Error: %v", tmpPath, err)
  640. }
  641. }()
  642. if setting.SSH.AuthorizedKeysBackup {
  643. isExist, err := util.IsExist(fPath)
  644. if err != nil {
  645. log.Error("Unable to check if %s exists. Error: %v", fPath, err)
  646. return err
  647. }
  648. if isExist {
  649. bakPath := fmt.Sprintf("%s_%d.gitea_bak", fPath, time.Now().Unix())
  650. if err = com.Copy(fPath, bakPath); err != nil {
  651. return err
  652. }
  653. }
  654. }
  655. if err := regeneratePublicKeys(e, t); err != nil {
  656. return err
  657. }
  658. t.Close()
  659. return os.Rename(tmpPath, fPath)
  660. }
  661. // RegeneratePublicKeys regenerates the authorized_keys file
  662. func RegeneratePublicKeys(t io.StringWriter) error {
  663. return regeneratePublicKeys(x, t)
  664. }
  665. func regeneratePublicKeys(e Engine, t io.StringWriter) error {
  666. if err := e.Where("type != ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
  667. _, err = t.WriteString((bean.(*PublicKey)).AuthorizedString())
  668. return err
  669. }); err != nil {
  670. return err
  671. }
  672. fPath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
  673. isExist, err := util.IsExist(fPath)
  674. if err != nil {
  675. log.Error("Unable to check if %s exists. Error: %v", fPath, err)
  676. return err
  677. }
  678. if isExist {
  679. f, err := os.Open(fPath)
  680. if err != nil {
  681. return err
  682. }
  683. scanner := bufio.NewScanner(f)
  684. for scanner.Scan() {
  685. line := scanner.Text()
  686. if strings.HasPrefix(line, tplCommentPrefix) {
  687. scanner.Scan()
  688. continue
  689. }
  690. _, err = t.WriteString(line + "\n")
  691. if err != nil {
  692. f.Close()
  693. return err
  694. }
  695. }
  696. f.Close()
  697. }
  698. return nil
  699. }
  700. // ________ .__ ____ __.
  701. // \______ \ ____ ______ | | ____ ___.__.| |/ _|____ ___.__.
  702. // | | \_/ __ \\____ \| | / _ < | || <_/ __ < | |
  703. // | ` \ ___/| |_> > |_( <_> )___ || | \ ___/\___ |
  704. // /_______ /\___ > __/|____/\____// ____||____|__ \___ > ____|
  705. // \/ \/|__| \/ \/ \/\/
  706. // DeployKey represents deploy key information and its relation with repository.
  707. type DeployKey struct {
  708. ID int64 `xorm:"pk autoincr"`
  709. KeyID int64 `xorm:"UNIQUE(s) INDEX"`
  710. RepoID int64 `xorm:"UNIQUE(s) INDEX"`
  711. Name string
  712. Fingerprint string
  713. Content string `xorm:"-"`
  714. Mode AccessMode `xorm:"NOT NULL DEFAULT 1"`
  715. CreatedUnix timeutil.TimeStamp `xorm:"created"`
  716. UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
  717. HasRecentActivity bool `xorm:"-"`
  718. HasUsed bool `xorm:"-"`
  719. }
  720. // AfterLoad is invoked from XORM after setting the values of all fields of this object.
  721. func (key *DeployKey) AfterLoad() {
  722. key.HasUsed = key.UpdatedUnix > key.CreatedUnix
  723. key.HasRecentActivity = key.UpdatedUnix.AddDuration(7*24*time.Hour) > timeutil.TimeStampNow()
  724. }
  725. // GetContent gets associated public key content.
  726. func (key *DeployKey) GetContent() error {
  727. pkey, err := GetPublicKeyByID(key.KeyID)
  728. if err != nil {
  729. return err
  730. }
  731. key.Content = pkey.Content
  732. return nil
  733. }
  734. // IsReadOnly checks if the key can only be used for read operations
  735. func (key *DeployKey) IsReadOnly() bool {
  736. return key.Mode == AccessModeRead
  737. }
  738. func checkDeployKey(e Engine, keyID, repoID int64, name string) error {
  739. // Note: We want error detail, not just true or false here.
  740. has, err := e.
  741. Where("key_id = ? AND repo_id = ?", keyID, repoID).
  742. Get(new(DeployKey))
  743. if err != nil {
  744. return err
  745. } else if has {
  746. return ErrDeployKeyAlreadyExist{keyID, repoID}
  747. }
  748. has, err = e.
  749. Where("repo_id = ? AND name = ?", repoID, name).
  750. Get(new(DeployKey))
  751. if err != nil {
  752. return err
  753. } else if has {
  754. return ErrDeployKeyNameAlreadyUsed{repoID, name}
  755. }
  756. return nil
  757. }
  758. // addDeployKey adds new key-repo relation.
  759. func addDeployKey(e *xorm.Session, keyID, repoID int64, name, fingerprint string, mode AccessMode) (*DeployKey, error) {
  760. if err := checkDeployKey(e, keyID, repoID, name); err != nil {
  761. return nil, err
  762. }
  763. key := &DeployKey{
  764. KeyID: keyID,
  765. RepoID: repoID,
  766. Name: name,
  767. Fingerprint: fingerprint,
  768. Mode: mode,
  769. }
  770. _, err := e.Insert(key)
  771. return key, err
  772. }
  773. // HasDeployKey returns true if public key is a deploy key of given repository.
  774. func HasDeployKey(keyID, repoID int64) bool {
  775. has, _ := x.
  776. Where("key_id = ? AND repo_id = ?", keyID, repoID).
  777. Get(new(DeployKey))
  778. return has
  779. }
  780. // AddDeployKey add new deploy key to database and authorized_keys file.
  781. func AddDeployKey(repoID int64, name, content string, readOnly bool) (*DeployKey, error) {
  782. fingerprint, err := calcFingerprint(content)
  783. if err != nil {
  784. return nil, err
  785. }
  786. accessMode := AccessModeRead
  787. if !readOnly {
  788. accessMode = AccessModeWrite
  789. }
  790. sess := x.NewSession()
  791. defer sess.Close()
  792. if err = sess.Begin(); err != nil {
  793. return nil, err
  794. }
  795. pkey := &PublicKey{
  796. Fingerprint: fingerprint,
  797. }
  798. has, err := sess.Get(pkey)
  799. if err != nil {
  800. return nil, err
  801. }
  802. if has {
  803. if pkey.Type != KeyTypeDeploy {
  804. return nil, ErrKeyAlreadyExist{0, fingerprint, ""}
  805. }
  806. } else {
  807. // First time use this deploy key.
  808. pkey.Mode = accessMode
  809. pkey.Type = KeyTypeDeploy
  810. pkey.Content = content
  811. pkey.Name = name
  812. if err = addKey(sess, pkey); err != nil {
  813. return nil, fmt.Errorf("addKey: %v", err)
  814. }
  815. }
  816. key, err := addDeployKey(sess, pkey.ID, repoID, name, pkey.Fingerprint, accessMode)
  817. if err != nil {
  818. return nil, err
  819. }
  820. return key, sess.Commit()
  821. }
  822. // GetDeployKeyByID returns deploy key by given ID.
  823. func GetDeployKeyByID(id int64) (*DeployKey, error) {
  824. return getDeployKeyByID(x, id)
  825. }
  826. func getDeployKeyByID(e Engine, id int64) (*DeployKey, error) {
  827. key := new(DeployKey)
  828. has, err := e.ID(id).Get(key)
  829. if err != nil {
  830. return nil, err
  831. } else if !has {
  832. return nil, ErrDeployKeyNotExist{id, 0, 0}
  833. }
  834. return key, nil
  835. }
  836. // GetDeployKeyByRepo returns deploy key by given public key ID and repository ID.
  837. func GetDeployKeyByRepo(keyID, repoID int64) (*DeployKey, error) {
  838. return getDeployKeyByRepo(x, keyID, repoID)
  839. }
  840. func getDeployKeyByRepo(e Engine, keyID, repoID int64) (*DeployKey, error) {
  841. key := &DeployKey{
  842. KeyID: keyID,
  843. RepoID: repoID,
  844. }
  845. has, err := e.Get(key)
  846. if err != nil {
  847. return nil, err
  848. } else if !has {
  849. return nil, ErrDeployKeyNotExist{0, keyID, repoID}
  850. }
  851. return key, nil
  852. }
  853. // UpdateDeployKeyCols updates deploy key information in the specified columns.
  854. func UpdateDeployKeyCols(key *DeployKey, cols ...string) error {
  855. _, err := x.ID(key.ID).Cols(cols...).Update(key)
  856. return err
  857. }
  858. // UpdateDeployKey updates deploy key information.
  859. func UpdateDeployKey(key *DeployKey) error {
  860. _, err := x.ID(key.ID).AllCols().Update(key)
  861. return err
  862. }
  863. // DeleteDeployKey deletes deploy key from its repository authorized_keys file if needed.
  864. func DeleteDeployKey(doer *User, id int64) error {
  865. sess := x.NewSession()
  866. defer sess.Close()
  867. if err := sess.Begin(); err != nil {
  868. return err
  869. }
  870. if err := deleteDeployKey(sess, doer, id); err != nil {
  871. return err
  872. }
  873. return sess.Commit()
  874. }
  875. func deleteDeployKey(sess Engine, doer *User, id int64) error {
  876. key, err := getDeployKeyByID(sess, id)
  877. if err != nil {
  878. if IsErrDeployKeyNotExist(err) {
  879. return nil
  880. }
  881. return fmt.Errorf("GetDeployKeyByID: %v", err)
  882. }
  883. // Check if user has access to delete this key.
  884. if !doer.IsAdmin {
  885. repo, err := getRepositoryByID(sess, key.RepoID)
  886. if err != nil {
  887. return fmt.Errorf("GetRepositoryByID: %v", err)
  888. }
  889. has, err := isUserRepoAdmin(sess, repo, doer)
  890. if err != nil {
  891. return fmt.Errorf("GetUserRepoPermission: %v", err)
  892. } else if !has {
  893. return ErrKeyAccessDenied{doer.ID, key.ID, "deploy"}
  894. }
  895. }
  896. if _, err = sess.ID(key.ID).Delete(new(DeployKey)); err != nil {
  897. return fmt.Errorf("delete deploy key [%d]: %v", key.ID, err)
  898. }
  899. // Check if this is the last reference to same key content.
  900. has, err := sess.
  901. Where("key_id = ?", key.KeyID).
  902. Get(new(DeployKey))
  903. if err != nil {
  904. return err
  905. } else if !has {
  906. if err = deletePublicKeys(sess, key.KeyID); err != nil {
  907. return err
  908. }
  909. // after deleted the public keys, should rewrite the public keys file
  910. if err = rewriteAllPublicKeys(sess); err != nil {
  911. return err
  912. }
  913. }
  914. return nil
  915. }
  916. // ListDeployKeys returns all deploy keys by given repository ID.
  917. func ListDeployKeys(repoID int64, listOptions ListOptions) ([]*DeployKey, error) {
  918. return listDeployKeys(x, repoID, listOptions)
  919. }
  920. func listDeployKeys(e Engine, repoID int64, listOptions ListOptions) ([]*DeployKey, error) {
  921. sess := e.Where("repo_id = ?", repoID)
  922. if listOptions.Page != 0 {
  923. sess = listOptions.setSessionPagination(sess)
  924. keys := make([]*DeployKey, 0, listOptions.PageSize)
  925. return keys, sess.Find(&keys)
  926. }
  927. keys := make([]*DeployKey, 0, 5)
  928. return keys, sess.Find(&keys)
  929. }
  930. // SearchDeployKeys returns a list of deploy keys matching the provided arguments.
  931. func SearchDeployKeys(repoID int64, keyID int64, fingerprint string) ([]*DeployKey, error) {
  932. keys := make([]*DeployKey, 0, 5)
  933. cond := builder.NewCond()
  934. if repoID != 0 {
  935. cond = cond.And(builder.Eq{"repo_id": repoID})
  936. }
  937. if keyID != 0 {
  938. cond = cond.And(builder.Eq{"key_id": keyID})
  939. }
  940. if fingerprint != "" {
  941. cond = cond.And(builder.Eq{"fingerprint": fingerprint})
  942. }
  943. return keys, x.Where(cond).Find(&keys)
  944. }
  945. // __________ .__ .__ .__
  946. // \______ _______|__| ____ ____ |_____________ | | ______
  947. // | ___\_ __ | |/ \_/ ___\| \____ \__ \ | | / ___/
  948. // | | | | \| | | \ \___| | |_> / __ \| |__\___ \
  949. // |____| |__| |__|___| /\___ |__| __(____ |____/____ >
  950. // \/ \/ |__| \/ \/
  951. // AddPrincipalKey adds new principal to database and authorized_principals file.
  952. func AddPrincipalKey(ownerID int64, content string, loginSourceID int64) (*PublicKey, error) {
  953. sess := x.NewSession()
  954. defer sess.Close()
  955. if err := sess.Begin(); err != nil {
  956. return nil, err
  957. }
  958. // Principals cannot be duplicated.
  959. has, err := sess.
  960. Where("content = ? AND type = ?", content, KeyTypePrincipal).
  961. Get(new(PublicKey))
  962. if err != nil {
  963. return nil, err
  964. } else if has {
  965. return nil, ErrKeyAlreadyExist{0, "", content}
  966. }
  967. key := &PublicKey{
  968. OwnerID: ownerID,
  969. Name: content,
  970. Content: content,
  971. Mode: AccessModeWrite,
  972. Type: KeyTypePrincipal,
  973. LoginSourceID: loginSourceID,
  974. }
  975. if err = addPrincipalKey(sess, key); err != nil {
  976. return nil, fmt.Errorf("addKey: %v", err)
  977. }
  978. if err = sess.Commit(); err != nil {
  979. return nil, err
  980. }
  981. sess.Close()
  982. return key, RewriteAllPrincipalKeys()
  983. }
  984. func addPrincipalKey(e Engine, key *PublicKey) (err error) {
  985. // Save Key representing a principal.
  986. if _, err = e.Insert(key); err != nil {
  987. return err
  988. }
  989. return nil
  990. }
  991. // CheckPrincipalKeyString strips spaces and returns an error if the given principal contains newlines
  992. func CheckPrincipalKeyString(user *User, content string) (_ string, err error) {
  993. if setting.SSH.Disabled {
  994. return "", ErrSSHDisabled{}
  995. }
  996. content = strings.TrimSpace(content)
  997. if strings.ContainsAny(content, "\r\n") {
  998. return "", errors.New("only a single line with a single principal please")
  999. }
  1000. // check all the allowed principals, email, username or anything
  1001. // if any matches, return ok
  1002. for _, v := range setting.SSH.AuthorizedPrincipalsAllow {
  1003. switch v {
  1004. case "anything":
  1005. return content, nil
  1006. case "email":
  1007. emails, err := GetEmailAddresses(user.ID)
  1008. if err != nil {
  1009. return "", err
  1010. }
  1011. for _, email := range emails {
  1012. if !email.IsActivated {
  1013. continue
  1014. }
  1015. if content == email.Email {
  1016. return content, nil
  1017. }
  1018. }
  1019. case "username":
  1020. if content == user.Name {
  1021. return content, nil
  1022. }
  1023. }
  1024. }
  1025. return "", fmt.Errorf("didn't match allowed principals: %s", setting.SSH.AuthorizedPrincipalsAllow)
  1026. }
  1027. // RewriteAllPrincipalKeys removes any authorized principal and rewrite all keys from database again.
  1028. // Note: x.Iterate does not get latest data after insert/delete, so we have to call this function
  1029. // outside any session scope independently.
  1030. func RewriteAllPrincipalKeys() error {
  1031. return rewriteAllPrincipalKeys(x)
  1032. }
  1033. func rewriteAllPrincipalKeys(e Engine) error {
  1034. // Don't rewrite key if internal server
  1035. if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedPrincipalsFile {
  1036. return nil
  1037. }
  1038. sshOpLocker.Lock()
  1039. defer sshOpLocker.Unlock()
  1040. if setting.SSH.RootPath != "" {
  1041. // First of ensure that the RootPath is present, and if not make it with 0700 permissions
  1042. // This of course doesn't guarantee that this is the right directory for authorized_keys
  1043. // but at least if it's supposed to be this directory and it doesn't exist and we're the
  1044. // right user it will at least be created properly.
  1045. err := os.MkdirAll(setting.SSH.RootPath, 0700)
  1046. if err != nil {
  1047. log.Error("Unable to MkdirAll(%s): %v", setting.SSH.RootPath, err)
  1048. return err
  1049. }
  1050. }
  1051. fPath := filepath.Join(setting.SSH.RootPath, authorizedPrincipalsFile)
  1052. tmpPath := fPath + ".tmp"
  1053. t, err := os.OpenFile(tmpPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
  1054. if err != nil {
  1055. return err
  1056. }
  1057. defer func() {
  1058. t.Close()
  1059. os.Remove(tmpPath)
  1060. }()
  1061. if setting.SSH.AuthorizedPrincipalsBackup {
  1062. isExist, err := util.IsExist(fPath)
  1063. if err != nil {
  1064. log.Error("Unable to check if %s exists. Error: %v", fPath, err)
  1065. return err
  1066. }
  1067. if isExist {
  1068. bakPath := fmt.Sprintf("%s_%d.gitea_bak", fPath, time.Now().Unix())
  1069. if err = com.Copy(fPath, bakPath); err != nil {
  1070. return err
  1071. }
  1072. }
  1073. }
  1074. if err := regeneratePrincipalKeys(e, t); err != nil {
  1075. return err
  1076. }
  1077. t.Close()
  1078. return os.Rename(tmpPath, fPath)
  1079. }
  1080. // ListPrincipalKeys returns a list of principals belongs to given user.
  1081. func ListPrincipalKeys(uid int64, listOptions ListOptions) ([]*PublicKey, error) {
  1082. sess := x.Where("owner_id = ? AND type = ?", uid, KeyTypePrincipal)
  1083. if listOptions.Page != 0 {
  1084. sess = listOptions.setSessionPagination(sess)
  1085. keys := make([]*PublicKey, 0, listOptions.PageSize)
  1086. return keys, sess.Find(&keys)
  1087. }
  1088. keys := make([]*PublicKey, 0, 5)
  1089. return keys, sess.Find(&keys)
  1090. }
  1091. // RegeneratePrincipalKeys regenerates the authorized_principals file
  1092. func RegeneratePrincipalKeys(t io.StringWriter) error {
  1093. return regeneratePrincipalKeys(x, t)
  1094. }
  1095. func regeneratePrincipalKeys(e Engine, t io.StringWriter) error {
  1096. if err := e.Where("type = ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
  1097. _, err = t.WriteString((bean.(*PublicKey)).AuthorizedString())
  1098. return err
  1099. }); err != nil {
  1100. return err
  1101. }
  1102. fPath := filepath.Join(setting.SSH.RootPath, authorizedPrincipalsFile)
  1103. isExist, err := util.IsExist(fPath)
  1104. if err != nil {
  1105. log.Error("Unable to check if %s exists. Error: %v", fPath, err)
  1106. return err
  1107. }
  1108. if isExist {
  1109. f, err := os.Open(fPath)
  1110. if err != nil {
  1111. return err
  1112. }
  1113. scanner := bufio.NewScanner(f)
  1114. for scanner.Scan() {
  1115. line := scanner.Text()
  1116. if strings.HasPrefix(line, tplCommentPrefix) {
  1117. scanner.Scan()
  1118. continue
  1119. }
  1120. _, err = t.WriteString(line + "\n")
  1121. if err != nil {
  1122. f.Close()
  1123. return err
  1124. }
  1125. }
  1126. f.Close()
  1127. }
  1128. return nil
  1129. }