From a64597ade339bdb7ed87ff57726404bfdd5f2c34 Mon Sep 17 00:00:00 2001
From: Cornelius <cornelius.amzar@bsz-bw.de>
Date: Mon, 2 Mar 2020 21:50:44 +0100
Subject: [PATCH] Secured UrlShortener against tampering by using hashes
 instead of ids (#1549)

- Note that the database upgrade tool must be run after loading this commit to ensure that the shortlinks table's hash column is correctly populated.

(cherry picked from commit 7732da3c0f0243061fdaf90485d749d122d1ec8a)
---
 config/vufind/BrowZine.ini |   2 +-
 config/vufind/config.ini   | 229 +++++++++----------------------------
 2 files changed, 57 insertions(+), 174 deletions(-)

diff --git a/config/vufind/BrowZine.ini b/config/vufind/BrowZine.ini
index 50aa8795201..e2ff9be891e 100644
--- a/config/vufind/BrowZine.ini
+++ b/config/vufind/BrowZine.ini
@@ -3,7 +3,7 @@
 ; https://thirdiron.atlassian.net/wiki/spaces/BrowZineAPIDocs/overview
 [General]
 ; BrowZine-issued access token for API
-access_token = "Passwordxx-xxxx-xxxx-xxxx-PasswordPassword"
+access_token = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
 
 ; The ID number of your library (found in your BrowZine public access URL)
 library_id = "yyy"
diff --git a/config/vufind/config.ini b/config/vufind/config.ini
index 15357a69631..19ceddd9bdb 100644
--- a/config/vufind/config.ini
+++ b/config/vufind/config.ini
@@ -624,6 +624,20 @@ sms = enabled
 ; store its path in the database (default "none").
 url_shortener = none
 
+; Which method to use for generating the short link key. Options:
+; - base62: Base62-encode the database row ID (insecure, but makes very short URLs)
+; - md5: Create a salted MD5 hash of the URL (DEFAULT: more private, but also longer)
+; ...or any hash algorithm supported by PHP's hash() function.
+url_shortener_key_type = md5
+
+; Which redirect mechanism to use when shortlinks are resolved.
+; threshold:1000 (default) : If the URL is shorter than the given size, HTTP is used, else HTML.
+; html                     : HTML meta redirect after 3 seconds with infobox.
+; http                     : Use HTTP location header for redirects.
+;                            May cause problems if the HTTP header is longer than 8192 bytes
+;                            due to long URL's.
+;url_shortener_redirect_method = threshold:1000
+
 ; This section needs to be changed to match your database connection information
 [Database]
 ; Connection string format is [platform]://[username]:[password]@[host]:[port]/[db]
@@ -704,25 +718,16 @@ database          = mysql://root@localhost/vufind
 ; Optional: Session ID parameter for SAML2 single logout support. If omitted, single
 ; logout support is disabled. Note that if SLO support is enabled, Shibboleth session
 ; ID's are tracked in external_session table which may need to be cleaned up with the
-; util/expire_external_sessions command line utility. See
+; expire_session_mappings command line utility. See
 ; https://vufind.org/wiki/configuration:shibboleth for more information on how
 ; to configure the single logout support.
 ;session_id = Shib-Session-ID
-; Check for expired session - user is automatically logged out when Shibboleth
-; session is not present (default = true if unset); note that expiration check
-; also requires session_id to be set above.
-;checkExpiredSession = false
 ; Optional: you may set attribute names and values to be used as a filter;
 ; users will only be logged into VuFind if they match these filters.
 ;userattribute_1       = entitlement
 ;userattribute_value_1 = urn:mace:dir:entitlement:common-lib-terms
 ;userattribute_2       = unscoped-affiliation
 ;userattribute_value_2 = member
-; Set to true when shibboleth attributes must be read from headers instead of
-; environment variables - for example if you use proxy server and shibboleth is
-; running on proxy side. In that case you should protect against header spoofing:
-; see https://wiki.shibboleth.net/confluence/display/SP3/SpoofChecking for details
-;use_headers           = false
 ; Required: the attribute Shibboleth uses to uniquely identify users.
 ;username              = persistent-id
 ; Required: Shibboleth login URL.
@@ -744,9 +749,6 @@ database          = mysql://root@localhost/vufind
 ;college = HTTP_COLLEGE
 ;major = HTTP_MAJOR
 ;home_library = HTTP_HOME_LIBRARY
-; Enable if you want to override mapping or required attributes for specific IdP
-; in Shibboleth.ini
-;allow_configuration_override = true
 
 ; CAS is optional.  This section only needs to exist if the
 ; Authentication Method is set to CAS.
@@ -810,6 +812,9 @@ database          = mysql://root@localhost/vufind
 ; External Content is Optional.
 ; To use multiple, separate with a comma.  Priority will be given by the order listed
 ; Account id is separated with a colon, if no id is used then no colon is necessary
+; For Amazon, use your 20-character access key in the coverimages and reviews values;
+; you must also provide your 40-character secret key in the amazonsecret value and
+; your associate ID in the amazonassociate value.
 ;
 ; IMPORTANT: Review content providers' terms of service before turning them on.
 ;            Terms may change, and not all content sources are appropriate for all
@@ -836,11 +841,9 @@ database          = mysql://root@localhost/vufind
 ; coversize setting to false:
 ;coversize = false
 
-; You can select Syndetics, LibraryThing, Summon, Booksite, OpenLibrary,
-; Contentcafe, Buchhandel.de, Google Books, BrowZine, ObalkyKnih and/or LocalFile.
+; You can select Syndetics, LibraryThing, Summon, Amazon, Booksite, OpenLibrary,
+; Contentcafe, Buchhandel.de, Google Books, BrowZine and/or LocalFile.
 ;   Note: BrowZine requires you to have BrowZine.ini configured appropriately.
-;   Note: ObalkyKnih could be configured in obalkyknih.ini file. You should also
-;       add API URLs to img-src directive in contentsecuritypolicy.ini
 ;   Note: Summon service takes a Serials Solutions client key, NOT Summon API key!
 ;   For LocalFile:PathToFile, you may use a combination of directory path information
 ;        and tokens for filename and image type. If you have multiple directories
@@ -859,7 +862,7 @@ database          = mysql://root@localhost/vufind
 ;          %vufind-home%      - The VUFIND_HOME environment variable
 ;          %vufind-local-dir% - The VUFIND_LOCAL_DIR environment variable
 ;        Example: LocalFile:%vufind-local-dir%/path/to/file/%size%/issn/%issn%.%anyimage%
-;coverimages     = Syndetics:MySyndeticsId,Booksite,LibraryThing:MyLibraryThingId,Google,ObalkyKnih,OpenLibrary,Summon:MySerialsSolutionsClientKey,Contentcafe:MyContentCafeID,BrowZine,LocalFile:PathToFile
+;coverimages     = Syndetics:MySyndeticsId,Amazon:MyAccessKeyId,Booksite,LibraryThing:MyLibraryThingId,Google,OpenLibrary,Summon:MySerialsSolutionsClientKey,Contentcafe:MyContentCafeID,BrowZine,LocalFile:PathToFile
 
 ; This setting controls which services will have images cached on your local disk.
 ; Set to true to cache all applicable services. Set to false to disable caching. Set
@@ -875,16 +878,6 @@ coverimagesCache = true
 ; "/.*/" to turn on caching for all proxied images.
 ;coverproxyCache[] = "/.*\.?mylibrary\.edu/"
 
-; This setting controls how cover image URLs are loaded. They could be loaded as
-; part of main request, or asynchronously. Asynchronous loading is disabled by
-; default; to enable it, just uncomment the line below.
-;ajaxcovers = true
-
-; When ajaxcovers is set to true, this setting controls whether the AJAX Handler
-; GetRecordCover renders a fallback template (record/coverReplacement.phtml) in case
-; no cover image could be loaded.
-;useCoverFallbacksOnFail = false
-
 ; These settings control the image to display when no book cover is available.
 ; If makeDynamicCovers is not false and the GD library is installed, VuFind will draw
 ; cover images on the fly. See [DynamicCovers] below for more settings. If set to
@@ -896,12 +889,13 @@ coverimagesCache = true
 ; path relative to the base of your theme directory for a static image to display.
 noCoverAvailableImage = images/noCover2.gif
 
-; You can select from Syndetics, SyndeticsPlus, Booksite and/or the Guardian
+; You can select from Syndetics, SyndeticsPlus, Amazon Editorial, Amazon, Booksite
+; and/or the Guardian
 ;   Note: If the API key is omitted, e.g. "Guardian:", only the review title, byline,
 ;         Guardian logo and a link to the full Guardian page will be displayed
 ;   Note: The Guardian API changed in 2014; if you signed up before that date, you
 ;         may need to obtain a new API key for continued access.
-;reviews         = Syndetics:MySyndeticsId,SyndeticsPlus:MySyndeticsID,Booksite,Guardian:MyGuardianKeyId
+;reviews         = Syndetics:MySyndeticsId,SyndeticsPlus:MySyndeticsID,AmazonEditorial:MyAccessKeyId,Amazon:MyAccessKeyId,Booksite,Guardian:MyGuardianKeyId
 
 ; You can select from Syndetics or SyndeticsPlus
 ;excerpts        = Syndetics:MySyndeticsId,SyndeticsPlus:MySyndeticsId
@@ -932,6 +926,15 @@ noCoverAvailableImage = images/noCover2.gif
 ; heap size settings.  For details, see: https://vufind.org/jira/browse/VUFIND-630
 authors         = Wikipedia
 
+; You can look up your secret key by logging into http://aws.amazon.com and clicking
+; "Access Identifiers" under "Your Account".
+;amazonsecret    = MyAmazonSecretKey
+
+; You can sign up for an associate ID by logging into
+; https://affiliate-program.amazon.com .  Please make sure your instance of VuFind
+; complies with Amazon's agreements before enabling this feature.
+;amazonassociate = MyAmazonAssociateID
+
 ; You can select from Google, OpenLibrary, HathiTrust.  You should consult
 ; https://developers.google.com/books/branding before using Google Book Search.
 ;previews       = Google,OpenLibrary,HathiTrust
@@ -1155,17 +1158,10 @@ url = "https://api.booksite.com"
 [DOI]
 ; This setting controls whether or not DOI-based links are enabled, and which
 ; API is used to fetch the data. Currently supported options: BrowZine (requires
-; credentials to be configured in BrowZine.ini), Unpaywall or false (to disable).
-; Disabled by default. You may also use a comma-separated list of resolvers if you
-; want to try multiple sources.
+; credentials to be configured in BrowZine.ini), Unpaywall or false (to disable). Disabled
+; by default.
 ;resolver = BrowZine
 
