Postgres ECPG: adding a function outside main() breaks the program - c

I have successfully connected and obtained data from Postgresql with my C application. My connector.pgc file looks like this:
#include <stdlib.h>
#include <stdio.h>
//#include "connect.h" // PROBLEM
int connect(); //NO PROBLEM
EXEC SQL BEGIN DECLARE SECTION;
char dbname[1024];
const char *target = "dbname#host:port";
const char *user = "user";
const char *passwd = "password";
EXEC SQL END DECLARE SECTION;
int main() {
EXEC SQL CONNECT TO :target AS con1 USER :user USING :passwd;
EXEC SQL SELECT pg_catalog.set_config('search_path', 'schema_name', false); EXEC SQL COMMIT;
EXEC SQL SET CONNECTION con1;
EXEC SQL SELECT current_database() INTO :dbname;
printf("current database is '%s'\n", dbname);
EXEC SQL DISCONNECT ALL;
// connect();
return 0;
}
// PROBLEM
//int connect(){
// printf("A\n");
// return 0;
//}
except, of course, username/password/schema_name/etc. are replaced with actual values.
I then do the following:
ecpg connector.pgc && gcc connector.c -o connectorXec -lecpg -L/usr/pgsql-12/lib && ./connectorXec
My operating system is a default CentOS 8.
ecpg --version returns ecpg (PostgreSQL) 13.2
psql --version returns psql (PostgreSQL) 12.8
The program compiles fine and I am able to connect without issues, the way I know this is printf extracts the correct database name, and I've also run other SQL SELECTS to confirm the data.
However, as soon as I uncomment the int connect() function, even without using it, it is called 3 times before the actual program, and I do not know why. To be more precise, I see the letter A being printed 3 times. Additionally, printf no longer displays the correct name, instead dbname is empty.
I tried putting int connect() function into a separate connect.c file, then linking it together with this program through connect.h, and the result is the same.
If I put the contents of main() into connect(), and then call it, the process just hangs indefinitely.
Truly, I am at a loss, and I do not have even the slightest idea of where to begin, since this situation seems impossible. I checked the connector.c file that ECPG produces and there are no additional calls. Most references I can find online contain only main() function, and in rare cases where they do not, there is no mention of any remotely similar issue.
Any ideas as to what's going on?

OK, so it turns out the connect() function is used somewhere, since renaming it solved the issue. I was renaming it in the created connector.c file, which is how I missed this obvious solution.
Laurenz Albe said that he tried this on his end and everything is fine, which means it is somehow unique to my setup.

Related

Precompile embedded sql in c on ubuntu linux db2 does not work

I asked before but it looks like its not me, its the system..
My db2 installation completed with "minor errors" so maybe that is it.
I can't make out the error code explanations.
The content of the folder:
prog1.sqc sh.sh
I gave DBADM authority to instance user.
It should create bnd file on its own, correct?
Here is the report:
$ db2 precompile prog1.sqc bindfile
LINE MESSAGES FOR prog1.sqc
------ --------------------------------------------------------------------
SQL0060W The "C" precompiler is in progress.
SQL0031C File "/home/nikica/UCENJE/precompile/prog1.bnd"
could not be opened.
SQL0095N No bind file was created because of previous
errors.
SQL0091W Precompilation or binding was ended with "2"
errors and "0" warnings.
IBM support pages:
https://www.ibm.com/support/pages/running-db2look-db2-instance-user-fails-sql0031c-file-db2lkfunbnd-could-not-be-opened
EDIT: my sqc
#include <stdio.h>
#include <string.h>
#include <sqlca.h>
/* SQL includes */
EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION;
EXEC SQL END DECLARE SECTION;
int main()
{
// EXEC SQL CONNECT TO sample;
return (0);
}
RESOLVED with
Precompilation or binding was ended with "0"
errors and "0" warnings.
Thanks to mao
Did all the steps like 100 times before plus "su - root" in the beginning

Simple buffer overflow via xinetd

