Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MDEV-30178] Explicit errors on required secured transport #2581

Merged
merged 2 commits into from
Jul 25, 2023

Conversation

Chupsy
Copy link

@Chupsy Chupsy commented Mar 28, 2023

  • The Jira issue number for this PR is: MDEV-30178

Description

The error message for user connections using insecure transport when connection requires a secured transport.

To make the error message more relevant, introduce a new error 'ER_SECURE_TRANSPORT_REQUIRED', copy of MySQL error message with the error code 08004 (SQL-server rejected establishment SQL-connection).

Before: ER_ACCESS_DENIED "Access denied for user '%s'@'%s'"

Now: ER_ACCESS_SSL_REQUIRED "Connections using insecure transport are prohibited while --require_secure_transport=ON."

Also move the code of 'require_secure_transport' to be executed before
authentication verification, as it's not part of authentication but
rather verifying if connection should be allowed in the first place.

How can this PR be tested?

Modified the existing test for require_secure_transport to expect the new error.

Basing the PR against the correct MariaDB version

  • This is a new feature and the PR is based against the latest MariaDB development branch

Backward compatibility

This PR adds a new error message, this should be fully backward compatible.

PR quality check

Copyright

All new code of the whole pull request, including one or several files that
are either new files or modified ones, are contributed under the BSD-new license.
I am contributing on behalf of my employer Amazon Web Services, Inc.

@CLAassistant
Copy link

CLAassistant commented Mar 28, 2023

CLA assistant check
All committers have signed the CLA.

Copy link
Member

@grooverdan grooverdan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice to see this bug being addressed. Thank you.

note the other test failures in BB (perfschema.hostcache_ipv6_ssl perfschema.hostcache_ipv4_ssl), check if they are returning the right error code and adjust accordingly.

@vuvova as the error code is the same can this be a 10.5 fix? or did you want the MySQL error code 3159? Did you want to do a final review?

sql/sql_acl.cc Outdated Show resolved Hide resolved
sql/sql_acl.cc Outdated Show resolved Hide resolved
sql/sql_acl.cc Outdated Show resolved Hide resolved
sql/sql_acl.cc Outdated Show resolved Hide resolved
@grooverdan grooverdan added license-bsd-new Contributed under BSD-new license need feedback Can the contributor please address the questions asked. labels Mar 29, 2023
@Chupsy Chupsy requested a review from grooverdan March 29, 2023 20:59
Copy link
Member

@grooverdan grooverdan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks

@grooverdan grooverdan removed the need feedback Can the contributor please address the questions asked. label Mar 29, 2023
@Chupsy
Copy link
Author

Chupsy commented Mar 30, 2023

Thank you for your review! I see that buildbot is failing at 2 places, is that "expected"? When checking, it does not seem to be due to my changes

@grooverdan
Copy link
Member

Thank you for your review! I see that buildbot is failing at 2 places, is that "expected"? When checking, it does not seem to be due to my changes

Yes. Both seem unrelated to your change and have occurred before.

Copy link
Member

@vuvova vuvova left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is a good approach in general. I'd think a user-independent check for opt_require_secure_transport should be done rather early, almost immediately after the connection is established. And it'll fail with ER_ACCESS_SSL_REQUIRED. It's not part of the authentication, it checks whether the connection itself can be allowed to exist.

While acl_check_ssl() checks user specific SSL requirements, is done after the password is verified and returns ER_ACCESS_DENIED, as it's part of the authentication.

Also, as it's the error message that MySQL has, can it have the same text and the same error number as in MySQL? For compatibility reasons.

@@ -10780,3 +10780,5 @@ ER_CM_OPTION_MISSING_REQUIREMENT
eng "CHANGE MASTER TO option '%s=%s' is missing requirement %s"
ER_SLAVE_STATEMENT_TIMEOUT 70100
eng "Slave log event execution was interrupted (slave_max_statement_time exceeded)"
ER_ACCESS_SSL_REQUIRED 28000
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SQLSTATE 08004 is more appropriate here.

28000 is invalid authorization specification like ER_ACCESS_DENIED_ERROR
08004 is SQL-server rejected establishment SQL-connection like ER_NOT_SUPPORTED_AUTH_MODE

@Chupsy
Copy link
Author

Chupsy commented Mar 31, 2023

Thank you for your review @vuvova

I understand that we should follow errors from MySQL, here is the original error

Mysql error:SQLSTATE[HY000] [3159] Connections using insecure transport are prohibited while --require_secure_transport=ON

This is a bit different from what is proposed in this CR, the error would only concern this small part

    if (opt_require_secure_transport)
    {
      enum enum_vio_type type= vio_type(vio);

      bool has_secured_transport =
      #ifdef HAVE_OPENSSL
        (type == VIO_TYPE_SSL) ||
      #endif
      #ifdef _WIN32
        (type == VIO_TYPE_NAMEDPIPE);
      #else
        (type == VIO_TYPE_SOCKET);
      #endif

      if(!has_secured_transport){
        return ER_ACCESS_SSL_REQUIRED;
      }
    }

