Based on my last post MySQL LDAP Authentication Plugin, I received feedback from MySql Joro Blog by Oracle.
They told me:
Insted of writing (and having to deply) your own client plugin you probably can reuse the cleartext client side plugin, specially because it’s available in a number of mysql clients already. Check sql-common/client.c on MySQL 5.5+ for details.
This is very useful because you only need to put the plugin in server side, and in the client side you only need to check if the clear password plugin is enabled.
Now, I present the updated code with the only server side plugin, and I reused the cleartext client side plugin from MySql, it’s more short and very focused in LDAP authentication:
/* Author: Ignacio Ocampo <nafiux@gmail.com> Website: http://www.nafiux.com/blog Version: 1.0.3 Description: Server auth LDAP plugin with client cleartext built-in plugin */ #include <mysql/plugin_auth.h> #include <mysql/client_plugin.h> #include <mysql.h> #include <stdio.h> #include <unistd.h> #include <syslog.h> #include <string.h> #include <ldap.h> #define LDAP_SERVER "ldap://nafiux.com:389" #define LDAP_PATH "ou=People,dc=nafiux,dc=com" static void auth_ldap_log(int priority, char *msg) { openlog("auth_ldap", LOG_PID|LOG_CONS, LOG_USER); syslog(LOG_INFO, msg); closelog(); } /* ldap login function */ static int auth_ldap_login(char *username, unsigned char *password) { LDAP *ld; int rc; char dn[200]; char buffer[200]; /* Open LDAP Connection*/ if( ldap_initialize( &ld, LDAP_SERVER ) ) { auth_ldap_log(LOG_ERR, "ldap_initialize"); return( 1 ); } /* User authentication (bind) */ sprintf(dn, "cn=%s,%s", username, LDAP_PATH); rc = ldap_simple_bind_s( ld, dn, password ); if( rc != LDAP_SUCCESS ) { sprintf(buffer, "Authentication failed: %s", dn); auth_ldap_log(LOG_INFO, buffer); return( 1 ); } sprintf(buffer, "Authentication successful: %s", dn); auth_ldap_log(LOG_INFO, buffer); return( 0 ); } /* principal function */ static int auth_ldap_server (MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) { unsigned char *pkt; int pkt_len; /* read the password as null-terminated string, fail on error */ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0) return CR_ERROR; /* fail on empty password */ if (!pkt_len || *pkt == '\0') { auth_ldap_log(LOG_INFO, "fail empty password"); info->password_used= PASSWORD_USED_NO; return CR_ERROR; } /* accept any nonempty password */ info->password_used= PASSWORD_USED_YES; //auth_ldap_log(LOG_INFO, "accept any nonempty password"); if(auth_ldap_login(info->user_name, pkt)) return CR_ERROR; strcpy(info->authenticated_as, "dev"); // local user strcpy(info->external_user, info->user_name); return CR_OK; } static struct st_mysql_auth auth_ldap_handler = { MYSQL_AUTHENTICATION_INTERFACE_VERSION, "mysql_clear_password", /* required client-side plugin name */ auth_ldap_server /* server-side plugin main function */ }; mysql_declare_plugin(auth_ldap) { MYSQL_AUTHENTICATION_PLUGIN, &auth_ldap_handler, /* type-specific descriptor */ "auth_ldap", /* plugin name */ "Ignacio Ocampo", /* author */ "LDAP authentication plugin", /* description */ PLUGIN_LICENSE_GPL, /* license type */ NULL, /* no init function */ NULL, /* no deinit function */ 0x0100, /* version = 1.0 */ NULL, /* no status variables */ NULL, /* no system variables */ NULL, /* no reserved information */ 0 /* no flags */ } mysql_declare_plugin_end;
Make the plugin
make
And copy to plugin folder
cp plugin/auth_ldap/auth_ldap.so /usr/local/mysql/lib/plugin/auth_ldap.so
Test it
/usr/local/mysql/bin/mysql -h 127.0.0.1 -u nafiux --password=anypassword ERROR 2059 (HY000): Authentication plugin 'mysql_clear_password' cannot be loaded: plugin not enabled
If you get this error it’s because in sql-common/client_plugin.c, in the load_env_plugins function is a validation:
static void load_env_plugins(MYSQL *mysql) { char *plugs, *free_env, *s= getenv("LIBMYSQL_PLUGINS"); char *enable_cleartext_plugin= getenv("LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN"); if (enable_cleartext_plugin && strchr("1Yy", enable_cleartext_plugin[0])) libmysql_cleartext_plugin_enabled= 1; /* no plugins to load */ if(!s) return;
To solve this, you need to define the environment variable LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN as:
export LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN=1
It only works on user session, if you want to do this permanently edit your ~/.bash_profile, for all users edit /etc/profile
Re-try:
[root@localhost mysql-5.5.27]# /usr/local/mysql/bin/mysql -h 127.0.0.1 -u nafiux --password=anypassword ERROR 1045 (28000): Access denied for user 'nafiux'@'localhost' (using password: YES) [root@localhost mysql-5.5.27]# /usr/local/mysql/bin/mysql -h 127.0.0.1 -u nafiux --password=REAL_LDAP_PASSWORD Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 9 Server version: 5.5.27 Source distribution Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql>
PlanetMySQL Voting: Vote UP / Vote DOWN