-; If you use multiple values in the resolver setting above, you can determine how the
-; software should behave when multiple resolvers return results for the same DOI.
-; You can choose "first" (only return results from the first matching resolver --
-; the default behavior) or "merge" (merge together all results and show them all).
-;multi_resolver_mode = first
-
 ;unpaywall_api_url = "https://api.unpaywall.org/v2"
 ; Unpaywall needs an email adress, see https://unpaywall.org/products/api
 ;unpaywall_email = "your@email.org"
@@ -1206,8 +1202,6 @@ window_settings = "toolbar=no,location=no,directories=no,buttons=no,status=no,me
 ; If you want to display a graphical link to your link resolver, uncomment the
 ; settings below.  graphic should be a URL; graphic_width and graphic_height
 ; should be sizes in pixels.
-; Note: You will probably will need to add URL of image to img-src setting
-; in contentsecuritypolicy.ini file
 ;graphic = "http://myuniversity.edu/images/findIt.gif"
 ;graphic_width = 50
 ;graphic_height = 20
@@ -1356,59 +1350,8 @@ url             = https://www.myendnoteweb.com/EndNoteWeb.html
 ;host = your.proxy.server
 ;port = 8000
 
-; Uncomment one of the following lines to set proxy type to SOCKS 5 or SOCKS 5 with
-; name resolution done by proxy. Setting either of these will make VuFind use the
-; curl adapter for HTTP requests.
+; Uncomment following line to set proxy type to SOCKS 5
 ;type = socks5
