Add WebAuthn settings to manager (#1411)

This commit is contained in:
Maxime Besson 2021-12-23 18:45:26 +01:00
parent 38a100f6f6
commit 3fef6ddcaa
18 changed files with 233 additions and 11 deletions

View File

@ -31,7 +31,7 @@ use constant DEFAULTCONFBACKENDOPTIONS => (
);
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|f(?:indUser(?:Exclud|Search)ingAttribute|acebookExportedVar)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:S(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar|ScopeRule|Macro)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node))|penIdExportedVars)|c(?:as(?:A(?:ppMetaData(?:(?:ExportedVar|Option|Macro)s|Node)|ttributes)|S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions))|(?:ustom(?:Plugins|Add)Param|heckUserHiddenHeader|ombModule)s)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option|Macro)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/;
our $arrayParameters = qr/^mySessionAuthorizedRWKeys$/;
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|t(?:ayConnected(?:BypassFG)?|orePassword)|f(?:RemovedUseNotif|OnlyUpgrade)|kip(?:Upgrade|Renew)Confirmation|oap(?:Session|Config)Server|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:A(?:llow(?:(?:ClientCredentials|Password)Grant|Offline)|ccessToken(?:Claims|JWT))|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration|OnlyDeclaredScopes)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|c(?:a(?:sS(?:rvMetaDataOptions(?:Gateway|Renew)|trictMatching)|ptcha_(?:register|login|mail)_enabled)|heck(?:DevOps(?:D(?:isplayNormalizedHeaders|ownload)|CheckSessionAttributes)?|State|User|XSS)|o(?:ntextSwitching(?:Allowed2fModifications|StopWithLogout)|mpactConf|rsEnabled)|rowdsec|da)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|CertificateResetByMail|GeneratePassword|PasswordPolicy)|E(?:rrorOn(?:ExpiredSession|MailNotFound)|nablePasswordDisplay)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxy(?:AuthServiceImpersonation|UseSoap))|l(?:dap(?:(?:G(?:roup(?:DecodeSearchedValu|Recursiv)|etUserBeforePasswordChang)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|n(?:o(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|ewLocationWarning)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|re(?:st(?:(?:Password|Session|Config|Auth)Server|ExportSecretKeys)|freshSessions)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|d(?:is(?:ablePersistentStorage|playSessionId)|biDynamicHashEnabled)|to(?:tp2f(?:UserCanRemoveKey|EncryptSecret)|kenUseGlobalStorage)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|g(?:roupsBeforeMacros|lobalLogoutTimer)|a(?:voidAssignment|ctiveTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|krb(?:RemoveDomain|ByJs)|(?:wsdlServ|findUs)er)$/;
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|t(?:ayConnected(?:BypassFG)?|orePassword)|f(?:RemovedUseNotif|OnlyUpgrade)|kip(?:Upgrade|Renew)Confirmation|oap(?:Session|Config)Server|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:A(?:llow(?:(?:ClientCredentials|Password)Grant|Offline)|ccessToken(?:Claims|JWT))|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration|OnlyDeclaredScopes)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|c(?:a(?:sS(?:rvMetaDataOptions(?:Gateway|Renew)|trictMatching)|ptcha_(?:register|login|mail)_enabled)|heck(?:DevOps(?:D(?:isplayNormalizedHeaders|ownload)|CheckSessionAttributes)?|State|User|XSS)|o(?:ntextSwitching(?:Allowed2fModifications|StopWithLogout)|mpactConf|rsEnabled)|rowdsec|da)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|CertificateResetByMail|GeneratePassword|PasswordPolicy)|E(?:rrorOn(?:ExpiredSession|MailNotFound)|nablePasswordDisplay)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxy(?:AuthServiceImpersonation|UseSoap))|l(?:dap(?:(?:G(?:roup(?:DecodeSearchedValu|Recursiv)|etUserBeforePasswordChang)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|n(?:o(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|ewLocationWarning)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|re(?:st(?:(?:Password|Session|Config|Auth)Server|ExportSecretKeys)|freshSessions)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|d(?:is(?:ablePersistentStorage|playSessionId)|biDynamicHashEnabled)|to(?:tp2f(?:UserCanRemoveKey|EncryptSecret)|kenUseGlobalStorage)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|w(?:ebauthn2fUserCanRemoveKey|sdlServer)|g(?:roupsBeforeMacros|lobalLogoutTimer)|a(?:voidAssignment|ctiveTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|krb(?:RemoveDomain|ByJs)|findUser)$/;
our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );

View File

@ -385,14 +385,18 @@ sub defaultValues {
'useRedirectOnError' => 1,
'useSafeJail' => 1,
'utotp2fActivation' => 0,
'viewerHiddenKeys' => 'samlIDPMetaDataNodes, samlSPMetaDataNodes',
'webIDAuthnLevel' => 1,
'webIDExportedVars' => {},
'whatToTrace' => 'uid',
'yubikey2fActivation' => 0,
'yubikey2fPublicIDSize' => 12,
'yubikey2fSelfRegistration' => 0,
'yubikey2fUserCanRemoveKey' => 1
'viewerHiddenKeys' => 'samlIDPMetaDataNodes, samlSPMetaDataNodes',
'webauthn2fActivation' => 0,
'webauthn2fSelfRegistration' => 0,
'webauthn2fUserCanRemoveKey' => 1,
'webauthn2fUserVerification' => 'preferred',
'webIDAuthnLevel' => 1,
'webIDExportedVars' => {},
'whatToTrace' => 'uid',
'yubikey2fActivation' => 0,
'yubikey2fPublicIDSize' => 12,
'yubikey2fSelfRegistration' => 0,
'yubikey2fUserCanRemoveKey' => 1
};
}

View File

@ -4479,6 +4479,50 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
'virtualHosts' => {
'type' => 'virtualHostContainer'
},
'webauthn2fActivation' => {
'default' => 0,
'type' => 'boolOrExpr'
},
'webauthn2fAuthnLevel' => {
'type' => 'int'
},
'webauthn2fLabel' => {
'type' => 'text'
},
'webauthn2fLogo' => {
'type' => 'text'
},
'webauthn2fSelfRegistration' => {
'default' => 0,
'type' => 'boolOrExpr'
},
'webauthn2fUserCanRemoveKey' => {
'default' => 1,
'type' => 'bool'
},
'webauthn2fUserVerification' => {
'default' => 'preferred',
'select' => [ {
'k' => 'discouraged',
'v' => 'Discouraged'
},
{
'k' => 'preferred',
'v' => 'Preferred'
},
{
'k' => 'required',
'v' => 'Required'
}
],
'type' => 'select'
},
'webauthnDisplayNameAttr' => {
'type' => 'text'
},
'webauthnRpName' => {
'type' => 'text'
},
'webIDAuthnLevel' => {
'default' => 1,
'type' => 'int'

View File

@ -2191,6 +2191,55 @@ sub attributes {
documentation => 'Yubikey device time to live',
},
# WebAuthn 2FA
webauthn2fActivation => {
type => 'boolOrExpr',
default => 0,
documentation => 'WebAuthn second factor activation',
},
webauthn2fSelfRegistration => {
type => 'boolOrExpr',
default => 0,
documentation => 'WebAuthn self registration activation',
},
webauthn2fAuthnLevel => {
type => 'int',
documentation =>
'Authentication level for users authentified by WebAuthn second factor'
},
webauthn2fLabel => {
type => 'text',
documentation => 'Portal label for WebAuthn second factor'
},
webauthn2fLogo => {
type => 'text',
documentation => 'Custom logo for WebAuthn 2F',
},
webauthn2fUserVerification => {
type => 'select',
select => [
{ k => 'discouraged', v => 'Discouraged' },
{ k => 'preferred', v => 'Preferred' },
{ k => 'required', v => 'Required' },
],
default => 'preferred',
documentation => 'Verify user during registration and login',
},
webauthn2fUserCanRemoveKey => {
type => 'bool',
default => 1,
documentation => 'Authorize users to remove existing WebAuthn',
},
webauthnDisplayNameAttr => {
type => 'text',
documentation => 'Session attribute containing user display name',
},
webauthnRpName => {
type => 'text',
documentation => 'WebAuthn Relying Party display name',
},
# Single session
notifyDeleted => {
default => 1,

View File

@ -992,6 +992,21 @@ sub tree {
'rest2fLabel', 'rest2fLogo'
]
},
{
title => 'webauthn2f',
help => 'webauthn2f.html',
nodes => [
'webauthn2fActivation',
'webauthn2fUserVerification',
'webauthn2fSelfRegistration',
'webauthn2fUserCanRemoveKey',
'webauthnRpName',
'webauthnDisplayNameAttr',
'webauthn2fAuthnLevel',
'webauthn2fLabel',
'webauthn2fLogo',
]
},
'sfExtra',
{
title => 'sfRemovedNotification',

View File

@ -1213,6 +1213,16 @@
"webIDAuthnLevel":"مستوى إثبات الهوية",
"webIDExportedVars":"المتغيرات المصدرة",
"webIDWhitelist":"القائمة البيضاء للويب آي دي",
"webauthn2f":"WebAuthn",
"webauthn2fActivation":"تفعيل",
"webauthn2fAuthnLevel":"مستوى إثبات الهوية",
"webauthn2fLabel":"Label",
"webauthn2fLogo":"شعار",
"webauthn2fSelfRegistration":"التسجيل الذاتي",
"webauthn2fUserCanRemoveKey":"Allow user to remove WebAuthn",
"webauthn2fUserVerification":"User verification",
"webauthnDisplayNameAttr":"User Display Name attribute",
"webauthnRpName":"Relying Party display name",
"webidParams":"معايير ويب أي دي",
"whatToTrace":"المستخدم_البعيد",
"whiteList":"القائمة البيضاء",

View File

@ -1213,6 +1213,16 @@
"webIDAuthnLevel":"Authentication level",
"webIDExportedVars":"Exported variables",
"webIDWhitelist":"WebID whitelist",
"webauthn2f":"WebAuthn",
"webauthn2fActivation":"Activation",
"webauthn2fAuthnLevel":"Authentication level",
"webauthn2fLabel":"Label",
"webauthn2fLogo":"Logo",
"webauthn2fSelfRegistration":"Self registration",
"webauthn2fUserCanRemoveKey":"Allow user to remove WebAuthn",
"webauthn2fUserVerification":"User verification",
"webauthnDisplayNameAttr":"User Display Name attribute",
"webauthnRpName":"Relying Party display name",
"webidParams":"WebID parameters",
"whatToTrace":"REMOTE_USER",
"whiteList":"White list",

View File

@ -1213,6 +1213,16 @@
"webIDAuthnLevel":"Authentication level",
"webIDExportedVars":"Exported variables",
"webIDWhitelist":"WebID whitelist",
"webauthn2f":"WebAuthn",
"webauthn2fActivation":"Activation",
"webauthn2fAuthnLevel":"Authentication level",
"webauthn2fLabel":"Label",
"webauthn2fLogo":"Logo",
"webauthn2fSelfRegistration":"Self registration",
"webauthn2fUserCanRemoveKey":"Allow user to remove WebAuthn",
"webauthn2fUserVerification":"User verification",
"webauthnDisplayNameAttr":"User Display Name attribute",
"webauthnRpName":"Relying Party display name",
"webidParams":"WebID parameters",
"whatToTrace":"REMOTE_USER",
"whiteList":"White list",

View File

@ -1213,6 +1213,16 @@
"webIDAuthnLevel":"Nivel de autentificación",
"webIDExportedVars":"Exported variables",
"webIDWhitelist":"WebID whitelist",
"webauthn2f":"WebAuthn",
"webauthn2fActivation":"Activación",
"webauthn2fAuthnLevel":"Nivel de autentificación",
"webauthn2fLabel":"Label",
"webauthn2fLogo":"Logo",
"webauthn2fSelfRegistration":"Self registration",
"webauthn2fUserCanRemoveKey":"Allow user to remove WebAuthn",
"webauthn2fUserVerification":"User verification",
"webauthnDisplayNameAttr":"User Display Name attribute",
"webauthnRpName":"Relying Party display name",
"webidParams":"WebID parameters",
"whatToTrace":"REMOTE_USER",
"whiteList":"White list",

View File

@ -1213,6 +1213,16 @@
"webIDAuthnLevel":"Niveau d'authentification",
"webIDExportedVars":"Variables exportées",
"webIDWhitelist":"Liste blanche WebID",
"webauthn2f":"WebAuthn",
"webauthn2fActivation":"Activation",
"webauthn2fAuthnLevel":"Niveau d'authentification",
"webauthn2fLabel":"Label",
"webauthn2fLogo":"Logo",
"webauthn2fSelfRegistration":"Auto-enregistrement",
"webauthn2fUserCanRemoveKey":"Autoriser les utilisateurs à effacer leur WebAuthn",
"webauthn2fUserVerification":"Vérification de l'utilisateur",
"webauthnDisplayNameAttr":"Attribut du nom d'affichage de l'utilisateur",
"webauthnRpName":"Nom d'affichage du portail",
"webidParams":"Paramètres WebID",
"whatToTrace":"REMOTE_USER",
"whiteList":"Liste blanche",

View File

@ -1213,6 +1213,16 @@
"webIDAuthnLevel":"Livello di autenticazione",
"webIDExportedVars":"Variabili esportate",
"webIDWhitelist":"Whitelist WebID",
"webauthn2f":"WebAuthn",
"webauthn2fActivation":"Attivazione",
"webauthn2fAuthnLevel":"Livello di autenticazione",
"webauthn2fLabel":"Label",
"webauthn2fLogo":"Logo",
"webauthn2fSelfRegistration":"Auto-registrazione",
"webauthn2fUserCanRemoveKey":"Autorizza l'utente a rimuovere la WebAuthn",
"webauthn2fUserVerification":"User verification",
"webauthnDisplayNameAttr":"User Display Name attribute",
"webauthnRpName":"Relying Party display name",
"webidParams":"Parametri di WebID",
"whatToTrace":"\nREMOTE_USER",
"whiteList":"Lista bianca",

View File

@ -1213,6 +1213,16 @@
"webIDAuthnLevel":"Poziom uwierzytelnienia",
"webIDExportedVars":"Wyeksportowane zmienne",
"webIDWhitelist":"Biała lista WebID",
"webauthn2f":"WebAuthn",
"webauthn2fActivation":"Aktywacja",
"webauthn2fAuthnLevel":"Poziom uwierzytelnienia",
"webauthn2fLabel":"Etykieta",
"webauthn2fLogo":"Logo",
"webauthn2fSelfRegistration":"Samodzielna rejestracja",
"webauthn2fUserCanRemoveKey":"Pozwól użytkownikowi usunąć WebAuthn",
"webauthn2fUserVerification":"User verification",
"webauthnDisplayNameAttr":"User Display Name attribute",
"webauthnRpName":"Relying Party display name",
"webidParams":"Parametry WebID",
"whatToTrace":"REMOTE_USER",
"whiteList":"Biała lista",

View File

@ -1213,6 +1213,16 @@
"webIDAuthnLevel":"Doğrulama seviyesi",
"webIDExportedVars":"Dışa aktarılan değişkenler",
"webIDWhitelist":"WebID beyaz listesi",
"webauthn2f":"WebAuthn",
"webauthn2fActivation":"Aktivasyon",
"webauthn2fAuthnLevel":"Doğrulama seviyesi",
"webauthn2fLabel":"Etiket",
"webauthn2fLogo":"Logo",
"webauthn2fSelfRegistration":"Kendi kendine kayıt",
"webauthn2fUserCanRemoveKey":"WebAuthn'i kaldırmak için kullanıcıya izin ver",
"webauthn2fUserVerification":"User verification",
"webauthnDisplayNameAttr":"User Display Name attribute",
"webauthnRpName":"Relying Party display name",
"webidParams":"WebID parametreleri",
"whatToTrace":"REMOTE_USER",
"whiteList":"Beyaz liste",

View File

@ -1213,6 +1213,16 @@
"webIDAuthnLevel":"Mức xác thực",
"webIDExportedVars":"Xuất khẩu biến",
"webIDWhitelist":"WebID white list",
"webauthn2f":"WebAuthn",
"webauthn2fActivation":"Kích hoạt",
"webauthn2fAuthnLevel":"Mức xác thực",
"webauthn2fLabel":"Label",
"webauthn2fLogo":"Logo",
"webauthn2fSelfRegistration":"Tự đăng ký",
"webauthn2fUserCanRemoveKey":"Allow user to remove WebAuthn",
"webauthn2fUserVerification":"User verification",
"webauthnDisplayNameAttr":"User Display Name attribute",
"webauthnRpName":"Relying Party display name",
"webidParams":"Tham số WebID",
"whatToTrace":"REMOTE_USER",
"whiteList":"Danh sách trắng",

View File

@ -1213,6 +1213,16 @@
"webIDAuthnLevel":"认证等级",
"webIDExportedVars":"Exported variables",
"webIDWhitelist":"WebID whitelist",
"webauthn2f":"WebAuthn",
"webauthn2fActivation":"激活",
"webauthn2fAuthnLevel":"认证等级",
"webauthn2fLabel":"Label",
"webauthn2fLogo":"Logo",
"webauthn2fSelfRegistration":"Self registration",
"webauthn2fUserCanRemoveKey":"Allow user to remove WebAuthn",
"webauthn2fUserVerification":"User verification",
"webauthnDisplayNameAttr":"User Display Name attribute",
"webauthnRpName":"Relying Party display name",
"webidParams":"WebID parameters",
"whatToTrace":"REMOTE_USER",
"whiteList":"White list",

View File

@ -1213,6 +1213,16 @@
"webIDAuthnLevel":"驗證等級",
"webIDExportedVars":"已匯出的變數",
"webIDWhitelist":"WebID 白名單",
"webauthn2f":"WebAuthn",
"webauthn2fActivation":"啟用",
"webauthn2fAuthnLevel":"驗證等級",
"webauthn2fLabel":"標籤",
"webauthn2fLogo":"圖示",
"webauthn2fSelfRegistration":"自行註冊",
"webauthn2fUserCanRemoveKey":"允許使用者移除 WebAuthn",
"webauthn2fUserVerification":"User verification",
"webauthnDisplayNameAttr":"User Display Name attribute",
"webauthnRpName":"Relying Party display name",
"webidParams":"WebID 參數",
"whatToTrace":"REMOTE_USER",
"whiteList":"白名單",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long