Other errors due to user specific SSL requirements will still return ER_ACCESS_DENIED

We can move this part to check it earlier in the function, before the check of the password?

@Chupsy
Copy link
Author

Chupsy commented Apr 3, 2023

Here are the changes I added:

  • reverted the changes that were no longer useful for custom errors in sql_acl
  • Moved the code to check require_secure_transport in sql_connect as part of the connection verification as discussed in comments earlier
  • Changed the error message and error id (ER_SECURE_TRANSPORT_REQUIRED) to match MySQL
  • Used 08004 as error code as proposed in previous comment

@Chupsy Chupsy changed the title [MDEV-30178] Explicit errors on ssl transport auth [MDEV-30178] Explicit errors on required secured transport Apr 3, 2023
@Chupsy Chupsy force-pushed the 11.0 branch 6 times, most recently from ac813a5 to 3bc8def Compare April 5, 2023 20:46
@Chupsy
Copy link
Author

Chupsy commented Apr 11, 2023

For some reason, amd64-ubuntu-2204-msan is failing on tests unrelated to my changes...

    innodb.undo_truncate
    mariabackup.incremental_page_compressed
    innodb.innodb_page_compressed
    innodb.innodb_page_compressed
    innodb.innodb_page_compressed
    innodb.innodb_page_compressed
    innodb.innodb_page_compressed
    innodb_zip.create_options innodb_zip.recover innodb_zip.innodb-zip innodb_zip.bug56680

I'm not sure why these come up

@Chupsy
Copy link
Author

Chupsy commented Apr 29, 2023

@vuvova the CI is green, feel free to review at any time

@Chupsy
Copy link
Author

Chupsy commented May 1, 2023

The only CI failing is due to a test losing connection, I see that all PRs have the same issue, with a different test

@dlenski
Copy link
Contributor

dlenski commented May 3, 2023

@LinuxJedi, @vuvova, could you please take another look at this?

(And perhaps re-start the amd64-ubuntu-2204-msan CI job which appears to be failing in a way that's unrelated to this PR.)

@Chupsy Chupsy requested a review from LinuxJedi May 23, 2023 19:18
@LinuxJedi
Copy link
Contributor

Agreed, this is likely unrelated. I'll look into it.

Copy link
Contributor

@LinuxJedi LinuxJedi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more style issues to fixup. Looking good though :)

sql/sql_connect.cc Outdated Show resolved Hide resolved
sql/sql_connect.cc Outdated Show resolved Hide resolved
sql/sql_acl.cc Outdated Show resolved Hide resolved
@Chupsy Chupsy force-pushed the 11.0 branch 2 times, most recently from 6b56768 to 669fc7c Compare June 5, 2023 21:36
@Chupsy Chupsy requested review from LinuxJedi and dlenski June 5, 2023 23:51
@Chupsy
Copy link
Author

Chupsy commented Jun 5, 2023

I fixed the minor issues (and apparently the CI is working now)

@@ -10780,3 +10780,5 @@ ER_CM_OPTION_MISSING_REQUIREMENT
eng "CHANGE MASTER TO option '%s=%s' is missing requirement %s"
ER_SLAVE_STATEMENT_TIMEOUT 70100
eng "Slave log event execution was interrupted (slave_max_statement_time exceeded)"
ER_SECURE_TRANSPORT_REQUIRED 08004
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's try to have it the same number as in MySQL, if possible

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switched to 3159 as it is the error number on MySQL

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did you do it? I don't see how it was done :(

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it defined only through sql/share/errmsg-utf8.txt ? If so, I modified the error number to match the new number

(type != VIO_TYPE_NAMEDPIPE);
#else
(type != VIO_TYPE_SOCKET);
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you need all these #ifdef's ? they make the code difficult to read. Values are defined unconditionally, so it seems that you can remove ifdefs and the code will still compile file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those #ifdefs predate this PR, as you can see from the diff of sql_acl.cc above. @Chupsy has simplified them considerably here.

Values are defined unconditionally, …

Right. https://github.com/MariaDB/server/blob/HEAD/include/violite.h#L38-L45

… so it seems that you can remove ifdefs and the code will still compile file.

There are a fairly enormous number of other places in the code which are wrapped in unnecessary #ifdef HAVE_OPENSSL, in that case 😅

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not totally certain on how #ifdef work so I just optimized them with @dlenski, not sure what would happen if we removed them. Tell me if you want me to remove them completely from the code

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on what @vuvova said and what I see in the code, it seems like you could simply change this section as follows…

    return
      (type != VIO_TYPE_SSL) &&
      (type != VIO_TYPE_NAMEDPIPE) &&
      (type != VIO_TYPE_SOCKET);

… and it should still compile and work correctly on all platforms, even if MariaDB is (somehow) built without TLS support, and even though named pipes are only used on Windows builds, and Unix sockets are only used on POSIX builds.