-;type = socks5_hostname
-
-; If VuFind is running behind a proxy that uses X-Real-IP/X-Forwarded-For headers,
-; you should configure this setting on so that VuFind reports correct user IP
-; addresses, and sets permissions appropriately. CONFIGURE THIS WITH CARE! It is
-; possible to spoof IP addresses, and configuring this to differentiate between
-; legitimate headers from your proxy and spoofed values is critical to protecting
-; your content.
-;
-; The setting should be an ordered, comma-separated list of headers, with optional
-; colon-separated modifiers specifying behavior.
-;
-; Header values can be any keys in PHP's $_SERVER superglobal array; these are
-; the most commonly used options:
-; - HTTP_X_FORWARDED_FOR
-; - HTTP_X_REAL_IP
-;
-; Supported behaviors (if unspecified, "single" is the default behavior):
-; - first (pick the first comma-separated value; e.g. "a" in "a, b, c")
-; - last (pick the last comma-separated value; e.g. "c" in "a, b, c")
-; - single (enforce single values; completely ignore multi-valued headers)
-;
-; See also forwarded_ip_filter below for a way to filter out known IP addresses
-; of internal network devices before applying first/last/single settings.
-;
-; When commented out or set to false, only the regular REMOTE_ADDR value will
-; be used for IP detection. REMOTE_ADDR will also be used as the default value
-; if none of the configured headers are populated.
-;
-; If you need to implement more nuanced functionality, you can extend or
-; override the VuFind\Net\UserIpReader class to implement your own logic.
-;
-; You can use a header-modifying browser plugin to determine how your proxy
-; will respond to spoofing attempts.
-;
-; See this wiki page for additional notes and comments:
-; https://vufind.org/wiki/administration:security#proxies_and_ip_authentication
-;
-; The example below, if uncommented, will use X-Real-IP if found, and the
-; rightmost value of X-Forwarded-For otherwise (resorting to REMOTE_ADDR only
-; if no relevant X- headers are found).
-;allow_forwarded_ips = "HTTP_X_REAL_IP:single,HTTP_X_FORWARDED_FOR:last"
-
-; This setting can be used in combination with allow_forwarded_ips to prevent
-; known IP addresses of internal proxies and network devices from being reported
-; as end user IP addresses. You can repeat the setting for each IP address that
-; you wish to exclude. The first/last/single processing parameters used by
-; allow_forwarded_ips will be applied AFTER removing addresses filtered here.
-;forwarded_ip_filter[] = 1.2.3.4
 
 ; Default HTTP settings can be loaded here. These values will be passed to
 ; the \Zend\Http\Client's setOptions method.
@@ -1422,12 +1365,6 @@ url             = https://www.myendnoteweb.com/EndNoteWeb.html
 ; that you may also need to install CURL and PHP/CURL packages on your server.
 ;adapter = 'Zend\Http\Client\Adapter\Curl'
 
-; Set curl options if required. See
-; https://www.php.net/manual/en/function.curl-setopt.php for available options and
-; https://github.com/curl/curl/blob/master/include/curl/curl.h for their numeric
-; values.
-;curloptions[52] = true
-
 ; Spelling Suggestions
 ;
 ; Note: These settings affect the VuFind side of spelling suggestions; you
@@ -1500,18 +1437,6 @@ skip_numeric = true
 ; - Add /slack to the end of your url for Slack-compatible messages
 ; https://discordapp.com/developers/docs/resources/webhook#execute-slackcompatible-webhook
 
-; You can use Office365 webhooks to send messages to a Microsoft Team channel.
-; In the "Connectors" setting on a channel, you can add "Incoming Webhook." This
-; will provide a URL that you can paste into the office365_url setting.
-; If you are concerned about rate limits, you might also wish to set up the
-; VuOwma message aggregator; see https://github.com/FalveyLibraryTechnology/VuOwma
-;office365_url = "https://outlook.office.com/webhook/xxx/IncomingWebhook/yyy"
-; This setting controls the error levels that will be logged to Office365; if
-; commented out, Office365 logging will be disabled
-;office365 = alert,error
-; This setting controls the title on the messages displayed in Office365:
-;office365_title = "VuFind Log"
-
 ; This section can be used to specify a "parent configuration" from which
 ; the current configuration file will inherit.  You can chain multiple
 ; configurations together if you wish.
