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

Replace UnixEndPoint with UnixDomainSocketEndPoint #1160

Closed
mguinness opened this issue Apr 11, 2022 · 4 comments · Fixed by #1163
Closed

Replace UnixEndPoint with UnixDomainSocketEndPoint #1160

mguinness opened this issue Apr 11, 2022 · 4 comments · Fixed by #1163

Comments

@mguinness
Copy link
Contributor

mguinness commented Apr 11, 2022

While looking into https://stackoverflow.com/questions/71742985 I noticed that OpenUnixSocketAsync() uses the UnixEndPoint class that was added with PR #119 back in 2016.

private async Task<bool> OpenUnixSocketAsync(ConnectionSettings cs, IOBehavior ioBehavior, CancellationToken cancellationToken)
{
m_logArguments[1] = cs.UnixSocket;
Log.Trace("Session{0} connecting to UNIX Socket '{1}'", m_logArguments);
var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP);
var unixEp = new UnixEndPoint(cs.UnixSocket!);
try
{
using (cancellationToken.Register(() => socket.Dispose()))
{
try
{
if (ioBehavior == IOBehavior.Asynchronous)
{
await Task.Factory.FromAsync(socket.BeginConnect, socket.EndConnect, unixEp, null).ConfigureAwait(false);
}
else
{
socket.Connect(unixEp);
}
}
catch (ObjectDisposedException) when (cancellationToken.IsCancellationRequested)
{
Log.Info("Session{0} connect timeout expired connecting to UNIX Socket '{1}'", m_logArguments);
throw new MySqlException(MySqlErrorCode.UnableToConnectToHost, "Connect Timeout expired.");
}
}
}
catch (SocketException)
{
socket.Dispose();
}
if (socket.Connected)
{
m_socket = socket;
m_stream = new NetworkStream(socket);
m_activityTags.Add(ActivitySourceHelper.NetTransportTagName, ActivitySourceHelper.NetTransportUnixValue);
m_activityTags.Add(ActivitySourceHelper.NetPeerNameTagName, cs.UnixSocket);
lock (m_lock)
m_state = State.Connected;
return true;
}
return false;
}

Since .NET Standard 2.1 the UnixDomainSocketEndPoint class is available which should provide the same functionality as UnixEndPoint that was copied from Mono.

It probably doesn't offer any benefits other than code maintainability, but if the code implementing Unix Domain Sockets can easily switch to the new class that would be worthwhile. The Postgres driver also made this switch in npgsql/npgsql#3314,

The question as to why the uid option is needed in the connection string for the unix socket authentication plugin to work is another issue which I asked the OP to submit.

@bgrainger
Copy link
Member

The question as to why the uid option is needed in the connection string for the unix socket authentication plugin to work is another issue which I asked the OP to submit.

MySqlConnector always sends a handshake response packet (when connecting via any protocol, including Unix sockets), which contains a "username" field. In the SO poster's case, it will contain the empty string. The MariaDB documentation makes it sound as if the client doesn't need to provide a user name:

The unix_socket authentication plugin works by calling the getsockopt system call with the SO_PEERCRED socket option, which allows it to retrieve the uid of the process that is connected to the socket. It is then able to get the user name associated with that uid. Once it has the user name, it will authenticate the connecting user as the MariaDB account that has the same user name.

Maybe client libraries are supposed to implicitly set the user name to whoami when connecting via Unix sockets, and this is just undocumented expected behaviour?

@mguinness
Copy link
Contributor Author

mguinness commented Apr 12, 2022

That's really not clear to me either, some examples show the command line client with the --user option and others don't.

The MySQL plugin documentation shows how to map a DB user to a different OS user which necessitates providing the user.

Maybe the answer is when connection protocol is set to unix and user is empty then just replace it with Environment.UserName?

Would you be able to do a packet capture on mysql client without user to see what is sent in the handshake response packet?

@bgrainger
Copy link
Member

bgrainger commented Apr 12, 2022

https://dev.mysql.com/doc/refman/8.0/en/user-names.html

On Unix, most MySQL clients by default try to log in using the current Unix user name as the MySQL user name, but that is for convenience only.

https://dev.mysql.com/doc/c-api/8.0/en/mysql-real-connect.html

The user argument contains the user's MySQL login ID. If user is NULL or the empty string "", the current user is assumed. Under Unix, this is the current login name.

Sounds like the official mysql client (and probably any others that use the mysql_real_connect function in their implementation) would default to Environment.UserName if not specified.

Maybe the answer is when connection protocol is set to unix and user is empty then just replace it with Environment.UserName?

I filed a suggestion for this improvement: #1161.

bgrainger added a commit to bgrainger/MySqlConnector that referenced this issue Apr 23, 2022
Signed-off-by: Bradley Grainger <bgrainger@gmail.com>
bgrainger added a commit to bgrainger/MySqlConnector that referenced this issue Apr 23, 2022
Signed-off-by: Bradley Grainger <bgrainger@gmail.com>
@bgrainger
Copy link
Member

Implemented in 2.1.9.

okramarenko added a commit to memsql/SingleStoreNETConnector that referenced this issue Mar 30, 2023
Summary:
This diff grabs changes from original connector that were made in 2.1.9 release:
- Use UnixDomainSocketEndPoint. Fixes mysql-net#1160
- Add SingleStoreSslMode.Disabled. Fixes mysql-net#1168
- Implement SingleStoreAttribute.Clone. Fixes mysql-net#1169
- Update activity status on failure SingleStoreDataReader
- Use net7.0 (update .csproj files and CI config.yml)
- Use new C# 11 features (e.g. string literals, list patterns, Regex generator)
- Updating different packages

Test Plan: https://app.circleci.com/pipelines/github/memsql/SingleStoreNETConnector/255/workflows/5ffa09c8-5b07-4c58-81b9-68e98d9c3557

Reviewers: pmishchenko-ua

Subscribers: engineering-list

JIRA Issues: PLAT-6408

Differential Revision: https://grizzly.internal.memcompute.com/D61770
okramarenko added a commit to memsql/SingleStoreNETConnector that referenced this issue Mar 31, 2023
Summary:
This diff grabs changes from original connector that were made in 2.1.9 release:
- Use UnixDomainSocketEndPoint. Fixes mysql-net#1160
- Add SingleStoreSslMode.Disabled. Fixes mysql-net#1168
- Implement SingleStoreAttribute.Clone. Fixes mysql-net#1169
- Update activity status on failure SingleStoreDataReader
- Use net7.0 (update .csproj files and CI config.yml)
- Use new C# 11 features (e.g. string literals, list patterns, Regex generator)
- Updating different packages

Test Plan: https://app.circleci.com/pipelines/github/memsql/SingleStoreNETConnector/255/workflows/5ffa09c8-5b07-4c58-81b9-68e98d9c3557

Reviewers: pmishchenko-ua

Reviewed By: pmishchenko-ua

Subscribers: engineering-list

JIRA Issues: PLAT-6408

Differential Revision: https://grizzly.internal.memcompute.com/D61770
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
2 participants