Tuesday, May 4, 2010

Mod_auth_mysql Django Authentication

I needed a way to get mod_auth mysql to work with django password scheme so that I can have a single sign-on between apache and django. Unfortunately, Django uses a salted password scheme (hashtype$salt$Password) while mod_auth_mysql expects unsalted hashes. To take advantage of the salting advantages, it's better to update mod_auth_mysql to understand django's password scheme.
Well since blogger doesn't allow me to upload a patch file, here it goes
Patch for mod-auth-mysql-4.3.9
----
--- mod_auth_mysql.c-pristine   2010-05-04 17:07:43.000000000 +0400
+++ mod_auth_mysql.c 2010-05-04 17:08:01.000000000 +0400
@@ -103,6 +103,8 @@
#endif
#define SHA1SUM_ENCRYPTION_FLAG 1<<6

+#define DJANGO_ENCRYPTION_FLAG 1<<8
+
static int check_no_encryption(const char *passwd, char *enc_passwd)
{
return (!strcmp(passwd, enc_passwd));
@@ -226,6 +228,86 @@
return (!strcmp(sha1_hex_hash(passwd), enc_passwd));
}

+static int check_django_encryption(const char *passwd, char *enc_passwd)
+{
+ char *delim = "$";
+ char *hash_type, *cp, *hash, *salt, *salted_passwd, *free_cp;
+ int ret;
+
+ // Since strtok alters the string it is parsing,
+ // we should always copy the string to a temporary buffer
+ cp = strdup (enc_passwd);
+
+ // strdup() function returns a pointer to the duplicated string, or
+ // NULL if insufficient memory was available
+ if (cp == NULL){
+ //TODO: Use the proper log for these errors. Not syslog
+ syslog(LOG_DEBUG, "Module_Auth_MySQL: Couldn't allocate memory for %s.\nExiting\n", cp);
+ return 0;
+ }
+ free_cp = cp;
+
+
+ //split the hash_type out
+ hash_type = strtok(cp, delim);
+ if (hash_type == NULL){
+ syslog(LOG_DEBUG, "Module_Auth_MySQL: Couldn't find %s in %s.\nExiting\n",delim, cp);
+ free(free_cp);
+ return 0;
+ }
+
+ //split the salt out
+ salt = strtok(NULL, delim);
+ if (salt == NULL){
+ syslog(LOG_DEBUG, "Module_Auth_MySQL: Couldn't find %s in %s.\nExiting\n",delim, cp);
+ free(free_cp);
+ return 0;
+ }
+
+ //split the salt out
+ hash = strtok(NULL, delim);
+ if (hash == NULL){
+ syslog(LOG_DEBUG, "Module_Auth_MySQL: Couldn't find %s in %s.\nExiting\n",delim, cp);
+ free(free_cp);
+ return 0;
+ }
+
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "MAMDEBUG: DJANGO called: passwd:%s enc_password:%s", passwd, enc_passwd);
+ syslog(LOG_DEBUG, "MAMDEBUG: Hash method: %s\n", hash_type);
+ syslog(LOG_DEBUG, "MAMDEBUG: Salt: %s\n", salt);
+ syslog(LOG_DEBUG, "MAMDEBUG: Hash: %s\n", hash);
+#endif
+
+ // Concat salt and password.
+ salted_passwd = malloc(strlen(salt)+strlen(passwd)+1);
+ if (salted_passwd == NULL){
+ syslog(LOG_DEBUG, "Module_Auth_MySQL: Couldn't allocate memory for %s.\nExiting\n", salted_passwd);
+ free(free_cp);
+ return 0;
+ }
+ strcpy(salted_passwd, salt);
+ strcat(salted_passwd, passwd);
+
+ if( !strcmp(hash_type, "sha1") ) {
+ ret = (!strcmp(sha1_hex_hash(salted_passwd), hash));
+ }
+ else if( !strcmp(hash_type, "md5") ) {
+ ret = (!strcmp(md5_hex_hash(salted_passwd), hash));
+ }
+ else {
+ syslog(LOG_DEBUG, "Module_Auth_MySQL: Uknown salt type %s.", hash_type);
+ ret = 0;
+ }
+
+ //Free the strdup resource and the malloc resource
+ free(free_cp);
+ free(salted_passwd);
+
+ return ret;
+}
+
+

static int check_mysql_encryption(const char *passwd, char *enc_passwd)
{
@@ -254,6 +336,7 @@
{ "PHP_MD5", check_PHP_MD5_encryption, PHP_MD5_ENCRYPTION_FLAG },
{ "SHA1Sum", check_SHA1Sum_encryption, SHA1SUM_ENCRYPTION_FLAG},
/* add additional encryption types below */
+ { "Django", check_django_encryption, DJANGO_ENCRYPTION_FLAG},
{ NULL, NULL, 0 }
};

----
A dpatch is also available for debian users. Read more about dpatch here. Remember to update your 00list :)

No comments:

Post a Comment