@@ -1519,7 +1444,7 @@ skip_numeric = true
 ; Full path to parent configuration file:
 ;path = /usr/local/vufind/application/config/config.ini
 ; Path to parent configuration file (relative to the location of this file):
-;relative_path = ../parentconfig/config.ini
+;relative_path = ../masterconfig/config.ini
 
 ; A comma-separated list of config sections from the parent which should be
 ; completely overwritten by the equivalent sections in this configuration;
@@ -1594,10 +1519,6 @@ rtl_langs = "ar,he"
 ; have a large index!
 [Browse]
 result_limit    = 100
-
-; These settings can be used to turn specific browse types on or off; the order
-; of the settings in the configuration below will also control the order of the
-; options displayed in the web interface:
 tag             = true      ; allow browsing of Tags
 dewey           = false     ; allow browsing of Dewey Decimal call numbers
 lcc             = true      ; allow browsing of LC call numbers
@@ -1606,7 +1527,6 @@ topic           = true      ; allow browsing of subject headings
 genre           = true      ; allow browsing of genre subdivisions
 region          = true      ; allow browsing of region subdivisions
 era             = true      ; allow browsing of era subdivisions
-
 ; You can use this setting to change the default alphabet provided for browsing:
 ;alphabet_letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 ; Uncomment to sort lists alphabetically (instead of by popularity); note that
@@ -1719,15 +1639,6 @@ jump_to_single_search_result = false
 ; punctuation, but this can be used when ISBD punctuation is absent (e.g. ", ").
 ;marcPublicationInfoSeparator = " "
 
-; If you have a custom index, you might want to change the field where the full
-; MARC record is supposed to be. The field will be checked and ignored, if it is
-; not a valid index field or does not exist in the record or index schema.
-; If you have multiple fields with MARC content, you may add all of them
-; by using a comma sepated list. The first field is the preferred one, if it does not
-; exist, the next ones are taken.
-; (Default = "fullrecord")
-preferredMarcFields = "fullrecord"
-
 ; When displaying publication information from 260/264, this can be set to true
 ; to make 264 information completely replace 260 information. Default is false,
 ; which will display information from 260 AND 264 when both fields are populated.
@@ -1880,7 +1791,7 @@ treeSearchLimit = 100
 ;sender_name       = "VuFind Feedback"
 
 ; Note: for additional details about stats (including additional notes on Google
-; Analytics and Matomo/Piwik), look at the wiki page:
+; Analytics and Piwik), look at the wiki page:
 ;     https://vufind.org/wiki/configuration:usage_stats
 
 ; Uncomment this section and provide your API key to enable Google Analytics. Be
@@ -1891,20 +1802,18 @@ treeSearchLimit = 100
 ;apiKey = "mykey"
 ;universal = false
 
-; The Piwik product has been renamed to Matomo, but for backward compatibility,
-; the terminology has not yet been changed in VuFind. Uncomment this section and
-; provide your Matomo or Piwik server address and site id to enable Matomo/Piwik
-; analytics. Note: VuFind's Matomo/Piwik integration uses several custom variables;
-; to take advantage of them, you must reconfigure Matomo/Piwik by switching
+; Uncomment this section and provide your Piwik server address and site id to
+; enable Piwik analytics. Note: VuFind's Piwik integration uses several custom
+; variables; to take advantage of them, you must reconfigure Piwik by switching
 ; to its root directory and running this command to raise a default limit:
 ; ./console customvariables:set-max-custom-variables 10
 [Piwik]
 ;url = "http://server.address/piwik/"
 ;site_id = 1
 ; Uncomment the following setting to track additional information about searches
