diff --git a/.gitignore b/.gitignore index acad6e2..d419d98 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -SOURCES/mod_auth_mellon-0.11.0.tar.gz +SOURCES/mod_auth_mellon-0.13.1.tar.gz +SOURCES/user_guide.tar.gz diff --git a/.mod_auth_mellon.metadata b/.mod_auth_mellon.metadata index 4bee861..56de7c2 100644 --- a/.mod_auth_mellon.metadata +++ b/.mod_auth_mellon.metadata @@ -1 +1,2 @@ -57403fad4595fae773abae04b631cacfbe5948f5 SOURCES/mod_auth_mellon-0.11.0.tar.gz +a0e8edcb4ecbbc2b37b98ce394ed17bee1b622a3 SOURCES/mod_auth_mellon-0.13.1.tar.gz +f1ecf8e6e809edcb5b595be206b745fe1dcfc5be SOURCES/user_guide.tar.gz diff --git a/SOURCES/content-type.patch b/SOURCES/content-type.patch deleted file mode 100644 index 7b8b54a..0000000 --- a/SOURCES/content-type.patch +++ /dev/null @@ -1,36 +0,0 @@ -commit 040a1ae5cb2aab38b2bc716cc3d0d6fa7b998a7a -Author: John Dennis -Date: Mon Jan 16 09:02:06 2017 -0500 - - Use ap_set_content_type() to set "Content-Type" header - - Formerly we were setting the response header "Content-Type" in - r->headers_out directly via the apr_table_setn() call. Although using - apr_table_setn() is appropriate for many HTTP headers Apache actively - manages a small set of headers in - http_filters.c:ap_http_header_filter(). These managed headers are - derived from values maintained in the request_rec. "Content-Type" is - one of the managed headers. - - Because we didn't set r->content_type field via the - ap_set_content_type() call and instead directly updated the - r->headers_out table our value for "Content-Type" was overwriten when - the ap_http_header_filter() was run just prior to emitting the - response with the result the "Content-Type" header returned to the - client was incorrect. - - Signed-off-by: John Dennis - -diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c -index a55828a..25365de 100644 ---- a/auth_mellon_handler.c -+++ b/auth_mellon_handler.c -@@ -2655,7 +2655,7 @@ static int am_set_authn_request_post_content(request_rec *r, LassoLogin *login) - */ - static int am_set_authn_request_paos_content(request_rec *r, LassoLogin *login) - { -- apr_table_setn(r->headers_out, "Content-Type", MEDIA_TYPE_PAOS); -+ ap_set_content_type(r, MEDIA_TYPE_PAOS); - ap_rputs(LASSO_PROFILE(login)->msg_body, r); - - return OK; diff --git a/SOURCES/ecp_doc.patch b/SOURCES/ecp_doc.patch deleted file mode 100644 index 2acd5de..0000000 --- a/SOURCES/ecp_doc.patch +++ /dev/null @@ -1,29 +0,0 @@ -commit 39017b2957fc7f046725339f1914eb7a87db2bea -Author: John Dennis -Date: Fri Apr 8 09:17:17 2016 -0400 - - Fix Content-Type, should be "text/xml" not "application/soap+xml" - - There was an error in the example for POST'ing the the AuthnRequest to - the IdP, the Content-Type header erroneously was - "application/soap+xml" when in fact it should have been "text/xml". - - As background the Content-Type for SOAP 1.1 is "text/xml" but in SOAP - 1.2 it was changed to "application/soap+xml". ECP is specificed to - used SOAP 1.1. - - Signed-off-by: John Dennis - -diff --git a/ECP.rst b/ECP.rst -index 4add62a..927ce13 100644 ---- a/ECP.rst -+++ b/ECP.rst -@@ -140,7 +140,7 @@ operations. - response = session.post(ecp.msgUrl, - data=ecp.msgBody, - auth=requests.auth.HTTPDigestAuth(user, password) -- headers={'Content-Type': 'application/soap+xml'}) -+ headers={'Content-Type': 'text/xml'}) - - # Process returned SOAP wrapped from IdP - ecp.processResponseMsg(response.text) diff --git a/SOURCES/enabled_in_check_uid.patch b/SOURCES/enabled_in_check_uid.patch deleted file mode 100644 index ba99055..0000000 --- a/SOURCES/enabled_in_check_uid.patch +++ /dev/null @@ -1,34 +0,0 @@ -commit 912aa852ebd78577f59cf7958c709acea98ace4c -Author: John Dennis -Date: Fri Apr 8 09:01:22 2016 -0400 - - am_check_uid() should be no-op if mellon not enabled - - mod_auth_mellon was interferring with other Apache authentication - modules (e.g. mod_auth_kerb) because when the Apache check_user_id - hook ran the logic in am_check_uid would execute even if mellon was - not enabled for the location. This short circuited the hook execution - and never allowed the authentication enabled for the location to - execute. It resulted in HTTP_UNAUTHORIZED being returned with the - client then expecting a WWW-Authenticate header field causing the - client to attempt to authenticate again. - - Signed-off-by: John Dennis - -diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c -index a72e1ca..864396f 100644 ---- a/auth_mellon_handler.c -+++ b/auth_mellon_handler.c -@@ -3625,6 +3625,12 @@ int am_check_uid(request_rec *r) - return OK; - } - -+ /* Check that the user has enabled authentication for this directory. */ -+ if(dir->enable_mellon == am_enable_off -+ || dir->enable_mellon == am_enable_default) { -+ return DECLINED; -+ } -+ - #ifdef HAVE_ECP - am_req_cfg_rec *req_cfg = am_get_req_cfg(r); - if (req_cfg->ecp_authn_req) { diff --git a/SOURCES/lasso_error_check.patch b/SOURCES/lasso_error_check.patch new file mode 100644 index 0000000..f9cc4ca --- /dev/null +++ b/SOURCES/lasso_error_check.patch @@ -0,0 +1,70 @@ +commit 2c2e19d96069f2d94d6c68f50e3ef2175a412cfb +Author: Olav Morken +Date: Tue Aug 8 14:34:24 2017 +0200 + + Fix incorrect error check for many `lasso_*`-functions. + + Several places in the code we assumed that Lasso error codes were + negative, however some of them are positive integers. This patch + ensures that we do direct check for a zero return code in all cases. + + Fixes issue #128. + +diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c +index 70462a7..5661083 100644 +--- a/auth_mellon_handler.c ++++ b/auth_mellon_handler.c +@@ -640,7 +640,7 @@ static void am_restore_lasso_profile_state(request_rec *r, + identity_dump = am_cache_get_lasso_identity(am_session); + if(identity_dump != NULL) { + rc = lasso_profile_set_identity_from_dump(profile, identity_dump); +- if(rc < 0) { ++ if(rc != 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Could not restore identity from dump." + " Lasso error: [%i] %s", rc, lasso_strerror(rc)); +@@ -651,7 +651,7 @@ static void am_restore_lasso_profile_state(request_rec *r, + session_dump = am_cache_get_lasso_session(am_session); + if(session_dump != NULL) { + rc = lasso_profile_set_session_from_dump(profile, session_dump); +- if(rc < 0) { ++ if(rc != 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Could not restore session from dump." + " Lasso error: [%i] %s", rc, lasso_strerror(rc)); +@@ -1842,7 +1842,7 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login, + } + + rc = lasso_login_accept_sso(login); +- if(rc < 0) { ++ if(rc != 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Unable to accept SSO message." + " Lasso error: [%i] %s", rc, lasso_strerror(rc)); +@@ -2157,7 +2157,7 @@ static int am_handle_artifact_reply(request_rec *r) + rc = lasso_login_init_request(login, r->args, + LASSO_HTTP_METHOD_ARTIFACT_GET); + +- if(rc < 0) { ++ if(rc != 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to handle login response." + " Lasso error: [%i] %s", rc, lasso_strerror(rc)); +@@ -2181,7 +2181,7 @@ static int am_handle_artifact_reply(request_rec *r) + ap_unescape_url(saml_art); + + rc = lasso_login_init_request(login, saml_art, LASSO_HTTP_METHOD_ARTIFACT_POST); +- if(rc < 0) { ++ if(rc != 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to handle login response." + " Lasso error: [%i] %s", rc, lasso_strerror(rc)); +@@ -2192,7 +2192,7 @@ static int am_handle_artifact_reply(request_rec *r) + + /* Prepare SOAP request. */ + rc = lasso_login_build_request_msg(login); +- if(rc < 0) { ++ if(rc != 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to prepare SOAP message for HTTP-Artifact" + " resolution." diff --git a/SOURCES/lasso_provider_warning.patch b/SOURCES/lasso_provider_warning.patch deleted file mode 100644 index 1163574..0000000 --- a/SOURCES/lasso_provider_warning.patch +++ /dev/null @@ -1,33 +0,0 @@ -commit 5ba9bb72707a90503cd4d042083ea074a0cb6b8a -Author: John Dennis -Date: Fri Oct 30 15:46:33 2015 -0400 - - Role maybe unknown when assertion consumer url is looked up - - Replace the call to lasso_provider_get_metadata_one() with - lasso_provider_get_metadata_one_for_role() so that we can exlicitly - pass the LASSO_PROVIDER_ROLE_SP role. The former call obtains the - role from the provider object and then calls - lasso_provider_get_metadata_one_for_role() using that role. However - the role will not have been set in the provider until the first request is - processed. This means the first time we call this routine it won't - work correctly because the role will not have been set yet, by - explicitly passing the role we avoid this problem. - - Signed-off-by: John Dennis - -diff --git a/auth_mellon_util.c b/auth_mellon_util.c -index 155bb1a..6c694b7 100644 ---- a/auth_mellon_util.c -+++ b/auth_mellon_util.c -@@ -1827,7 +1827,9 @@ char *am_get_assertion_consumer_service_by_binding(LassoProvider *provider, cons - } - - if (selected_descriptor) { -- url = lasso_provider_get_metadata_one(provider, selected_descriptor); -+ url = lasso_provider_get_metadata_one_for_role(provider, -+ LASSO_PROVIDER_ROLE_SP, -+ selected_descriptor); - } - - lasso_release_list_of_strings(descriptors); diff --git a/SOURCES/log_no_idp.patch b/SOURCES/log_no_idp.patch new file mode 100644 index 0000000..c51f30b --- /dev/null +++ b/SOURCES/log_no_idp.patch @@ -0,0 +1,42 @@ +commit daa5d1e66791a155dc74b220f16422ba206b8788 +Author: John Dennis +Date: Tue Jun 13 09:34:36 2017 -0400 + + If no IdP's are defined explicitly log that fact + + Sometimes configuration errors are made and a location does have any + IdP's defined for it. Previosly the error message in this case was: + + "Error adding IdP to lasso server object. Please verify the following + configuration directives: MellonIdPMetadataFile and + MellonIdPPublicKeyFile." + + But this message is misleading, it suggests an attempt was made to add + the IdP but somehow it failed, this will often cause folks to try to + determine what is wrong with the IdP metadata file, which may in fact + be defined in the mellon config but because of location inheritance is + not being included in the per directory config. + + It would be much more helpful to indicate no IdP's were defined for + this config location which is clearly a different problem than + suggesting an attempt was made to add an IdP but it failed. + + Signed-off-by: John Dennis + +diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c +index 44a5ee9..2004752 100644 +--- a/auth_mellon_handler.c ++++ b/auth_mellon_handler.c +@@ -242,6 +242,12 @@ static guint am_server_add_providers(am_dir_cfg_rec *cfg, request_rec *r) + idp_public_key_file = NULL; + #endif /* ! HAVE_lasso_server_load_metadata */ + ++ if (cfg->idp_metadata->nelts == 0) { ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ "Error, URI \"%s\" has no IdP's defined", r->uri); ++ return 0; ++ } ++ + for (index = 0; index < cfg->idp_metadata->nelts; index++) { + const am_metadata_t *idp_metadata; + int error; diff --git a/SOURCES/log_typo.patch b/SOURCES/log_typo.patch new file mode 100644 index 0000000..ff0cf6a --- /dev/null +++ b/SOURCES/log_typo.patch @@ -0,0 +1,52 @@ +commit 4c924d9062406762c44ce95bdee14dadf4bfeed2 +Author: Thijs Kinkhorst +Date: Sun Jul 9 14:42:29 2017 +0000 + + Fix some log message typos + +diff --git a/auth_mellon_cache.c b/auth_mellon_cache.c +index 9a5bb0e..cd3b9b0 100644 +--- a/auth_mellon_cache.c ++++ b/auth_mellon_cache.c +@@ -740,7 +740,7 @@ int am_cache_set_lasso_state(am_cache_entry_t *session, + lasso_identity); + if (status != 0) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, +- "Lasso identity is to big for storage. Size of lasso" ++ "Lasso identity is too big for storage. Size of lasso" + " identity is %" APR_SIZE_T_FMT ".", + (apr_size_t)strlen(lasso_identity)); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -751,7 +751,7 @@ int am_cache_set_lasso_state(am_cache_entry_t *session, + lasso_session); + if (status != 0) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, +- "Lasso session is to big for storage. Size of lasso" ++ "Lasso session is too big for storage. Size of lasso" + " session is %" APR_SIZE_T_FMT ".", + (apr_size_t)strlen(lasso_session)); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -762,8 +762,8 @@ int am_cache_set_lasso_state(am_cache_entry_t *session, + lasso_saml_response); + if (status != 0) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, +- "Lasso SAML response is to big for storage. Size of " +- "lasso SAML Reponse is %" APR_SIZE_T_FMT ".", ++ "Lasso SAML response is too big for storage. Size of " ++ "lasso SAML Response is %" APR_SIZE_T_FMT ".", + (apr_size_t)strlen(lasso_saml_response)); + return HTTP_INTERNAL_SERVER_ERROR; + } +diff --git a/auth_mellon_util.c b/auth_mellon_util.c +index 34cf88d..19bfb41 100644 +--- a/auth_mellon_util.c ++++ b/auth_mellon_util.c +@@ -1823,7 +1823,7 @@ tokenize(apr_pool_t *pool, const char *str, bool ignore_whitespace, + } + if (*p != '\"') { + *error = apr_psprintf(pool, +- "unterminated string begining at " ++ "unterminated string beginning at " + "position %" APR_SIZE_T_FMT " in \"%s\"", + start-str, str); + break; diff --git a/SOURCES/mellon_user_case_insensitive.patch b/SOURCES/mellon_user_case_insensitive.patch new file mode 100644 index 0000000..5dad36b --- /dev/null +++ b/SOURCES/mellon_user_case_insensitive.patch @@ -0,0 +1,41 @@ +commit c29123244e546986ff3c9e6fe94772c4411adf2b +Author: Olav Morken +Date: Wed Aug 16 17:28:16 2017 +0200 + + Make MellonUser case-insensitive. + + MellonUser used to perform its attribute match in a case-sesnsitive + manner, while environment variables are stored in a case-insensitive + table in Apache. + + The result is a bit of inconsistency between the way mod_auth_mellon + handles the attribute names and the way they are accessed other places + in Apache. + + This patch changes the code to use a case-insensitive match when + processing the MellonUser directive. + + Fixes issue #131. + +diff --git a/auth_mellon_cache.c b/auth_mellon_cache.c +index cd3b9b0..7d51589 100644 +--- a/auth_mellon_cache.c ++++ b/auth_mellon_cache.c +@@ -552,7 +552,7 @@ void am_cache_env_populate(request_rec *r, am_cache_entry_t *t) + if (am_cache_entry_slot_is_empty(&t->user)) { + for(i = 0; i < t->size; ++i) { + varname = am_cache_entry_get_string(t, &t->env[i].varname); +- if (strcmp(varname, d->userattr) == 0) { ++ if (strcasecmp(varname, d->userattr) == 0) { + value = am_cache_entry_get_string(t, &t->env[i].value); + status = am_cache_entry_store_string(t, &t->user, value); + if (status != 0) { +@@ -592,7 +592,7 @@ void am_cache_env_populate(request_rec *r, am_cache_entry_t *t) + * If we find a variable remapping to MellonUser, use it. + */ + if (am_cache_entry_slot_is_empty(&t->user) && +- (strcmp(varname, d->userattr) == 0)) { ++ (strcasecmp(varname, d->userattr) == 0)) { + status = am_cache_entry_store_string(t, &t->user, value); + if (status != 0) { + ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, diff --git a/SOURCES/post_segfault.patch b/SOURCES/post_segfault.patch new file mode 100644 index 0000000..2d20e16 --- /dev/null +++ b/SOURCES/post_segfault.patch @@ -0,0 +1,38 @@ +commit 5c5ed1d6ab2798b4833a12b81f77aca3f82e86f0 +Author: Olav Morken +Date: Tue Aug 8 09:45:10 2017 +0200 + + Fix segmentation fault with POST field without a value. + + This patch fixes a segmentation fault that can occur after the user + has logged in if the server is configured to replay POST data from + before login. If the POST data contained a field without a value we + would attempt to pass a constant string to the + am_urldecode()-function, which would crash with a segmentation fault. + + This patch fixes that by using an empty string allocated on the stack + instead of a constant string. + + Fixes #115. + +diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c +index f073721..70462a7 100644 +--- a/auth_mellon_handler.c ++++ b/auth_mellon_handler.c +@@ -2329,6 +2329,7 @@ const char *am_post_mkform_urlencoded(request_rec *r, const char *post_data) + const char *item; + char *last; + char *post_form = ""; ++ char empty_value[] = ""; + + for (item = am_xstrtok(r, post_data, "&", &last); item; + item = am_xstrtok(r, NULL, "&", &last)) { +@@ -2344,7 +2345,7 @@ const char *am_post_mkform_urlencoded(request_rec *r, const char *post_data) + continue; + + if (value == NULL) +- value = (char *)""; ++ value = empty_value; + + if (am_urldecode(name) != OK) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, diff --git a/SOURCES/update_log_invalid_dst.patch b/SOURCES/update_log_invalid_dst.patch new file mode 100644 index 0000000..17c328d --- /dev/null +++ b/SOURCES/update_log_invalid_dst.patch @@ -0,0 +1,32 @@ +commit 93faba4505b2c02c4885d33f785db97efd6f9c1b +Author: nneul at neulinger.org +Date: Fri Oct 6 12:08:58 2017 +0000 + + Update log msg for Invalid Destination and Invalid Audience to show both the expected and received values. + +diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c +index afb3195..030abe7 100644 +--- a/auth_mellon_handler.c ++++ b/auth_mellon_handler.c +@@ -1461,8 +1461,8 @@ static int am_validate_conditions(request_rec *r, + + if (ar->Audience == NULL || strcmp(ar->Audience, providerID)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, +- "Invalid Audience in Conditions. Should be: %s", +- providerID); ++ "Invalid Audience in Conditions. Should be '%s', but was '%s'", ++ providerID, ar->Audience ? ar->Audience : ""); + return HTTP_BAD_REQUEST; + } + } +@@ -1791,8 +1791,8 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login, + if (response->parent.Destination) { + if (strcmp(response->parent.Destination, url)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, +- "Invalid Destination on Response. Should be: %s", +- url); ++ "Invalid Destination on Response. Should be '%s', but was '%s'", ++ url, response->parent.Destination); + lasso_login_destroy(login); + return HTTP_BAD_REQUEST; + } diff --git a/SPECS/mod_auth_mellon.spec b/SPECS/mod_auth_mellon.spec index 1f5e40b..c9ab7bb 100644 --- a/SPECS/mod_auth_mellon.spec +++ b/SPECS/mod_auth_mellon.spec @@ -1,14 +1,16 @@ Summary: A SAML 2.0 authentication module for the Apache Httpd Server Name: mod_auth_mellon -Version: 0.11.0 -Release: 4%{?dist} +Version: 0.13.1 +Release: 1%{?dist} Group: System Environment/Daemons Source0: https://github.com/UNINETT/mod_auth_mellon/releases/download/v%{version}/%{name}-%{version}.tar.gz Source1: auth_mellon.conf Source2: 10-auth_mellon.conf Source3: mod_auth_mellon.conf Source4: mellon_create_metadata.sh +Source5: user_guide.tar.gz License: GPLv2+ + BuildRequires: curl-devel BuildRequires: glib2-devel BuildRequires: httpd-devel @@ -19,10 +21,12 @@ Requires: httpd-mmn = %{_httpd_mmn} Requires: lasso >= 2.5.0 Url: https://github.com/UNINETT/mod_auth_mellon -Patch1: lasso_provider_warning.patch -Patch2: enabled_in_check_uid.patch -Patch3: ecp_doc.patch -Patch4: content-type.patch +Patch1: log_typo.patch +Patch2: post_segfault.patch +Patch3: lasso_error_check.patch +Patch4: mellon_user_case_insensitive.patch +Patch5: log_no_idp.patch +Patch6: update_log_invalid_dst.patch %description The mod_auth_mellon module is an authentication service that implements the @@ -35,6 +39,8 @@ received in assertions generated by a IdP server. %patch2 -p1 %patch3 -p1 %patch4 -p1 +%patch5 -p1 +%patch6 -p1 %build export APXS=%{_httpd_apxs} @@ -60,6 +66,11 @@ mkdir -p %{buildroot}/run/%{name} mkdir -p %{buildroot}/%{_libexecdir}/%{name} install -m 755 %{SOURCE4} %{buildroot}/%{_libexecdir}/%{name} +# install user guide +mkdir -p %{buildroot}/%{_pkgdocdir} +tar -C %{buildroot}/%{_pkgdocdir} -xf %{SOURCE5} + + %files %defattr(-,root,root) %if 0%{?rhel} && 0%{?rhel} < 7 @@ -68,6 +79,7 @@ install -m 755 %{SOURCE4} %{buildroot}/%{_libexecdir}/%{name} %license COPYING %endif %doc README NEWS ECP.rst +%doc %{_pkgdocdir}/user_guide %config(noreplace) %{_httpd_modconfdir}/10-auth_mellon.conf %config(noreplace) %{_httpd_confdir}/auth_mellon.conf %{_httpd_moddir}/mod_auth_mellon.so @@ -76,6 +88,19 @@ install -m 755 %{SOURCE4} %{buildroot}/%{_libexecdir}/%{name} %dir /run/%{name}/ %changelog +* Fri Oct 20 2017 John Dennis - 0.13.1-1 +- Resolves: rhbz#1481332 Upgrade to current upstream 0.13.1 +- Adds the following upstream bug fixes on top of 0.13.1: + * ee97812 Add Mellon User Guide + * daa5d1e If no IdP's are defined explicitly log that fact + * c291232 Make MellonUser case-insensitive. + * 2c2e19d Fix incorrect error check for many `lasso_*`-functions. + * 5c5ed1d Fix segmentation fault with POST field without a value. + * 4c924d9 Fix some log message typos + * 93faba4 Update log msg for Invalid Destination and Invalid Audience to + show both the expected and received values. +- Add new mellon user guide to installed docdir + * Mon Jan 30 2017 John Dennis - 0.11.0-4 - Resolves: rhbz#1414021 - Incorrect Content-Type header in ECP PAOS Rebuilding due to missing comment in Changelog