--- plugins/sql.c.orig Fri Dec 24 14:06:15 2004 +++ plugins/sql.c Sun Sep 4 22:28:30 2005 @@ -54,6 +54,7 @@ const char *sql_insert; const char *sql_update; int sql_usessl; + int sql_verbose; } sql_settings_t; static const char * SQL_BLANK_STRING = ""; @@ -279,8 +280,9 @@ } else if (status != PGRES_TUPLES_OK) { /* error */ - utils->log(NULL, SASL_LOG_DEBUG, "sql plugin: %s ", - PQresStatus(status)); + if (settings->sql_verbose) + utils->log(NULL, SASL_LOG_DEBUG, "sql plugin: %s ", + PQresStatus(status)); PQclear(result); return -1; } @@ -405,7 +407,8 @@ rc = sqlite_exec((sqlite*)db, cmd, sqlite_my_callback, (void*)&result, &zErrMsg); if (rc != SQLITE_OK && rc != SQLITE_ABORT) { - utils->log(NULL, SASL_LOG_DEBUG, "sql plugin: %s ", zErrMsg); + if (settings->sql_verbose) + utils->log(NULL, SASL_LOG_DEBUG, "sql plugin: %s ", zErrMsg); sqlite_freemem (zErrMsg); return -1; } @@ -596,7 +599,7 @@ { sql_settings_t *settings; int r; - const char *usessl, *engine_name; + const char *usessl, *engine_name, *sql_verbose; const sql_engine_t *e; settings = (sql_settings_t *) glob_context; @@ -678,6 +681,11 @@ } else { settings->sql_usessl = 0; } + + /* sql verbose */ + r = utils->getopt(utils->getopt_context, "SQL", "sql_verbose", &sql_verbose, NULL); + if (r || !sql_verbose) sql_verbose = "no"; + settings->sql_verbose = (*sql_verbose == '1' || *sql_verbose == 'y' || *sql_verbose == 't' || (*sql_verbose == 'o' && sql_verbose[1] == 'n')); } static void *sql_connect(sql_settings_t *settings, const sasl_utils_t *utils) @@ -691,7 +699,8 @@ * it should probably save the connection but for * now we will just disconnect everytime */ - utils->log(NULL, SASL_LOG_DEBUG, + if (settings->sql_verbose) + utils->log(NULL, SASL_LOG_DEBUG, "sql plugin try and connect to a host\n"); /* create a working version of the hostnames */ @@ -707,10 +716,11 @@ while (!isalnum(db_host[0])) db_host++; } - utils->log(NULL, SASL_LOG_DEBUG, - "sql plugin trying to open db '%s' on host '%s'%s\n", - settings->sql_database, cur_host, - settings->sql_usessl ? " using SSL" : ""); + if (settings->sql_verbose) + utils->log(NULL, SASL_LOG_DEBUG, + "sql plugin trying to open db '%s' on host '%s'%s\n", + settings->sql_database, cur_host, + settings->sql_usessl ? " using SSL" : ""); /* set the optional port */ if ((cur_port = strchr(cur_host, ':'))) *cur_port++ = '\0'; @@ -724,7 +734,7 @@ if (conn) break; utils->log(NULL, SASL_LOG_ERR, - "sql plugin could not connect to host %s", cur_host); + "sql plugin could not connect to host %s", cur_host); cur_host = db_host; } @@ -761,7 +771,8 @@ /* setup the settings */ settings = (sql_settings_t *) glob_context; - sparams->utils->log(NULL, SASL_LOG_DEBUG, + if (settings->sql_verbose) + sparams->utils->log(NULL, SASL_LOG_DEBUG, "sql plugin Parse the username %s\n", user); user_buf = sparams->utils->malloc(ulen + 1); @@ -832,14 +843,16 @@ if (!do_txn) { do_txn = 1; - sparams->utils->log(NULL, SASL_LOG_DEBUG, "begin transaction"); + if (settings->sql_verbose) + sparams->utils->log(NULL, SASL_LOG_DEBUG, "begin transaction"); if (settings->sql_engine->sql_begin_txn(conn, sparams->utils)) { - sparams->utils->log(NULL, SASL_LOG_ERR, - "Unable to begin transaction\n"); + sparams->utils->log(NULL, SASL_LOG_ERR, + "Unable to begin transaction\n"); } } - - sparams->utils->log(NULL, SASL_LOG_DEBUG, + + if (settings->sql_verbose) + sparams->utils->log(NULL, SASL_LOG_DEBUG, "sql plugin create statement from %s %s %s\n", realname, escap_userid, escap_realm); @@ -849,7 +862,8 @@ escap_realm, NULL, sparams->utils); - sparams->utils->log(NULL, SASL_LOG_DEBUG, + if (settings->sql_verbose) + sparams->utils->log(NULL, SASL_LOG_DEBUG, "sql plugin doing query %s\n", query); /* run the query */ @@ -863,7 +877,8 @@ } if (do_txn) { - sparams->utils->log(NULL, SASL_LOG_DEBUG, "commit transaction"); + if (settings->sql_verbose) + sparams->utils->log(NULL, SASL_LOG_DEBUG, "commit transaction"); if (settings->sql_engine->sql_commit_txn(conn, sparams->utils)) { sparams->utils->log(NULL, SASL_LOG_ERR, "Unable to commit transaction\n"); @@ -910,7 +925,8 @@ /* make sure our input is okay */ if (!glob_context || !sparams || !user) return SASL_BADPARAM; - sparams->utils->log(NULL, SASL_LOG_DEBUG, + if (settings->sql_verbose) + sparams->utils->log(NULL, SASL_LOG_DEBUG, "sql plugin Parse the username %s\n", user); user_buf = sparams->utils->malloc(ulen + 1); @@ -997,9 +1013,11 @@ cur->values && cur->values[0] ? "" : SQL_NULL_VALUE, sparams->utils); - sparams->utils->log(NULL, SASL_LOG_DEBUG, - "sql plugin doing statement %s\n", - log_statement); + + if (settings->sql_verbose) + sparams->utils->log(NULL, SASL_LOG_DEBUG, + "sql plugin doing statement %s\n", + log_statement); sparams->utils->free(log_statement); } @@ -1046,7 +1064,8 @@ if (!settings) return; - utils->log(NULL, SASL_LOG_DEBUG, "sql freeing memory\n"); + if (settings->sql_verbose) + utils->log(NULL, SASL_LOG_DEBUG, "sql freeing memory\n"); utils->free(settings); } @@ -1094,9 +1113,10 @@ return SASL_NOMECH; } - utils->log(NULL, SASL_LOG_DEBUG, - "sql auxprop plugin using %s engine\n", - settings->sql_engine->name); + if (settings->sql_verbose) + utils->log(NULL, SASL_LOG_DEBUG, + "sql auxprop plugin using %s engine\n", + settings->sql_engine->name); sql_auxprop_plugin.glob_context = settings; --- lib/Makefile.in.orig Sun May 15 02:58:38 2005 +++ lib/Makefile.in Sun Sep 4 22:28:45 2005 @@ -121,7 +121,7 @@ JAVA_TRUE = @JAVA_TRUE@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ +LIBS = -lcrypt @LIBS@ LIBTOOL = @LIBTOOL@ LIB_CRYPT = @LIB_CRYPT@ LIB_DES = @LIB_DES@ --- lib/checkpw.c.orig Wed Mar 17 10:58:13 2004 +++ lib/checkpw.c Sun Sep 4 22:28:45 2005 @@ -94,6 +94,23 @@ # endif #endif +/****************************** + * crypt(3) patch start * + ******************************/ +char *crypt(const char *key, const char *salt); + +/* cleartext password formats */ +#define PASSWORD_FORMAT_CLEARTEXT 1 +#define PASSWORD_FORMAT_CRYPT 2 +#define PASSWORD_FORMAT_CRYPTTRAD 3 +#define PASSWORD_SALT_BUF_LEN 22 + +/* weeds out crypt(3) password's salt */ +int _sasl_get_salt (char *dest, char *src, int format); + +/****************************** + * crypt(3) patch stop * + ******************************/ /* we store the following secret to check plaintext passwords: * @@ -143,7 +160,51 @@ "*cmusaslsecretPLAIN", NULL }; struct propval auxprop_values[3]; - + + /****************************** + * crypt(3) patch start * + * for password format check * + ******************************/ + sasl_getopt_t *getopt; + void *context; + const char *p = NULL; + /** + * MD5: 12 char salt + * BLOWFISH: 16 char salt + */ + char salt[PASSWORD_SALT_BUF_LEN]; + int password_format; + + /* get password format from auxprop configuration */ + if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) { + getopt(context, NULL, "password_format", &p, NULL); + } + + /* set password format */ + if (p) { + /* + memset(pass_format_str, '\0', PASSWORD_FORMAT_STR_LEN); + strncpy(pass_format_str, p, (PASSWORD_FORMAT_STR_LEN - 1)); + */ + /* modern, modular crypt(3) */ + if (strncmp(p, "crypt", 11) == 0) + password_format = PASSWORD_FORMAT_CRYPT; + /* traditional crypt(3) */ + else if (strncmp(p, "crypt_trad", 11) == 0) + password_format = PASSWORD_FORMAT_CRYPTTRAD; + /* cleartext password */ + else + password_format = PASSWORD_FORMAT_CLEARTEXT; + } else { + /* cleartext password */ + password_format = PASSWORD_FORMAT_CLEARTEXT; + } + + /****************************** + * crypt(3) patch stop * + * for password format check * + ******************************/ + if (!conn || !userstr) return SASL_BADPARAM; @@ -180,14 +241,31 @@ goto done; } - /* At the point this has been called, the username has been canonified - * and we've done the auxprop lookup. This should be easy. */ - if(auxprop_values[0].name - && auxprop_values[0].values - && auxprop_values[0].values[0] - && !strcmp(auxprop_values[0].values[0], passwd)) { - /* We have a plaintext version and it matched! */ - return SASL_OK; + + /****************************** + * crypt(3) patch start * + ******************************/ + + /* get salt */ + _sasl_get_salt(salt, (char *) auxprop_values[0].values[0], password_format); + + /* crypt(3)-ed password? */ + if (password_format != PASSWORD_FORMAT_CLEARTEXT) { + /* compare password */ + if (auxprop_values[0].name && auxprop_values[0].values && auxprop_values[0].values[0] && strcmp(crypt(passwd, salt), auxprop_values[0].values[0]) == 0) + return SASL_OK; + else + ret = SASL_BADAUTH; + } + else if (password_format == PASSWORD_FORMAT_CLEARTEXT) { + /* compare passwords */ + if (auxprop_values[0].name && auxprop_values[0].values && auxprop_values[0].values[0] && strcmp(auxprop_values[0].values[0], passwd) == 0) + return SASL_OK; + else + ret = SASL_BADAUTH; + /****************************** + * crypt(3) patch stop * + ******************************/ } else if(auxprop_values[1].name && auxprop_values[1].values && auxprop_values[1].values[0]) { @@ -975,3 +1053,37 @@ #endif { NULL, NULL } }; + +/* weeds out crypt(3) password's salt */ +int _sasl_get_salt (char *dest, char *src, int format) { + int num; /* how many characters is salt long? */ + switch (format) { + case PASSWORD_FORMAT_CRYPT: + /* md5 crypt */ + if (src[1] == '1') + num = 12; + /* blowfish crypt */ + else if (src[1] == '2') + num = (src[1] == '2' && src[2] == 'a') ? 17 : 16; + /* traditional crypt */ + else + num = 2; + break; + + case PASSWORD_FORMAT_CRYPTTRAD: + num = 2; + break; + + default: + return 1; + } + + /* destroy destination */ + memset(dest, '\0', (num + 1)); + + /* copy salt to destination */ + strncpy(dest, src, num); + + return 1; +} +