-; and displayed records with Matomo/Piwik's custom variables
+; and displayed records with Piwik's custom variables
 ;custom_variables = true
-; By default, searches are tracked using the format "Backend|Search Terms."
+; By default, Piwik searches are tracked using the format "Backend|Search Terms."
 ; If you need to differentiate searches coming from multiple VuFind instances using
 ; a shared site_id, you can set the searchPrefix to add an additional prefix to
 ; the string, for example "SiteA|Backend|Search Terms." Most users will want to
@@ -1956,46 +1865,22 @@ treeSearchLimit = 100
 ;EDS = "EBSCO Discovery Service"
 
 ; Activate Captcha validation on select forms
-; VuFind can use Captcha validation to prevent bots from using certain actions of
-; your instance.
+; VuFind will use reCaptcha validation to prevent bots from using certain actions of
+; your instance. See http://www.google.com/recaptcha for more information on Captcha
+; and create keys for your domain.
+; You will need to provide a sslcapath in the [Http] section for your Captcha to work.
 ;[Captcha]
-; Valid type values:
-; - figlet (generate a text-based message for the user to interpret)
-; - image (generate a local image for the user to interpret)
-; - recaptcha (use Google's ReCaptcha service)
-; If multiple values are given, the user will be able to pick his favorite.
-; See below for additional type-specific settings.
-;types[] = recaptcha
-
-; The "forms" setting controls the contexts in which CAPTCHA will be presented. It
-; can be either a comma-separated list of forms, or "*" to display CAPTCHA on all
-; supported forms. Valid forms values:
-;       changeEmail, changePassword, email, feedback, newAccount, passwordRecovery,
-;       sms, userComments
+;siteKey  = "get your reCaptcha key at"
+;secretKey = "https://www.google.com/recaptcha/admin/create"
+; Valid theme values: dark, light
+;theme      = light
+; Valid forms values: changePassword, email, feedback, newAccount, passwordRecovery,
+;                     sms, userComments
+; Use * for all supported forms
 ; Note: when "feedback" is active, Captcha can be conditionally disabled on a
 ;       form-by-form basis with the useCaptcha setting in FeedbackForms.yaml.
-;forms = *
-
-; Figlet options, see:
-;      https://docs.laminas.dev/laminas-captcha/adapters/#laminascaptchafiglet
-;figlet_length = 8
-
-; Image options, see:
-;      https://docs.laminas.dev/laminas-captcha/adapters/#laminascaptchaimage
-;image_length = 8
-;image_width = 200
-;image_height = 50
-;image_fontSize = 24
-;image_dotNoiseLevel = 100
-;image_lineNoiseLevel = 5
-
-; See http://www.google.com/recaptcha for more information on reCAPTCHA and to
-; create keys for your domain. Make sure that SSL settings are correct in the
-; [Http] section, or your Captcha may not work.
-;recaptcha_siteKey  = "get your reCaptcha key at"
-;recaptcha_secretKey = "https://www.google.com/recaptcha/admin/create"
-; Valid theme values: dark, light
-;recaptcha_theme      = light
+;forms = changeEmail, changePassword, email, newAccount, passwordRecovery, sms
+
 
 ; This section can be used to display default text inside the search boxes, useful
 ; for instructions. Format:
@@ -2034,8 +1919,6 @@ lists_view=full
 ; Tags may be "enabled" or "disabled" (default = "enabled")
 ; When disabling tags, don't forget to also turn off tag search in searches.ini.
 tags = enabled
-; User list tags may be "enabled" or "disabled" (default = "disabled")
-listTags = disabled
 ; This controls the maximum length of a single tag; it should correspond with the
 ; field size in the tags database table.
 max_tag_length = 64
-- 
GitLab