axl_bool mod_sasl_mysql_check_ip_filter_query (TurbulenceCtx * ctx, const char * query, VortexConnection * conn, axlNode * auth_db_node_conf) { MYSQL_RES * result; MYSQL_ROW row; axlError * err = NULL; TurbulenceExpr * expr; /* run query */ result = mod_sasl_mysql_do_query (ctx, auth_db_node_conf, query, axl_false, &err); /* check result */ if (result == NULL) { error ("Unable to run ip filter SQL, query string failed with %s", axl_error_get (err)); axl_error_free (err); return axl_false; } /* end if */ /* return content from the first [0][0] array position */ row = mysql_fetch_row (result); if (row == NULL) { mysql_free_result (result); return axl_true; /* do not filter (user unknown, so let login fail) */ } /* end if */ /* check for empty filter string */ if (row[0] == NULL || strlen (row[0]) == 0) { mysql_free_result (result); return axl_true; /* do not filter */ } msg ("Checking to apply ip filter with expression: %s (ip: %s:%s)", row[0], vortex_connection_get_host (conn), vortex_connection_get_host_ip (conn)); /* build expression */ expr = turbulence_expr_compile (ctx, row[0], NULL); if (expr == NULL) { error ("Failed to compile expression: %s. Unable to apply ip filter, denying connection.", row[0]); mysql_free_result (result); return axl_false; /* do not filter */ } mysql_free_result (result); /* now match by hostname */ if (turbulence_expr_match (expr, vortex_connection_get_host (conn))) { turbulence_expr_free (expr); return axl_true; /* do not filter */ } /* ..and by hostip */ if (turbulence_expr_match (expr, vortex_connection_get_host_ip (conn))) { turbulence_expr_free (expr); return axl_true; /* do not filter */ } /* free expression */ turbulence_expr_free (expr); return axl_false; /* do filter */ }
axl_bool mod_sasl_mysql_check_unallowed_sequence (TurbulenceCtx * ctx, VortexConnection * conn, const char * content) { char * new_content; axl_bool found; if (content == NULL || strlen (content) == 0) return axl_true; /* get a lower copy so we can do a case insensitive check */ new_content = axl_stream_to_lower_copy (content); if (new_content == NULL) { error ("Unable to copy content to do unallowed sequence, error was.."); return axl_false; } /* end if */ /* replace all \t with " " to unifify checks. Do the same with \n and \r */ axl_replace (new_content, "\t", " "); axl_replace (new_content, "\r", " "); axl_replace (new_content, "\n", " "); /* set initial status */ found = axl_false; if (strstr (new_content, "select ")) found = axl_true; if (strstr (new_content, "insert ")) found = axl_true; if (strstr (new_content, "delete ")) found = axl_true; if (strstr (new_content, ";")) found = axl_true; if (strstr (new_content, "--")) found = axl_true; if (strstr (new_content, "'")) found = axl_true; /* drop an error log if found */ if (found) { error ("IP %s should be blocked now because: Found unallowed input sequence at login attempt. Unallowed sequence is: %s", vortex_connection_get_host_ip (conn), content); vortex_connection_shutdown (conn); } /* end if */ /* release memory copy */ axl_free (new_content); /* report failure */ return ! found; }
axl_bool mod_sasl_mysql_do_auth (TurbulenceCtx * ctx, VortexConnection * conn, axlNode * auth_db_node_conf, const char * auth_id, const char * authorization_id, const char * formated_password, const char * password, const char * serverName, const char * sasl_method, axlError ** err) { char * query; axlDoc * doc; axlNode * node; axl_bool _result = axl_false; /* check import parameters without doing anything */ if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, auth_id)) return axl_false; if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, password)) return axl_false; if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, formated_password)) return axl_false; if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, serverName)) return axl_false; if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, authorization_id)) return axl_false; if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, sasl_method)) return axl_false; if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, auth_id)) return axl_false; if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, vortex_connection_get_host (conn))) return axl_false; /* get the auth query */ doc = axl_node_annotate_get (auth_db_node_conf, "mysql-conf", axl_false); if (doc == NULL) { axl_error_report (err, -1, "Found no xml document defining MySQL settings to connect to the database"); return axl_false; } /* end if */ /* check for ip filter reference */ node = axl_doc_get (doc, "/sasl-auth-db/ip-filter"); if (node && HAS_ATTR (node, "query")) { /* ip filter defined, get query */ query = axl_strdup (ATTR_VALUE (node, "query")); /* replace query with recognized tokens */ axl_replace (query, "%u", auth_id); axl_replace (query, "%n", serverName); axl_replace (query, "%i", authorization_id); axl_replace (query, "%m", sasl_method); msg ("Checking IP filter for auth id [%s], query [%s]", auth_id, query); if (! mod_sasl_mysql_check_ip_filter_query (ctx, query, conn, auth_db_node_conf)) { error ("login failure: %s, ip filtered by defined expression associated to user: %s denied connection from %s", auth_id, auth_id, vortex_connection_get_host_ip (conn)); axl_free (query); return 0; } msg ("IP not filtered by defined expression associated to user: %s allowed connection from %s", auth_id, vortex_connection_get_host_ip (conn)); /* ip not filtered, now let the auth continue */ axl_free (query); } /* end if */ /***** ALT AUTHENTICATION *****/ /* get alt password if defined <get-password-alt> */ node = axl_doc_get (doc, "/sasl-auth-db/get-password-alt"); if (node) { /* get query */ query = (char *) ATTR_VALUE_TRANS (node, "query"); /* call to do auth operation */ _result = __mod_sasl_mysql_prepare_query_and_auth (ctx, query, conn, auth_db_node_conf, auth_id, authorization_id, formated_password, password, serverName, sasl_method, axl_false, /* skip login error reporting */ axl_true, err); /* clean for cleanup node <get-password-alt-cleanup> */ node = axl_doc_get (doc, "/sasl-auth-db/get-password-alt-cleanup"); if (node) { /* get query */ query = (char *) ATTR_VALUE_TRANS (node, "query"); /* call and skip getting value reported */ if (! __mod_sasl_mysql_prepare_query_and_auth (ctx, query, conn, auth_db_node_conf, auth_id, authorization_id, formated_password, password, serverName, sasl_method, axl_true, /* skip login error reporting */ axl_true, err)) error ("Cleanup query failed, please, review <get-password-alt-cleanup>.."); } /* end if */ } /* end if */ /**** MAIN AUTHENTICATION ****/ /* if authentication failed, try with main table */ if (! _result) { /* get the node that contains the configuration */ node = axl_doc_get (doc, "/sasl-auth-db/get-password"); query = (char *) ATTR_VALUE (node, "query"); /* call to do auth operation */ _result = __mod_sasl_mysql_prepare_query_and_auth (ctx, query, conn, auth_db_node_conf, auth_id, authorization_id, formated_password, password, serverName, sasl_method, axl_false, /* skip login error reporting */ axl_false, err); } /* end if */ /* now check for auth-log declaration to report it */ node = axl_doc_get (doc, "/sasl-auth-db/auth-log"); if (node) { /* log auth defined */ query = axl_strdup (ATTR_VALUE (node, "query")); /* replace query with recognized tokens */ axl_replace (query, "%t", _result ? "ok" : "failed"); axl_replace (query, "%u", auth_id); axl_replace (query, "%n", serverName); axl_replace (query, "%i", authorization_id); axl_replace (query, "%m", sasl_method); axl_replace (query, "%p", vortex_connection_get_host (conn)); msg ("Trying to auth-log %s:%s with query string %s", auth_id, _result ? "ok" : "failed", query); /* exec query */ if (! mod_sasl_mysql_do_query (ctx, auth_db_node_conf, query, axl_true, err)) { error ("Unable to auth-log, failed query configured, error was: %d:%s", axl_error_get_code (*err), axl_error_get (*err)); axl_error_free (*err); } axl_free (query); } /* end if */ if (!_result) error ("login failure: %s, failed from: %s", auth_id, vortex_connection_get_host_ip (conn)); return _result ? 1 : 0; }
axl_bool __mod_sasl_mysql_prepare_query_and_auth (TurbulenceCtx * ctx, const char * _query, VortexConnection * conn, axlNode * auth_db_node_conf, const char * auth_id, const char * authorization_id, const char * formated_password, const char * password, const char * serverName, const char * sasl_method, axl_bool just_run_query, axl_bool skip_login_error_reporting, axlError ** err) { MYSQL_RES * result; MYSQL_ROW row; axl_bool _result; char * query; /* duplicate query */ query = axl_strdup (_query); if (query == NULL) return axl_false; /* allocation failure */ /* replace query with recognized tokens */ axl_replace (query, "%u", auth_id); axl_replace (query, "%n", serverName); axl_replace (query, "%i", authorization_id); axl_replace (query, "%m", sasl_method); axl_replace (query, "%p", vortex_connection_get_host (conn)); if (! just_run_query) { msg ("Trying to auth [%s] with query string [%s], conn-id=%d from %s:%s ", auth_id, query, vortex_connection_get_id (conn), vortex_connection_get_host (conn), vortex_connection_get_port (conn)); } /* end if */ /* run query */ result = mod_sasl_mysql_do_query (ctx, auth_db_node_conf, query, axl_false, err); axl_free (query); /* check if we have to only run this query */ if (just_run_query) { mysql_free_result (result); return axl_true; } /* end if */ /* check result */ if (result == NULL) { error ("Unable to authenticate user, query string failed with %s", axl_error_get (*err)); axl_error_free (*err); return axl_false; } /* end if */ /* return content from the first [0][0] array position */ row = mysql_fetch_row (result); if (row == NULL) { if (! skip_login_error_reporting) { /* log login failure */ error ("login failure: %s, failed from: %s", auth_id, vortex_connection_get_host_ip (conn)); } /* end if */ mysql_free_result (result); return axl_false; } /* end if */ /* check result */ _result = axl_cmp (row[0], formated_password); if (! _result) { /* if it fails, check password format */ /* support here passwords schemes using */ /* http://wiki.dovecot.org/Authentication/PasswordSchemes */ _result = common_sasl_check_crypt_password (password, row[0]); } /* end if */ mysql_free_result (result); return _result; }
/** * @brief a frame received Callback */ void listenerFrameReceivedCallback (VortexChannel* channel, VortexConnection* connection, VortexFrame* frame, axlPointer user_data) { VORTEXListenerFrameReceivedCallbackData* callbackData = (VORTEXListenerFrameReceivedCallbackData*) user_data; TML_INT32 iRet = TML_SUCCESS; ///////////////////////////////////////////////////////////////////////////// // Fetching all necessary attributes from Vortex: /////////////////////////// // Die Connection ID: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_connection_get_id"); int iConnectionID = vortex_connection_get_id(connection); /////////////////////////// // Die Host IP: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_connection_get_host_ip"); const char* sHostIP = vortex_connection_get_host_ip(connection); /////////////////////////// // Der Port: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_connection_get_local_port"); const char* sPort = vortex_connection_get_port(connection); /////////////////////////// // Die Channel ID: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_channel_get_number"); int iChannelID = vortex_channel_get_number (channel); if (-1 == iChannelID) iRet = TML_ERR_LISTENER_COMMUNICATION; /////////////////////////// // Die Message ID: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_frame_get_msgno"); int iMsgID = vortex_frame_get_msgno (frame); if (-1 == iMsgID) iRet = TML_ERR_LISTENER_COMMUNICATION; /////////////////////////// // Das Profil, mit dem der Sender conneted ist: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_channel_get_profile"); const char* sProfile = vortex_channel_get_profile (channel); if (NULL == sProfile) iRet = TML_ERR_LISTENER_COMMUNICATION; /////////////////////////// // Das Payload: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_frame_get_payload"); char* cPayload = (char*)vortex_frame_get_payload (frame); if (NULL == cPayload) iRet = TML_ERR_LISTENER_COMMUNICATION; /////////////////////////// // Die Payloadsize: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_frame_get_payload_size"); int iPayloadSize = vortex_frame_get_payload_size (frame); if (-1 == iPayloadSize) iRet = TML_ERR_LISTENER_COMMUNICATION; ///////////////////////////////////////////////////////////////////////////// // Set all necessary Vortex attributes into the TML_COMMAND_HANDLE Obj: if (TML_SUCCESS == iRet){ // A new TML_COMMAND_HANDLE object out of the payload: TML_COMMAND_HANDLE cmdHandle; iRet = tml_Cmd_Create(&cmdHandle); if (TML_SUCCESS == iRet){ SIDEX_HANDLE sHandle; /////////////////////////////////////////////// // Acquire critical section use: tml_Cmd_Acquire_Sidex_Handle(cmdHandle, &sHandle); iRet = sidex_Set_Content(sHandle, cPayload); /////////////////////////////////////////////// // Now I can release the critical section use: tml_Cmd_Release_Sidex_Handle(cmdHandle); } if (TML_SUCCESS == iRet){ // Vortex- session ID into the TML_COMMAND_HANDLE object: tml_Cmd_Attr_Set_Session_ID(cmdHandle, iConnectionID); // Don't mind of return value // Vortex- channel ID into the TML_COMMAND_HANDLE object: tml_Cmd_Attr_Set_Channel_ID(cmdHandle, iChannelID); // Don't mind of return value callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_channel_ref"); vortex_channel_ref(channel); // I will be shure to have a valid channel until the reply is send // Vortex- channel into the TML_COMMAND_HANDLE object: tml_Cmd_Attr_Set_Channel(cmdHandle, channel); // Don't mind of return value // Vortex- message ID into the TML_COMMAND_HANDLE object: tml_Cmd_Attr_Set_Message_ID(cmdHandle, iMsgID); // Don't mind of return value // Vortex- profile into the TML_COMMAND_HANDLE object: tml_Cmd_Attr_Set_Profile(cmdHandle, sProfile); // The core handle: tml_Cmd_Attr_Set_Core_Reference(cmdHandle, callbackData->tmlcorehandle); // Don't mind of return value TML_CONNECTION_HANDLE connectionHandle = TML_HANDLE_TYPE_NULL; ////////////////////////////////////////////////////////////////// // Add the connection to the list: if (NULL != sHostIP && NULL != sPort && NULL != connection){ ((tmlCoreWrapper*)callbackData->tmlcorehandle)->tmlCoreWrapper_Connect(sHostIP, sPort, false, &connectionHandle, connection); ((tmlObjWrapper*)cmdHandle)->tmlObjWrapper_Set_Connection(connectionHandle); } // Now call the callback method: globalCallback(callbackData->callback, (void*) cmdHandle); } } else{ callbackData->pLog->log ("TMLCoreListener", "listenerFrameReceivedCallback", "ERROR", "Problem on getting some attributes."); } return; }