From 9631dc115e6554d7cbc15a5186e37e6564c9b130 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Thu, 22 Jan 2009 00:35:17 +0000 Subject: [PATCH] Added PostgreSQL UDF to execute commands on the underlying system: * sys_eval() to return the standard output * sys_exec() to return the exit status Inspired by lib_mysqludf_sys 0.0.3 (https://svn.sqlmap.org/sqlmap/trunk/sqlmap/extra/mysqludfsys/) --- .../lib_postgresqludf_sys/Makefile | 4 + .../lib_postgresqludf_sys/install.sh | 43 ++++++++ .../lib_postgresqludf_sys.c | 100 ++++++++++++++++++ .../lib_postgresqludf_sys.so | Bin 0 -> 8607 bytes .../lib_postgresqludf_sys.sql | 23 ++++ .../lib_postgresqludf_sys_0.0.1.tar.gz | Bin 0 -> 5705 bytes 6 files changed, 170 insertions(+) create mode 100644 extra/postgresqludfsys/lib_postgresqludf_sys/Makefile create mode 100755 extra/postgresqludfsys/lib_postgresqludf_sys/install.sh create mode 100644 extra/postgresqludfsys/lib_postgresqludf_sys/lib_postgresqludf_sys.c create mode 100755 extra/postgresqludfsys/lib_postgresqludf_sys/lib_postgresqludf_sys.so create mode 100644 extra/postgresqludfsys/lib_postgresqludf_sys/lib_postgresqludf_sys.sql create mode 100644 extra/postgresqludfsys/lib_postgresqludf_sys_0.0.1.tar.gz diff --git a/extra/postgresqludfsys/lib_postgresqludf_sys/Makefile b/extra/postgresqludfsys/lib_postgresqludf_sys/Makefile new file mode 100644 index 000000000..05252cf31 --- /dev/null +++ b/extra/postgresqludfsys/lib_postgresqludf_sys/Makefile @@ -0,0 +1,4 @@ +LIBDIR=/usr/lib + +install: + gcc -Wall -I/usr/include/postgresql/8.3/server -I. -shared lib_postgresqludf_sys.c -o $(LIBDIR)/lib_postgresqludf_sys.so diff --git a/extra/postgresqludfsys/lib_postgresqludf_sys/install.sh b/extra/postgresqludfsys/lib_postgresqludf_sys/install.sh new file mode 100755 index 000000000..e645f723a --- /dev/null +++ b/extra/postgresqludfsys/lib_postgresqludf_sys/install.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions +# Copyright (C) 2009 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 + +echo "Compiling the PostgreSQL UDF" +make + +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:" + echo "apt-get install postgresql-server-dev-8.3" + exit 1 +else + echo "PostgreSQL UDF compiled successfully" +fi + +echo -e "\nPlease provide your PostgreSQL 'postgres' user's password" + +/usr/lib/postgresql/8.3/bin/psql -h 127.0.0.1 -p 5432 -U postgres -q template1 < lib_postgresqludf_sys.sql +#psql -h 127.0.0.1 -p 5432 -U postgres -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/postgresqludfsys/lib_postgresqludf_sys/lib_postgresqludf_sys.c b/extra/postgresqludfsys/lib_postgresqludf_sys/lib_postgresqludf_sys.c new file mode 100644 index 000000000..8d3d36656 --- /dev/null +++ b/extra/postgresqludfsys/lib_postgresqludf_sys/lib_postgresqludf_sys.c @@ -0,0 +1,100 @@ +/* + lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions + Copyright (C) 2009 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 +*/ + +#include +#include +#include + +#ifdef PG_MODULE_MAGIC +PG_MODULE_MAGIC; +#endif + +PG_FUNCTION_INFO_V1(sys_exec); +Datum sys_exec(PG_FUNCTION_ARGS) { + text *argv0 = PG_GETARG_TEXT_P(0); + int32 argv0_size; + int32 result = 0; + char *command; + + argv0_size = VARSIZE(argv0) - VARHDRSZ; + command = (char *)palloc(argv0_size + 1); + + memcpy(command, VARDATA(argv0), argv0_size); + command[argv0_size] = '\0'; + + /* + Only if you want to log + elog(NOTICE, "Command execution: %s", command); + */ + + result = system(command); + pfree(command); + + PG_FREE_IF_COPY(argv0, 0); + PG_RETURN_INT32(result); +} + +PG_FUNCTION_INFO_V1(sys_eval); +Datum sys_eval(PG_FUNCTION_ARGS) { + 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 *)palloc(argv0_size + 1); + + memcpy(command, VARDATA(argv0), argv0_size); + command[argv0_size] = '\0'; + + /* + Only if you want to log + elog(NOTICE, "Command evaluated: %s", command); + */ + + result = malloc(1); + outlen = 0; + + pipe = popen(command, "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[outlen] = 0x00; + } + + result_text = (text *)palloc(VARHDRSZ + strlen(result)); + SET_VARSIZE(result_text, VARHDRSZ + strlen(result)); + memcpy(VARDATA(result_text), result, strlen(result)); + + PG_RETURN_POINTER(result_text); +} diff --git a/extra/postgresqludfsys/lib_postgresqludf_sys/lib_postgresqludf_sys.so b/extra/postgresqludfsys/lib_postgresqludf_sys/lib_postgresqludf_sys.so new file mode 100755 index 0000000000000000000000000000000000000000..ddb1925d343a37385f51f55f1296250dbfbfa7f8 GIT binary patch literal 8607 zcmeHMeT-aH6~FVbWu@D8Tee!H&}l7S(Z20=+igo?>~=dXG+QX$E&>faW@p~c4$K!b zZ<<|2VKc5W8CTItqC^9vS}Vb*0kMFRZ5JrSKsFT(F@!V-iglSNmkjKAN#@6Nt? zU1Ko*VIpU8=G=47x#xbJd)|HT+!^lP>GS!7hJXkNa#IV0*a&*GMM*Y_kZ2H>;r~J@ z*ZQO@7AkBY(=4PsxI~EHDusJrzeGu56oD=BB zS>XVe?4!UY;0oY5KsQ|AFy}gSnM2P5WuN3ZPTIa(Jm3qyu;T{S(H8qL;`=W;I`Gu8 zhs>vzJ@LnH-myLW+sXEu_h0n#?bok-d~|y8Uw-rU;**Pxyad%cc*e!i-Vqni`DZ=6 zo+qnAz)!N^KnV1dWe95B~=b|7{QdYY+dFhkx6{>pf=m8eqjEH(fmEH{#*< zfPV~|!+lr=@3;e=E#>@}pO>5ASH8IQ1MDn&7 zi`a#f=qluLR@&ZUr82ppu1wmt25nKtbtaRUs7P6b`1wm$|`cGumtAjkVJHTB!{y%M+!5F>dY`L~KwpAEL+EKb&&x zBlnJwUzI?3Xb@|hx|T!&VIwFEhi{gAKx}dNrIPoH?cfPN#r`t>JmJs*Fyuc4tE7z~ zMJFKlqtox8l5_^V55eICc+v~tH>7OjN3eR)p_ihb{3`M&|J|X3tOvG}hpkRhO#6UC zThPBB0qY7c}a(p>h#wE64dai8)_?;Q8_D zBWNtDhtai!>S0FP0hZr5jb_!u+%c}Mcw+)A1qAeST~Fo5C=HLli-203Y`*JB23AqH zsa!n64#(`p3nGPF}5D<^p%QK ztA49U4b^7rbnZ{j7HQsBe7gC-%{Ps6o)rTX!{eWq-3QBuLeR%FmzNLCs?x&IBJ0q9 z^;Gfc;DMXQ%PZH8--EWtX0Wc(%CSc5iYyf;FDr)|%iEecUe2HtK65fWgFZw#e5Ndp zSNz3FuoRvxhi8jpzA_(iqO@aeu+*aUr^>yMo+*w6OZ(S0QdSO6X>({62v0prYqh#k zc*ey!-JgJottae-AaiYJp68s8HR;jz3{URB)}cvh-azaY(^?nxL2vsfO}d}SR0+R6_9n9-^t)wo>H}jBd?+5$&pv^&-FTq zHEG5i%5?@xBc~yMGdnsm3#!eQMqUP2zE}QB3%&`trqbq|7JG1Om5v8SS;swaEOM8c z)Gn2!RiCt1mi@wJBge&yNc{*##+Hl>z!Mxj$1lpV|0R!!FOAtt%F<9kR&j6Z#)cJ} z$4y42INF)uk z^ZF0e50CGL=a!4jP$|wBQlAXfbYCt z&D;Yyt~BDih$T=FuYkwnS#*QqQ6cY)yrRwE&chofZzPO8e7EGg=O7xfoP`m-Kk+@8 z?|{6t@ZEs$ezlqjL5{IyAQn@g6%68CQ1<;6&6`{*|`wD5h z5ZY+88ynWO6(rZzcDbtf-&7J}Erzdd@!TP`XKO(De#JG_p!9wKR_Q&8xwA9{JyoML z9|UpiaoHub_7xJznEH>k#`$`(ZiBJqiyPLj-?Dzw`b|o*&c^#tYodKi$2w}XM)QT% zXwFU;J>r8HaLjAdup)L{-5cuc3E_2Ti?Ov``0mPLSbpg`LEj@Nhk&hiD%%>3UfXu- z-k~dv{C~Yq-%`=Mpm#x_@q)&S8_%N)o?Y`3)cVCBWxn?oFT%h4!i0tNeUK%nTSH+O zt$5>%S=oGR+)7)yL{tc8U16B7#(Xh0qH5b3{5-XR#lF?8t3Q3?>Ug}h)!%@D1pT7H zPp1e>3P*<57@u#i9P%ae4jC(ouI83hIz)q?t`k`0TfKTUUYIb!20xuBux_pf)^tqa zXdVKx>oxg zTDg28ldfY-$Z}Sa`l^sk+QN{Z6%6^dZ^(}eMlK`Yw+(B+?9W9~mN24rCYMJCirgB7 zAsC6IunR^!10(n|q&3wNFY0KNNu}^X0jgGCA#O%;k#rm%CLESuBXl{^*O#*nYA%^b zqf6DuX;WK|e^X#+qf_$iGENhJ31l25@Qf4r4eqaqq10m>Cw8Ok)w>vVjOEm0d?$_p zX#+%3#`SeTwxu4Q2Sh#xH0a_cR4|rPk8zy11!dhY>xtWejQuP#{uAk=?ta0FYk_#> zmTmYPA@Vt*?NOi4lN()neC`lAZtBt9v|bctjum40+@s&FM_B{)2sZ<@9{rZ+)uV30 zrN?i|#EKpqWE=w_1Jw3-Mu_h3d%E9(qsMjOIU(}vfCjDi1ys-;^;)ojL@lGPE`J4O z>TyW&do{jYaJ@8Wy|1A{>ovj2n*N2}y)L~L=(Rvk+n`Ndz7J(Ah3uElV}1{xaLK91 zaU2Hfe)%n>0zKYIG*FLt6sYxh-_4v$h#0F5NL6?7l3ii)+X$k?M zH{ZJOY|)+u>OHO*P%V4LRi^kk=ii zOB9a}h5*J4Lcs9^#sBd9vlidP=2pK}3uyH;mZ$?-uD!1G85 z$P5j9u*P%cpkL#;EAW*X&)YQ4N{v@HK%NUiz&RQ8e?mZJeUzUoUf;f@7;@g$=O7?6 zF>aolI|qTfY!L11jE~X@AhNmlHHch7{h6MwvPV6CALf5Ccs+j~Jf|JJp1%)o5!=A) z_4Z@EucLlQ`MwWt6BhVp@Z56pdC;udR`}^cPfVGv-U)f5vtI1~tKb8 z9|8Y>+IDHrJ3qz=4V*81m;28c<-`8}8I)f%)%X^Pcfj+Tq2>cHsQ1t3pRO_{=>7Bg zmy1ilH|z1@gLymnAL{wx1NLt4+CSL72fPM)OANd_7j)1ir?=hV;lBaioh!P}B@aRW zM;`uHE}s2Ofaf!gz}(O8Jo1W%f6v1=;fT9)Q_Ed3gZ3}=@LR#Vb4$Cx(?1BzW%YRU zEe}5oz9l5prT&*a?MK18b6@wn+OI*gCtW)aDIHOFprd9D|EW0t+(HPFmv@^(CDA+ks4B2I&hmiT-@e1B*AudU$ecl+q`Dy&YtjobARXd?l9*Z z%V*4iNII5e3QaD69!#QRONW6Jo0*N8_CO(ho6$EY%pEse-MQzgE+I2>+qTtmXr3IN zOcBc5-n@CiS{l)tq?{)c>7@PU`daT~F;xoDUGHQD-BmJ4=&q1m%M_zbMAnI9p3z-X zTV$C9b!QM&g3_()%|On{HmZE1lZUL&rE(Dak;OiZfurmKz%U7vYXncaC(t^Wk> Cas501 literal 0 HcmV?d00001 diff --git a/extra/postgresqludfsys/lib_postgresqludf_sys/lib_postgresqludf_sys.sql b/extra/postgresqludfsys/lib_postgresqludf_sys/lib_postgresqludf_sys.sql new file mode 100644 index 000000000..1a86e984f --- /dev/null +++ b/extra/postgresqludfsys/lib_postgresqludf_sys/lib_postgresqludf_sys.sql @@ -0,0 +1,23 @@ +/* + lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions + Copyright (C) 2009 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 '/usr/lib/lib_postgresqludf_sys.so', 'sys_exec' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE; +CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/usr/lib/lib_postgresqludf_sys.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE; diff --git a/extra/postgresqludfsys/lib_postgresqludf_sys_0.0.1.tar.gz b/extra/postgresqludfsys/lib_postgresqludf_sys_0.0.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..575c46e0a4e6a302dc77dd1e4011de8af118aeef GIT binary patch literal 5705 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