I'm trying to make a simple buffer overflow tutorial that runs the program below as a service on port 8000 via xinetd. Code was compiled using
gcc -o bof bof.c -fno-stack-protector
ubuntu has stack protection turned off as well.
Exploiting locally i.e
python -c ---snippet--- | ./bof
is successful and the hidden function was executed, displaying text file contents.
However, running it as a service and performing
python -c ---snippet--- | nc localhost 8000
returns nothing when exploiting. Am I missing something here?
#include <stdio.h>
void secret()
{
int c;
FILE *file;
file = fopen("congratulations.txt", "r");
if (file) {
while ((c= getc(file)) !=EOF)
putchar(c);
fclose(file);
}
void textdisplay()
{
char buffer[56];
scanf("%s", buffer);
printf("You entered: %s\n", buffer);
}
int main()
{
textdisplay();
return 0;
}
Output is buffered by default. To disable this you can do the following at the top of main:
setbuf(stdin, NULL);
This should fix your issue.
This is an issue that I am running into as well. Almost exactly the same.
However, here is one piece that I have found out that might be helpful to you. I believe the issue has something to do with xinetd not executing the binary as a terminal and having job control.
So what I did was to have xinetd do:
server = /usr/bin/python
server_args = /opt/shell.py
Then within the /opt/shell.py I had:
import pty
pty.spawn("/opt/oflow.elf")
/opt/oflow.elf being my overflowed binary
When I do this, I can actually send and receive data. Thats when I run the following command via netcat to try and overflow the service remotely:
**printf "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80AAAAAAAAAAAAAAAAAAAAAAAAABCDEFGHIJKLMNOPQ\x7c\xfc\xff\xbf" | nc 192.168.1.2 9000**
This does nothing. However, I test the local version and it works PERFECTLY. Works every time.
Not when its being wrapped in a python pty and xinetd.
When I run the xinetd pointing directly to /opt/oflow.elf, I get absolutely nothing back from netcat.
So that doesn't exactly answer your question but it should whittle it down for you.
UPDATED COMPLETE ANSWER:
I figured out why this wasnt working. No need to use python at all. After every printf statement you must also include:
fflush(stdout);
Otherwise, xinetd doesnt know to send the stdout.
You may also need to do this for stdin:
fflush(stdin);

C program exits giving error ORA-12162: TNS:net service name is incorrectly specified

I am working on a remote red-hat server and there I'm developing a c application to insert data in to a remote oracle database. So first i installed the OCI instant client rpm on the server and tried to compile a sample program. after certain linkages I could compile it. But then when I am going to run it. It exits giving an error saying
ORA-12162: TNS:net service name is incorrectly specified
The sample code I used is from the blog (refer to this code in case you need to clarify the things.where I’m quoting only few pieces to this post) René Nyffenegger's collection of things on the web
René Nyffenegger on Oracle
(refer to this code in case you need to clarify the things.where I’m quoting only few pieces to this post)
In the code I added some prints to check for the error And it seems like It gets stuck in the OCIServerAttach() function r gives a printed walue of -1
r=OCIServerAttach(srv, err, dbname, strlen(dbname), (ub4) OCI_DEFAULT);
printf("r value %d",r);
if (r != OCI_SUCCESS) {
checkerr(err, r);
goto clean_up;
}
Another point is that in the compilation process it gives a warning saying that a certain libry is not include. but the exicutable file is created. Here is the massage I get in the compilation process.
[laksithe#loancust ~]$ gcc -L$ORACLE_HOME/lib/ -L$ORACLE_HOME/rdbms/lib/ -o oci_test oci_test.o -L/usr/lib/oracle/12.1/client64/lib -lclntsh `cat $ORACLE_HOME/lib/sysliblist`
cat: /lib/sysliblist: No such file or directory
Going through the web I found that by creating a tnsnames.ora file with the connection details I could solve the problem. But even It didn't work for me. Here is the link for that blog blog
It has been a week since this error and I cold'nt solve it. could someone please help me.
connection string format I used is abc.ghi.com:1521/JKLMN
My recommendation is to bypass tnsnames completely. Oracle has always allowed you to put in the direct connection details, but EZConnect makes that even easier.
When you format your connection string, instead of listing the TNS name, use the actual connection properties in the following format:
servername:port/service name
For Example
MyOracle.MyCompany.Com:1521/SalesReporting
Your connection string might also require direct=true, but I'm honestly not sure.
I like the idea of tnsnames, but it's a double edged sword. When it works, it's great. When it doesn't, you want to throw something. With EZConnect, it always works.
By the way, if you don't know the properties of the three items above, find a machine that connect via tnsnames and:
tnsping <your TNS-named database>

Function XOpenDisplay with and without parameter

I have little issue with XOpenDisplay function. In school I can run program and it works good when using XOpenDisplay("ip:0"), but on my local machine in home when I run program (changed ip on current) got "Segmentation fault (core dumped)", but with empy string XOpenDisplay("") it works fine. I need to be able to use ip. Used host +, but nothing changes.
My system is Kubuntu 14.04.1: 3.16.0-30-generic #40~14.04.1-Ubuntu SMP Thu Jan 15 17:43:14 UTC 2015
Here is code of program:
#include <X11/Xlib.h>
#include <X11/X.h>
#include <stdio.h>
Display *mydisplay;
Window mywindow;
XSetWindowAttributes mywindowattributes;
XGCValues mygcvalues;
GC mygc;
Visual *myvisual;
int mydepth;
int myscreen;
Colormap mycolormap;
XColor mycolor,mycolor1,dummy;
int i;
main()
{
mydisplay = XOpenDisplay("192.168.0.12:0");
myscreen = DefaultScreen(mydisplay);
myvisual = DefaultVisual(mydisplay,myscreen);
mydepth = DefaultDepth(mydisplay,myscreen);
mywindowattributes.background_pixel = XWhitePixel(mydisplay,myscreen);
mywindowattributes.override_redirect = True;
mywindow = XCreateWindow(mydisplay,XRootWindow(mydisplay,myscreen),
0,0,500,500,10,mydepth,InputOutput,
myvisual,CWBackPixel|CWOverrideRedirect,
&mywindowattributes);
mycolormap = DefaultColormap(mydisplay,myscreen);
XAllocNamedColor(mydisplay,mycolormap,"cyan",&mycolor,&dummy);
XAllocNamedColor(mydisplay,mycolormap,"red",&mycolor1,&dummy);
XMapWindow(mydisplay,mywindow);
mygc = DefaultGC(mydisplay,myscreen);
XSetForeground(mydisplay,mygc,mycolor.pixel);
XFillRectangle(mydisplay,mywindow,mygc,100,100,300,300);
XSetForeground(mydisplay,mygc,mycolor1.pixel);
XSetFunction(mydisplay,mygc,GXcopy);
XSetLineAttributes(mydisplay,mygc,10,LineSolid,CapProjecting,JoinMiter);
XDrawLine(mydisplay,mywindow,mygc,100,100,400,400);
XDrawLine(mydisplay,mywindow,mygc,100,400,400,100);
XFlush(mydisplay);
sleep(10);
XCloseDisplay(mydisplay);
exit(0);
}
I can only guess that need to set something, but have no idea where is that option.
You shall always check whether functions returned successfully, or not. It is not a Haskell, where all the checking done for you by monad, it is C. As for your particular case, the problem is that the function XOpenDisplay fails and returns null for you. In the next line you're trying to use DefaultScreen with the result. The DefaultScreen is defined as
#define DefaultScreen(dpy) ((dpy)->default_screen)
I.e. it just a macro, which using the first argument as a pointer. In your case it does ((0)->default_screen), i.e. it dereferencing the null pointer, and that leads to the segfault you see.
Also, about the XOpenDisplay("192.168.0.12:0"); — you didn't mentioned that you're trying to connect to another PC, so, if it's the same computer where the app running, try to call the function as XOpenDisplay("127.0.0.1:0");
UPD: okay, I tried to run the code at my PC, and the function doesn't work for me too. To find the reason I started the code under strace app, and saw
…
connect(3, {sa_family=AF_INET, sin_port=htons(6000), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 ECONNREFUSED (Connection refused)
…
Aha! So, the app trying to connect to XServer, but Xserver refuses the connection. Actually, it have a security reason to disable it by default — so, that nobody would connect to your XServer from a network unless you specifically allowed it. For the function to work you need to launch your XServer with the option that allows such a connection. Right now DisplayManagers are the ones, who manages xsessions, so you need to set some option depending on your DM.
The solution for lightdm
Open the /etc/lightdm/lightdm.conf, and paste the line xserver-allow-tcp=true in the section [SeatDefaults](you will see it).
The solution for gdm
Edit the file /etc/gdm/gdm.schemas, you will find there something like
<schema>
<key>security/DisallowTCP</key>
<signature>b</signature>
<default>true</default>
</schema>
Change the true to false.

accessing sqlite with C program

Core dumped while running this program:
int main(void) {
sqlite3 *conn;
int error = 0;
error = sqlite3_open("cloud_db.sqlite3", &conn);
if (error) {
puts("Can not open database");
exit(0);
}
error = sqlite3_exec(conn,
"update server set servername=\'Laks\' where ipaddress=\'192.168.1.111\'",
0, 0, 0);
if (error) {
puts("Can not update table");
exit(0);
}
sqlite3_close(conn);
return 0;
}
I have tried accessing (select query) sqlite using C and it shows the contents - that's fine. How can I use queries like update? Above I'm trying to execute a query like:
update server set servername="Laks" where ipaddress="192.168.1.111";
running this query with in sqlite> works fine. How to execute (update query) it from C program?
Since you point out that the problem is there when the statement contains "servername=\'Laks\'" and leaves when you change that to "servername=Laks" I guess the backslashes cause the problem. You don't need backslashes to escape the apostrophe in string literals. Simply use "servername='Laks'". You escape quotes (") in string literals and apostrophes (') in character literals, but not vice versa.
You also need to add the semicolon (;) at the end of the query string: "whatever sql statement text;".
sharptooth is right on when he asks which statement leads to the core dump. Since you haven't answered, I'm thinking you may not know how to do that.
First off, make sure your program is compiled with debug symbols. Assuming you're using gcc, you do that by having -g on the command line.
Next, make sure your environment will write core files. Do this with the shell command ulimit -c unlimited (when running in sh, bash, etc.) or limit core unlimited (when running in csh).
Run the program and let it crash.
Next, bring up the core in gdb with gdb programname corename.
Finally, run the backtrace command in gdb to see where the crash was.

Resources