diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cb86cee..6a984d32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 2.4.3 +- Support for clear text passwords using a boolean parameter in connection as 'allowClearTextPassword' to activate / deactivate the feature. [#20](https://github.com/isoos/postgresql-dart/pull/20). + ## 2.4.2 - Include original stacktrace when query fails. diff --git a/lib/src/auth/auth.dart b/lib/src/auth/auth.dart index 99e61161..1c487a1f 100644 --- a/lib/src/auth/auth.dart +++ b/lib/src/auth/auth.dart @@ -3,10 +3,11 @@ import 'package:sasl_scram/sasl_scram.dart'; import '../../postgres.dart'; import '../server_messages.dart'; +import 'clear_text_authenticator.dart'; import 'md5_authenticator.dart'; import 'sasl_authenticator.dart'; -enum AuthenticationScheme { MD5, SCRAM_SHA_256 } +enum AuthenticationScheme { MD5, SCRAM_SHA_256, CLEAR } abstract class PostgresAuthenticator { static String? name; @@ -27,6 +28,8 @@ PostgresAuthenticator createAuthenticator(PostgreSQLConnection connection, username: connection.username, password: connection.password); return PostgresSaslAuthenticator( connection, ScramAuthenticator('SCRAM-SHA-256', sha256, credentials)); + case AuthenticationScheme.CLEAR: + return ClearAuthenticator(connection); default: throw PostgreSQLException("Authenticator wasn't specified"); } diff --git a/lib/src/auth/clear_text_authenticator.dart b/lib/src/auth/clear_text_authenticator.dart new file mode 100644 index 00000000..b954a0ee --- /dev/null +++ b/lib/src/auth/clear_text_authenticator.dart @@ -0,0 +1,33 @@ +import 'package:buffer/buffer.dart'; + +import '../../postgres.dart'; +import '../client_messages.dart'; +import '../server_messages.dart'; +import '../utf8_backed_string.dart'; +import 'auth.dart'; + +class ClearAuthenticator extends PostgresAuthenticator { + ClearAuthenticator(PostgreSQLConnection connection) : super(connection); + + @override + void onMessage(AuthenticationMessage message) { + final authMessage = ClearMessage(connection.password!); + connection.socket!.add(authMessage.asBytes()); + } +} + +class ClearMessage extends ClientMessage { + UTF8BackedString? _authString; + + ClearMessage(String password) { + _authString = UTF8BackedString(password); + } + + @override + void applyToBuffer(ByteDataWriter buffer) { + buffer.writeUint8(ClientMessage.PasswordIdentifier); + final length = 5 + _authString!.utf8Length; + buffer.writeUint32(length); + _authString!.applyToBuffer(buffer); + } +} diff --git a/lib/src/connection.dart b/lib/src/connection.dart index c7cd7094..e4b1082c 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -39,6 +39,7 @@ class PostgreSQLConnection extends Object /// [queryTimeoutInSeconds] refers to the default timeout for [PostgreSQLExecutionContext]'s execute and query methods. /// [timeZone] is the timezone the connection is in. Defaults to 'UTC'. /// [useSSL] when true, uses a secure socket when connecting to a PostgreSQL database. + /// [allowClearTextPassword] when true, allows sending the password during authentication in clear text. Use only when required by the database server and under encrypted connections, this feature may lead to security issues. PostgreSQLConnection( this.host, this.port, @@ -50,6 +51,7 @@ class PostgreSQLConnection extends Object this.timeZone = 'UTC', this.useSSL = false, this.isUnixSocket = false, + this.allowClearTextPassword = false, }) { _connectionState = _PostgreSQLConnectionStateClosed(); _connectionState.connection = this; @@ -91,6 +93,9 @@ class PostgreSQLConnection extends Object /// If true, connection is made via unix socket. final bool isUnixSocket; + /// If true, allows password in clear text for authentication. + final bool allowClearTextPassword; + /// Stream of notification from the database. /// /// Listen to this [Stream] to receive events from PostgreSQL NOTIFY commands. diff --git a/lib/src/connection_fsm.dart b/lib/src/connection_fsm.dart index 4564351f..0dcdb788 100644 --- a/lib/src/connection_fsm.dart +++ b/lib/src/connection_fsm.dart @@ -110,6 +110,16 @@ class _PostgreSQLConnectionStateAuthenticating _authenticator = createAuthenticator(connection!, AuthenticationScheme.MD5); continue authMsg; + case AuthenticationMessage.KindClearTextPassword: + if (connection!.allowClearTextPassword) { + _authenticator = + createAuthenticator(connection!, AuthenticationScheme.CLEAR); + continue authMsg; + } else { + completer.completeError(PostgreSQLException( + 'type ${message.type} connections disabled. Set AllowClearTextPassword flag on PostgreSQLConnection to enable this feature.')); + break; + } case AuthenticationMessage.KindSASL: _authenticator = createAuthenticator( connection!, AuthenticationScheme.SCRAM_SHA_256); diff --git a/pubspec.yaml b/pubspec.yaml index 06d0b8d8..cf27afc2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: postgres description: PostgreSQL database driver. Supports statement reuse and binary protocol. -version: 2.4.2 +version: 2.4.3 homepage: https://github.com/isoos/postgresql-dart environment: