[MDEV-4691] Kerberize MariaDB -- add Kerberos authentication support to MariaDB Created: 2013-06-21  Updated: 2016-03-01  Resolved: 2016-01-20

Status: Closed
Project: MariaDB Server
Component/s: Plugins
Fix Version/s: 10.1.10

Type: Task Priority: Critical
Reporter: QIU Shuang Assignee: Vladislav Vaintroub
Resolution: Fixed Votes: 6
Labels: gsoc13

Issue Links:
Relates
relates to MDEV-6385 MariaDB Galera Authentication between... Closed
relates to MDEV-6387 MariaDB LDAP integration Open
Sprint: 10.2.0-1, 10.1.10, 10.2.0-2

 Description   

This task identifies TODOs to add Kerberos authentication support to MariaDB.

Kerberos is a standardised network authentication protocol providing mutual authentication of potential users and network service. Many commercial relational database management systems have already internalized support for Kerberos authentication. The goal of this project aims to adding cross-platform Kerberos authentication support to MariaDB database.

User Scenario

In this section, we give a normal use case.
Suppose user Adam what to authentication against his Kerberos principal.

Step 1 Create a login user in MariaDB and specify the kerberos as server side authentication plugin.

CREATE USER 'adam' IDENTIFIED VIA kerberos AS 'adam/mariadb@lp';

The gap between MariaDB username length and Kerberos principal name length make it error-prone to embedded a whole principal name into a MariaDB login name. We use a short name as MariaDB login name and identify the principal name with the AS clause. If the AS clause is absent when creating a user, the MariaDB login name is used as principal name implicitly.
Step 2 At client side, Adam acquires a service ticket (or access token) to MariaDB.
Step 3 Adam tries to login with short login name.

$ mysql -u adam

Step 4 If adam/mariadb@lp is a valid principal in Kerberos and the service ticket is not expired, Adam can login MariaDB passwordlessly; otherwise, he will receive an actionable error message.

The Source Code

Source codes will be located in the plugin/auth_kerberos directory.
mysql_declar_plugin/mysql_declare_plugin_end macros can be used to define server side plugin and mysql_declare_client_plugin/mysql_end_client_plugin macros for client side.

Client-Server Communication

This section defines the message exchanges between client and server during Kerberos authentication.

Step 1 Server sends the null-terminated SPN to the client (the SPN is given as server parameter, documented in yet another section).
Step 2 Client receives SPN from server with vio->read_packet, creates a secure context with the SPN by gss_init_sec_context repeating until done.
Step 3 Client writes the output token created by gss_init_sec_context to the server, using vio->write_packet.
Step 4 Server acquire credential with gss_acquire_cred to get the initial server credential.
Step 5 Server reads token created at step 3, checks the principal name enclosed in the token with its credential get in step 4 and accepts the access requests if recognizable otherwise fails the connection.

Figure-out SPN

This section describes the policy to identify a valid service principal name.

For the server side plugin, an SPN is requried. The principal name is an option in configuration file (e.g. ~/.my.cfn) with

spn=primary/instance@realm

or

spn=primary@machine.domain

depending on its platform, where primary is the service name. If this option does not present, mysql is the default SPN.

Cross-platform Requirements

GSSAPI based Kerberos authentication is widely used in *nix world, while Windows also provides an SSPI based Kerberos authentication process. The plugin will support Windows-SSPI in addition to GSSAPi to maximize the compatibility.

Links

  1. Configure Kerberos authentication in Oracle RDBMS. http://docs.oracle.com/cd/A97630_01/network.920/a96573/asokerb.htm
  2. Using Kerberos authentication with SQL Server. http://msdn.microsoft.com/en-us/library/cc280745(v=sql.105).aspx
  3. Configuring Kerberos for Sybase. http://www.sybase.com.hk/content/1029260/1029260.pdf
  4. The Kerberos network authentication service (v5). http://tools.ietf.org/html/rfc4120
  5. GSS-API C-binding. http://tools.ietf.org/html/rfc2744
  6. The Kerberos version 5 Generic Security Service Application Program Interface (GSS-API) mechanism: Version 2. http://tools.ietf.org/html/rfc4121
  7. MariaDB Pluggable Authentication. https://kb.askmonty.org/en/development-pluggable-authentication/
  8. How the Kerberos Version 5 Authentication Protocol Works. http://technet.microsoft.com/en-us/library/cc772815(v=ws.10).aspx
  9. SSPI/Kerberos Interoperability with GSSAPI. http://msdn.microsoft.com/en-us/library/ms995352.aspx
  10. Best Practices for Integrating Kerberos into Your Application. http://www.kerberos.org/software/appskerberos.pdf


 Comments   
