From 2792d8b3f526e4a55aae35d2a2a7ec9d42025a67 Mon Sep 17 00:00:00 2001 From: fenn-cs Date: Fri, 15 Mar 2024 11:46:19 +0100 Subject: [PATCH 1/2] feat: Limit email input on auth pages to 255 chars Excessively long emails reported make server unresponsive. We could at some point, consider adding a configuration for sysadmins to bypass this setting on their instance if they want. Signed-off-by: fenn-cs --- core/Controller/LoginController.php | 13 +++++++- core/Controller/LostController.php | 4 +++ core/src/components/login/LoginForm.vue | 8 ++++- core/src/components/login/ResetPassword.vue | 6 ++++ core/src/mixins/auth.js | 36 +++++++++++++++++++++ 5 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 core/src/mixins/auth.js diff --git a/core/Controller/LoginController.php b/core/Controller/LoginController.php index fb60f0feccc4a..90c49549249aa 100644 --- a/core/Controller/LoginController.php +++ b/core/Controller/LoginController.php @@ -336,9 +336,20 @@ public function tryLogin(Chain $loginChain, ); } + $user = trim($user); + + if (strlen($user) > 255) { + return $this->createLoginFailedResponse( + $user, + $user, + $redirect_url, + $this->l10n->t('Unsupported email length (>255)') + ); + } + $data = new LoginData( $this->request, - trim($user), + $user, $password, $redirect_url, $timezone, diff --git a/core/Controller/LostController.php b/core/Controller/LostController.php index 8e9a9e0f0de58..d94386f9ab542 100644 --- a/core/Controller/LostController.php +++ b/core/Controller/LostController.php @@ -182,6 +182,10 @@ public function email(string $user): JSONResponse { $user = trim($user); + if (strlen($user) > 255) { + return new JSONResponse($this->error($this->l10n->t('Unsupported email length (>255)'))); + } + \OCP\Util::emitHook( '\OCA\Files_Sharing\API\Server2Server', 'preLoginNameUsedAsUserName', diff --git a/core/src/components/login/LoginForm.vue b/core/src/components/login/LoginForm.vue index 9844df6239dfa..48620605c9df5 100644 --- a/core/src/components/login/LoginForm.vue +++ b/core/src/components/login/LoginForm.vue @@ -62,12 +62,15 @@ ref="user" :label="loginText" name="user" + :maxlength="255" :value.sync="user" :class="{shake: invalidPassword}" autocapitalize="none" :spellchecking="false" :autocomplete="autoCompleteAllowed ? 'username' : 'off'" required + :error="userNameInputLengthIs255" + :helper-text="userInputHelperText" data-login-form-input-user @change="updateUsername" /> @@ -117,6 +120,8 @@ import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js' import LoginButton from './LoginButton.vue' +import AuthMixin from '../../mixins/auth.js' + export default { name: 'LoginForm', @@ -126,6 +131,7 @@ export default { NcTextField, NcNoteCard, }, + mixins: [AuthMixin], props: { username: { @@ -160,7 +166,7 @@ export default { type: Array, default() { return [] - } + }, }, }, diff --git a/core/src/components/login/ResetPassword.vue b/core/src/components/login/ResetPassword.vue index 0490bd84cf5d8..a1ecc27bb8e49 100644 --- a/core/src/components/login/ResetPassword.vue +++ b/core/src/components/login/ResetPassword.vue @@ -25,8 +25,11 @@ @@ -60,6 +63,8 @@ import LoginButton from './LoginButton.vue' import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js' import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js' +import AuthMixin from '../../mixins/auth.js' + export default { name: 'ResetPassword', components: { @@ -67,6 +72,7 @@ export default { NcNoteCard, NcTextField, }, + mixins: [AuthMixin], props: { username: { type: String, diff --git a/core/src/mixins/auth.js b/core/src/mixins/auth.js new file mode 100644 index 0000000000000..c864371f2955b --- /dev/null +++ b/core/src/mixins/auth.js @@ -0,0 +1,36 @@ +/** + * @copyright Copyright (c) 2024 Fon E. Noel NFEBE + * + * @author Fon E. Noel NFEBE + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +export default { + + computed: { + userNameInputLengthIs255() { + return this.user.length >= 255 + }, + userInputHelperText() { + if (this.userNameInputLengthIs255) { + return t('core', 'Email length is at max (255)') + } + return undefined + }, + }, +} From 8a68814902c280f8844395461d4c7217b0f8d919 Mon Sep 17 00:00:00 2001 From: nextcloud-command Date: Thu, 21 Mar 2024 09:54:15 +0000 Subject: [PATCH 2/2] chore(assets): Recompile assets Signed-off-by: nextcloud-command --- dist/core-login.js | 4 ++-- dist/core-login.js.map | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/core-login.js b/dist/core-login.js index e2517728de538..0315d9810a542 100644 --- a/dist/core-login.js +++ b/dist/core-login.js @@ -1,3 +1,3 @@ /*! For license information please see core-login.js.LICENSE.txt */ -(()=>{var e,r,i,s={52138:(e,r,i)=>{"use strict";var s={};i.r(s),i.d(s,{exclude:()=>Vt,extract:()=>Mt,parse:()=>Dt,parseUrl:()=>zt,pick:()=>qt,stringify:()=>$t,stringifyUrl:()=>Ht});var o=i(85471),a=i(61338),l=i(4523),u=i(74692),c=i.n(u),d=i(85168),h=i(96763);const f={updatableNotification:null,getDefaultNotificationFunction:null,setDefault(t){this.getDefaultNotificationFunction=t},hide(t,e){l.default.isFunction(t)&&(e=t,t=void 0),t?(t.each((function(){c()(this)[0].toastify?c()(this)[0].toastify.hideToast():h.error("cannot hide toast because object is not set"),this===this.updatableNotification&&(this.updatableNotification=null)})),e&&e.call(),this.getDefaultNotificationFunction&&this.getDefaultNotificationFunction()):h.error("Missing argument $row in OC.Notification.hide() call, caller needs to be adjusted to only dismiss its own notification")},showHtml(t,e){(e=e||{}).isHTML=!0,e.timeout=e.timeout?e.timeout:d.DH;const n=(0,d.rG)(t,e);return n.toastElement.toastify=n,c()(n.toastElement)},show(t,e){(e=e||{}).timeout=e.timeout?e.timeout:d.DH;const n=(0,d.rG)(function(t){return t.toString().split("&").join("&").split("<").join("<").split(">").join(">").split('"').join(""").split("'").join("'")}(t),e);return n.toastElement.toastify=n,c()(n.toastElement)},showUpdate(t){return this.updatableNotification&&this.updatableNotification.hideToast(),this.updatableNotification=(0,d.rG)(t,{timeout:d.DH}),this.updatableNotification.toastElement.toastify=this.updatableNotification,c()(this.updatableNotification.toastElement)},showTemporary(t,e){(e=e||{}).timeout=e.timeout||d.aR;const n=(0,d.rG)(t,e);return n.toastElement.toastify=n,c()(n.toastElement)},isHidden:()=>!c()("#content").find(".toastify").length},p=l.default.throttle((()=>{f.showTemporary(t("core","Connection to server lost"))}),7e3,{trailing:!1});let m=!1;const g={enableDynamicSlideToggle(){m=!0},showAppSidebar:function(t){(t||c()("#app-sidebar")).removeClass("disappear").show(),c()("#app-content").trigger(new(c().Event)("appresized"))},hideAppSidebar:function(t){(t||c()("#app-sidebar")).hide().addClass("disappear"),c()("#app-content").trigger(new(c().Event)("appresized"))}};var v=i(99498);function y(t,e,n){"post"!==t&&"delete"!==t||!wt.PasswordConfirmation.requiresPasswordConfirmation()?(n=n||{},c().ajax({type:t.toUpperCase(),url:(0,v.KT)("apps/provisioning_api/api/v1/config/apps")+e,data:n.data||{},success:n.success,error:n.error})):wt.PasswordConfirmation.requirePasswordConfirmation(_.bind(y,this,t,e,n))}const b=window.oc_appconfig||{},w={getValue:function(t,e,n,r){!function(t,e,n,r){(r=r||{}).data={defaultValue:n},y("get","/"+t+"/"+e,r)}(t,e,n,{success:r})},setValue:function(t,e,n){!function(t,e,n,r){(r=r||{}).data={value:n},y("post","/"+t+"/"+e,r)}(t,e,n)},getApps:function(t){!function(t){y("get","",t)}({success:t})},getKeys:function(t,e){!function(t,e){y("get","/"+t,e)}(t,{success:e})},deleteKey:function(t,e){!function(t,e,n){y("delete","/"+t+"/"+e,void 0)}(t,e)}},A=void 0!==window._oc_appswebroots&&window._oc_appswebroots;var x=i(21391),C=i.n(x),N=i(78112),k=i(96763);const E={create:"POST",update:"PROPPATCH",patch:"PROPPATCH",delete:"DELETE",read:"PROPFIND"};function P(t,e){if(l.default.isArray(t))return l.default.map(t,(function(t){return P(t,e)}));var n={href:t.href};return l.default.each(t.propStat,(function(t){if("HTTP/1.1 200 OK"===t.status)for(var r in t.properties){var i=r;r in e&&(i=e[r]),n[i]=t.properties[r]}})),n.id||(n.id=j(n.href)),n}function j(t){var e=t.indexOf("?");e>0&&(t=t.substr(0,e));var n,r=t.split("/");do{n=r[r.length-1],r.pop()}while(!n&&r.length>0);return n}function S(t){return t>=200&&t<=299}function T(t,e,n,r){return t.propPatch(e.url,function(t,e){var n,r={};for(n in t){var i=e[n],s=t[n];i||(k.warn('No matching DAV property for property "'+n),i=n),(l.default.isBoolean(s)||l.default.isNumber(s))&&(s=""+s),r[i]=s}return r}(n.changed,e.davProperties),r).then((function(t){S(t.status)?l.default.isFunction(e.success)&&e.success(n.toJSON()):l.default.isFunction(e.error)&&e.error(t)}))}const O=C().noConflict();Object.assign(O,{davCall:(t,e)=>{var n=new N.dav.Client({baseUrl:t.url,xmlNamespaces:l.default.extend({"DAV:":"d","http://owncloud.org/ns":"oc"},t.xmlNamespaces||{})});n.resolveUrl=function(){return t.url};var r=l.default.extend({"X-Requested-With":"XMLHttpRequest",requesttoken:OC.requestToken},t.headers);return"PROPFIND"===t.type?function(t,e,n,r){return t.propFind(e.url,l.default.values(e.davProperties)||[],e.depth,r).then((function(t){if(S(t.status)){if(l.default.isFunction(e.success)){var n=l.default.invert(e.davProperties),r=P(t.body,n);e.depth>0&&r.shift(),e.success(r)}}else l.default.isFunction(e.error)&&e.error(t)}))}(n,t,0,r):"PROPPATCH"===t.type?T(n,t,e,r):"MKCOL"===t.type?function(t,e,n,r){return t.request(e.type,e.url,r,null).then((function(i){S(i.status)?T(t,e,n,r):l.default.isFunction(e.error)&&e.error(i)}))}(n,t,e,r):function(t,e,n,r){return r["Content-Type"]="application/json",t.request(e.type,e.url,r,e.data).then((function(t){if(S(t.status)){if(l.default.isFunction(e.success)){if("PUT"===e.type||"POST"===e.type||"MKCOL"===e.type){var r=t.body||n.toJSON(),i=t.xhr.getResponseHeader("Content-Location");return"POST"===e.type&&i&&(r.id=j(i)),void e.success(r)}if(207===t.status){var s=l.default.invert(e.davProperties);e.success(P(t.body,s))}else e.success(t.body)}}else l.default.isFunction(e.error)&&e.error(t)}))}(n,t,e,r)},davSync:(t=>(e,n,r)=>{var i={type:E[e]||e},s=n instanceof t.Collection;if("update"===e&&(n.hasInnerCollection?i.type="MKCOL":(n.usePUT||n.collection&&n.collection.usePUT)&&(i.type="PUT")),r.url||(i.url=l.default.result(n,"url")||function(){throw new Error('A "url" property or function must be specified')}()),null!=r.data||!n||"create"!==e&&"update"!==e&&"patch"!==e||(i.data=JSON.stringify(r.attrs||n.toJSON(r))),"PROPFIND"!==i.type&&(i.processData=!1),"PROPFIND"===i.type||"PROPPATCH"===i.type){var o=n.davProperties;!o&&n.model&&(o=n.model.prototype.davProperties),o&&(l.default.isFunction(o)?i.davProperties=o.call(n):i.davProperties=o),i.davProperties=l.default.extend(i.davProperties||{},r.davProperties),l.default.isUndefined(r.depth)&&(r.depth=s?1:0)}var a=r.error;r.error=function(t,e,n){r.textStatus=e,r.errorThrown=n,a&&a.call(r.context,t,e,n)};var u=r.xhr=t.davCall(l.default.extend(i,r),n);return n.trigger("request",n,u,r),u})(O)});const I=O;var L=i(71089);const R=window._oc_config||{},F=document.getElementsByTagName("head")[0].getAttribute("data-user"),B=document.getElementsByTagName("head")[0].getAttribute("data-user-displayname"),U=void 0!==F&&F;var M=i(39285),D=i(36882),$=i(43627);const z={YES_NO_BUTTONS:70,OK_BUTTONS:71,FILEPICKER_TYPE_CHOOSE:1,FILEPICKER_TYPE_MOVE:2,FILEPICKER_TYPE_COPY:3,FILEPICKER_TYPE_COPY_MOVE:4,FILEPICKER_TYPE_CUSTOM:5,dialogsCounter:0,alert:function(t,e,n,r){this.message(t,e,"alert",z.OK_BUTTON,n,r)},info:function(t,e,n,r){this.message(t,e,"info",z.OK_BUTTON,n,r)},confirm:function(t,e,n,r){return this.message(t,e,"notice",z.YES_NO_BUTTONS,n,r)},confirmDestructive:function(t,e,n,r,i){return this.message(t,e,"none",n,r,void 0===i||i)},confirmHtml:function(t,e,n,r){return this.message(t,e,"notice",z.YES_NO_BUTTONS,n,r,!0)},prompt:function(e,n,r,i,s,o){return c().when(this._getMessageTemplate()).then((function(a){var u="oc-dialog-"+z.dialogsCounter+"-content",d="#"+u,h=a.octemplate({dialog_name:u,title:n,message:e,type:"notice"}),f=c()("");f.attr("type",o?"password":"text").attr("id",u+"-input").attr("placeholder",s);var p=c()("