sql/sql_connect.cc Show resolved Hide resolved
@Chupsy Chupsy force-pushed the 11.0 branch 2 times, most recently from c9581e1 to 98e97d4 Compare June 12, 2023 16:47
@Chupsy Chupsy requested a review from vuvova June 12, 2023 16:50
@Chupsy Chupsy force-pushed the 11.0 branch 2 times, most recently from b04861c to afc3bea Compare June 16, 2023 14:57
Comment on lines 838 to 842
(type != VIO_TYPE_NAMEDPIPE);
(type != VIO_TYPE_SOCKET);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Chupsy, these should be separated by ; rather than &&… probably should be caught by a compiler warning.

@@ -10780,3 +10780,5 @@ ER_CM_OPTION_MISSING_REQUIREMENT
eng "CHANGE MASTER TO option '%s=%s' is missing requirement %s"
ER_SLAVE_STATEMENT_TIMEOUT 70100
eng "Slave log event execution was interrupted (slave_max_statement_time exceeded)"
ER_SECURE_TRANSPORT_REQUIRED 3159
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eh, no. you didn't change the error number, you've made sqlstate to be 3159, which isn't even a valid sqlstate value.

you can see error numbers in the include/mysqld_error.h file, they're generated, error messages are simply numbered sequentially.

you can see that the last MySQL error in errmsg-utf8.txt is currently ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS, number 3060. So if you want to add a new one with the number 3159, you need to add ~100 new error messages. Like this

         eng "Do not support online operation on table with GIS index"
         spa "No soporta operación en línea en tabla con índice GIS"
+
+ER_MYSQL_3061
+        eng ""
+ER_MYSQL_3062
+        eng ""
... and so on ...
+ER_MYSQL_3157
+        eng ""
+ER_MYSQL_3158
+        eng ""
+
+ER_SECURE_TRANSPORT_REQUIRED 08004
+        eng "Connections using insecure transport are prohibited while --requi>
+

Copy link
Contributor

@dlenski dlenski Jun 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's try to have it the same number as in MySQL, if possible

I completely understand the goal here, but how is this going to be possible in the long run, without some explicit coordination?

If the wire protocol associates error codes with specific meanings purely based on their numeric codes, which are sequentially increasing numbers assigned by two diverging codebases (MySQL and MariaDB), then there's inevitably going to be a point where MySQL and MariaDB assign different meanings to the same code, right?

(Maybe it has happened already 🤷‍♂️)

So if you want to add a new one with the number 3159, you need to add ~100 new error messages.

Couldn't we simply skip to a new position using start-error-number, as done at several other points in the file? E.g.

 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS
         chi "不要支持使用GIS索引的表中的在线操作"
         eng "Do not support online operation on table with GIS index"
         spa "No soporta operación en línea en tabla con índice GIS"
+
+ start-error-number 3159
+ ER_SECURE_TRANSPORT_REQUIRED 08004
+       eng "Connections using insecure transport are prohibited while --require_secure_transport=ON."

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Ranges are different. 1000-1999 is the historical range for MySQL/MariaDB common errors, 2000-2999 is for client-side errors from Connector/C, 3000-3999 is the new MySQL error range, 4000-4999 is the new MariaDB error range.
  2. no we cannot, I even tried that before writing a previous comment. it is assumed that ranges are all 1000 messages wide, see how ER() macro is defined:
#define ERRORS_PER_RANGE 1000

#define ER_THD(thd,X) ((thd)->variables.errmsgs[((X)-ER_ERROR_FIRST) / ERRORS_PER_RANGE][(X) % ERRORS_PER_RANGE])
#define ER(X)         ER_THD(current_thd, (X))

@Chupsy
Copy link
Author

Chupsy commented Jul 10, 2023

I fixed the error number and the error that @dlenski found, should be good to go now :)

Copy link
Member

@vuvova vuvova left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, thanks @Chupsy !

@Chupsy
Copy link
Author

Chupsy commented Jul 21, 2023

Thanks @vuvova !
@LinuxJedi anything else needed ? Can we merge the PR?

@LinuxJedi
Copy link
Contributor

Thanks @vuvova ! @LinuxJedi anything else needed ? Can we merge the PR?

Can you please rebase against 11.2? Then I think we are good :)

The error message for user connections using insecure transport when secured transport is required is very uninformative and doesn't mention the requirement of secure
transport at all.

To make the error message more relevant, introduce a new error
'ER_SECURE_TRANSPORT_REQUIRED', copy of MySQL error message with the
error code 08004 (SQL-server rejected establishment SQL-connection).

Move the code of 'require_secure_transport' to be executed before
authentication verification, as it's not part of authentication but
rather verifying if connection should be allowed in the first place.

All new code of the whole pull request, including one or several files that
are either new files or modified ones, are contributed under the BSD-new license.
I am contributing on behalf of my employer Amazon Web Services, Inc.
@LinuxJedi LinuxJedi merged commit 742f960 into MariaDB:11.2 Jul 25, 2023
12 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
license-bsd-new Contributed under BSD-new license
6 participants