Comment by David McLennan (Inactive) [ 2014-02-20 ]

Would like to add support for this capability and for default plugins to be shipped with the server and client distributions. We also need to consider JDBC, ODBC and .Net driver capabilities.

Comment by QIU Shuang [ 2014-02-21 ]

@DavidMcLennan My initial release of the plugin could be found at https://code.launchpad.net/~qiush-summer/maria/krb_auth_plugin, and Vlad also gave a JDBC implementation http://bazaar.launchpad.net/~wlad-montyprogram/+junk/mariadb-java-client/revision/470. Unfortunately, we didn't consider the ODBC and .Net driver correspondents then. See anything else I can help.

Comment by Daniel Black [ 2015-08-27 ]

Nice work qiushuang,

In CONJ-164 I've added a bit of a plugin framework. Should be easy enough to adapt the JDBC work there too. Vlad's client implementation seems compatible with http://docs.oracle.com/javase/6/docs/technotes/guides/security/jgss/lab/part5.html#SPNEGO (when SPNEGO_OID is used instead of KERBEROS_OID).

How hard would it be to wrap the server side in SPNEGO to be compatible with https://dev.mysql.com/doc/internals/en/spnego.html ?

elenst can you add a patch label here?

Comment by Vladislav Vaintroub [ 2015-08-27 ]

This can be easily modified to support Oracle/MySQL's Windows authentication. Easily however on Windows only (since choice Kerberos vs Negotiate is defined by single parameter in SSPI), no idea what effort would be to support it Unix server and C-client side.

But, if compatibility with Oracle/MySQL is desired, SPNEGO plugin also should be called differently. Neither "kerberos_client" , nor SPNEGO, but "authentication_windows_client" which is the name of Oracle/MySQL plugin ( they also only implement the server and C client on Window only)

Comment by Vladislav Vaintroub [ 2015-08-27 ]

@danblack : Also, there are some scary details in MySQL/Oracle windows authentication implementation for which I miss explanation, other than "it is a historical bug, but we document it here". Those should not be replicated QIUs kerberos plugin, I guess

https://dev.mysql.com/doc/internals/en/windows-native-authentication.html . has this or example:

Due to implementation details (again) the first packet sent from the client to the server is expected to be either

  • 254 bytes long max or
  • send the first 254 bytes first, appended by 1 byte with a magic value plus a 2nd packet with rest of the data
Comment by Daniel Black [ 2015-08-27 ]

yeh, saw those odd document bits. Different plugin structure on the server side corresponding to a different name. Thanks for the info.

Comment by Robbie Harwood [ 2015-08-28 ]

Hello! I have modified this code to support encryption as well, and opened https://github.com/MariaDB/server/pull/95 for it.

Comment by Vladislav Vaintroub [ 2015-08-29 ]

Robbie Harwood, nice work. But .. is there a very strong reason for Kerberos encryption, provided that server and most of the client libraries (including those written natively in Java, .NET, Python, Ruby etc) already support good encryption via SSL?
Also when using Kerberos, people would likely (more often than not) want to just to authenticate for say SSO purposes not to encrypt, as encryption is a big CPU hog.

Comment by Robbie Harwood [ 2015-09-03 ]

If one uses Kerberos for authentication, there is no additional sysadmin effort to use it for encryption. Kerberos does not need certificate management the way a TLS setup does.

Personally I doubt that the overhead of encryption is noticeable in the vast majority of cases, but if there is going to be a demand for authentication without encryption (which provides zero connection security on the wire since traffic it is not encrypted, which is why I don't understand the use case) then I can try to meet this demand. I think that having this option invites sysadmins to inadvertently negate their security guarantees.

There's also a limit we are quickly approaching with the current plugin architecture to keep in mind - Kerberos authentication+encryption are best done as a plugin, but at the moment encryption plugins cannot be created. This is changing, but the changes are not yet on the horizon is my understanding, and there is demand for Kerberos right now (there was even a GSOC for supporting it!). I have been performing a similar task for postgres, where they for some time have had authentication without encryption; there is no pleasant way to add encryption later.

Comment by Vladislav Vaintroub [ 2015-09-03 ]

The authentication is related yet separate thing from encryption. The use case I had in mind was single sign on, where user does not have to type his password once more after OS/kerberos login. I do not know how much it improves security (certainly it does not on the wire), but it increases convenience considerably and removes the need of having yet one more password, just for accessing database.

Apart from that, as mentioned, there are different clients apart from C client, that on different reasons cannot use C client. There adding additional authentication is trivial, but they require a lot of work in case you tie it together with encryption. You can investigate what it means to add kerberos encryption support to Maria JDBC, while auth only required maybe 20 lines of code

So rather than rendering kerberos support useless outside of C client world, I believe it is a better idea to just support authentication at current moment, and discuss the architecture of pluggable encryption on the mailing list or so. Pluggable encryption certainly has its merit. But, as you say, in this case is mostly convenience (no need to self-sign SSL certificates)

Comment by Vladislav Vaintroub [ 2015-09-03 ]

Apparently , there seems to be support for kerberos in SSL http://www.ietf.org/rfc/rfc2712.txt. ?I understand no certificates are necessary on either side, and the client (and server) identity could be extracted. Perhaps this can be investigated further, this could provide both encryption via SSL, authentication via Kerberos , without certificates, and without need to support more encryption in client libraries.

Comment by Robbie Harwood [ 2015-09-15 ]

I do not believe 2712 is a realistic option or that it is currently supported in TLS.

If JDBC is going to be required for this to merge, can you point me to that codebase?

Comment by Vladislav Vaintroub [ 2015-09-15 ]

JDBC driver is located here https://github.com/MariaDB/mariadb-connector-j

I have no authority about what is going to be required for merge (I am currently not even a member of MariaDB team). I think bigger changes and ideas like yours should be discussed on the mailing list rather than in a bug database.

So far I explained, why I think bundling Kerberos authentication with encryption would make it less valuable. If this RFC2712 is bad or outdated, even then other changes that would make using SSL easier, like for example creating self-signed server certificate on the fly during server start, should solve the remaining concerns about encryption. I doubted there is a significant need of yet another encryption, but this is just my own opinion, based on some previous work on MySQL connectors. Neither Java nor NET (and I guess not many other languages) would offer a "Kerberos stream", yet SSL support is pretty good everywhere.

Comment by Robbie Harwood [ 2015-09-16 ]

If you'd like, I can propose a change on the mailing list, though there was discussion of them on the IRC channel beforehand. Mostly, it takes me by surprise that anyone is opposed to these changes; they seem the natural addon to the GSOC work.

I am not sure what you mean by "Kerberos stream".

Comment by Vladislav Vaintroub [ 2015-09-16 ]

Java, as well as .NET and probably more languages and runtimes have notion of stream. Java and NET have transparent support for SSL , you read and write bytes without wrapping, in Java using SSLSocket.getInputStream() or SSLSocket.getOutputStream() . In .NET, there is SSLStream that wraps an unencrypted Stream. They are both used to implement SSL support for MySQL.

There is no analog for that stuff for Kerberos encryption, i.e no support out of the box. I do not know why nobody opposed there changes on IRC, but mostly likely the reason would be that people you spoke to never worked on drivers (Connectors in MySQL speak), other than C-based ones (which is, C API and ODBC). But I worked on them

Comment by Robbie Harwood [ 2015-09-16 ]

That's true, however: creating such an interface is not difficult (done it before; will probably do it again), and I would imagine it's what these "stream" interfaces are doing under the hood anyway. The GSSAPI interface is just set up to work with an existing flow control layer.

Comment by Vladislav Vaintroub [ 2015-09-16 ]

There is no GSSAPI for some of the environments we talk about.

Comment by Robbie Harwood [ 2015-09-16 ]

In those environments, one wouldn't be able to use GSSAPI authentication either, no?

Comment by Vladislav Vaintroub [ 2015-09-16 ]

No GSSAPI, but SSPI would do in some environments . Also in .NET for example, which does not support either SSPI nor GSSAPI natively, the closest things would be to reuse NegotateStream, which wraps SPNEGO packets .Which makes me think that (optionally?) supporting SPNEGO OID would be good in this patch (also because of the other reasons , it would allow Windows auth outside of domain)

Comment by Robbie Harwood [ 2015-09-16 ]

Well, if we're talking Windows, GSSAPI is available there (MIT Kerberos for Windows, or alternately a shim library over SSPI exists). QIU Shuang's original patch had SSPI support which I assume works; however, I can't test or code against that.

Comment by Vladislav Vaintroub [ 2015-09-16 ]

His code works fine,I tested it, and can code against that. I actually asked QIU to use SSPI, when I was mentoring his GSoc project, avoiding external dependencies is good , MariaDB/MySQL does not have any experience with shipping 3rd party dlls, the documentation MIT Kerberos on Windows is sparse, there is no 64 bit installer, the quality of them is unknown. His code does not have encryption, though it is possible with SSPI .
Nobody expects you to code on Windows. People just need to be aware that their patches won't always be taken "as-is", and could be heavily modified to be shippable.

Anyways, there is still a general question
1. Is TLS encryption with self-signed server certificate any worse than kerberos encryption? I know I bothered you with this one before, but have not got a "yes","no" or even "maybe" answer

Imagine for a second, TLS is super easy to use, and installer always creates some kind of self-signed certificate, and the server always starts with TLS support (I think I read that MySQL 5.7 installer does that)
Authentication kerberos and encryption(optionally) TLS, would satisfy the needs? What are the drawbacks in this scenario? the obvious benefits are less lines of code required to support GSSAPI encryption for all imaginable client libraries and also for the server. Also plugin can stay plugin,which is good.

2. Is SPNEGO support good in MIT Kerberos, if you are familiar with that? The examples are sparse on the internet? I thought perhaps it would be a good idea to make "GSSAPI" plugin, rather than Kerberos, with configurable OID, which is mostly useful for Windows (but also .NET / Mono, where SPNEGO protocol is supported but plain Kerberos not well)

Comment by Robbie Harwood [ 2015-09-18 ]

From a historical perspective, Kerberos has a better track record with regards to security than SSL/TLS. It's hard to use this figure for much, though, because the presence or lack thereof of known-and-resolved vulnerabilities doesn't indicate much about future vulnerability discoveries. GSSAPI has had a core API (with I believe one exception, all that I'm calling here is core) and wire protocol that was defined in 1997 and has not changed since (rfc 2078) except for a slight update in 2000 (rfc 2743 + 2744). By contrast, every version of TLS from SSL 1.0 through TLS 1.2 is either entirely insecure or requires deviation from the specification (client mitigations, disabling broken ciphers, etc.).

A self-signed certificate requires propagation of either the cert or the CA cert to each client that wishes to connect; if this is not performed, then the encryption is worth very little since an adversary can man-in-the-middle the connection without the client noticing. This is not true of Kerberos encryption. If there is a significant use case for GSSAPI authentication with TLS encryption, I'm willing to discuss adding support for operation in this mode, but I really do think GSSAPI encryption is strongly desirable as a feature (especially since it's not going to break anything else).

The plugin provided does not make any Kerberos calls; all are done through the GSSAPI, though I have not tested it with SPNEGO. (This is also true of the original GSOC code, excluding the SSPI portions.)

Comment by Vladislav Vaintroub [ 2015-12-25 ]

Serg, could you please review the corresponding commit
https://github.com/MariaDB/server/commit/e6898d1044a435e3dfd37e5c73cf4b75af5dcade

Comment by Henning Kropp [ 2016-02-29 ]

Hi, thank you for the patch. Could you please provide more details about how to configure the client correctly. For example where do I configure the SPN and the auth mech?

Comment by Robbie Harwood [ 2016-03-01 ]

SPN is configured in the [server] section of /etc/my.cnf.d/server.cnf (or similar) as kerberos_principal_name. Mechanism is configured through the GSSAPI layer; typically it will be Kerberos5 and SPNEGO, though this may vary with your system.

Comment by Vladislav Vaintroub [ 2016-03-01 ]

There is a documentation for the plugin,
https://mariadb.com/kb/en/mariadb/gssapi-authentication-plugin/

with example of how to create service principal on Unix (on Windows, with active directory, the principal name could be determined by the plugin startup code, so it is a lesser concern)

Comment by Henning Kropp [ 2016-03-01 ]

Sorry, but this all is not very clear for me. I was able to follow the doc to created a GSSAPI user. But running mysql --plugin-dir=/usr/lib64/mysql/plugin/ -u maria-user is not working for me.

From my understanding the client would need to be configured to use GSSAPI as well. And typically it needs the SPN name, so it knows the service to authenticate against.

https://mariadb.com/kb/en/mariadb/gssapi-authentication-plugin/ is really thin concerning the client config. There is a list of properties, but where do I place them? Also the client certainly does not need the keytab of the server, but the docu tells you so. Could you please review?

Comment by Henning Kropp [ 2016-03-01 ]

Oh, I realized this might just be a formatting issue :/ ... I read the bullet points as being related to the client properties, but they are not, right? Sorry for the confusion....

Found my mistake, docu is also fine (except confusing formatting). Sorry for bothering you here.

Comment by Vladislav Vaintroub [ 2016-03-01 ]

The only thing client has to do is to login as GSSAPI user (e.g kinit, or Windows domain login), and point to the plugin-dir (sometimes default plugin dir works, but often it does not ). client does not have any additional configuration, current plugin API does not allow it.

As for formatting, I do not see it as confusing, but maybe I miss something. I believe everyone can modify it, it is just a wiki, so you're welcome!

Generated at Thu Feb 08 06:58:24 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.