Can oracle read local files when only associated by secondary group? - oracle

I am trying to run a very simple python script from Oracle. Oracle is on the same linux box as the script. It opens a file and creates a checksum. It is triggered by a 'recon' user within oracle.
Running the script from within Oracle works fine as long as the file owner is 'oracle', or the group is 'oinstall' (oracle's default group), or the public is set to rx, the script works.
The problem is that we must use a different user:group, and we cannot use public permissions. We added the oracle user to the file's group.
uid=54321(oracle) gid=54321(oinstall) groups=54321(oinstall),202175(efs_data)
When running from within Oracle as we did before, it now fails, however, when sudo'ing into the oracle user and running the script directly, it works so we know the linux permissions are ok.
What could cause this? I guess Oracle is doing some other sort of access check overlaying the linux permissions, and this ignores the secondary groups and looks at gid only.
as 'recon' schema:
set serveroutput on size unlimited
declare
x number;
begin
x := run_cmd('/home/oracle/bin_dir/pytest.py');
dbms_output.put_line('return:' || x);
end;
run_cmd:
create or replace function RUN_CMD( p_cmd in varchar2) return number as
language java
name 'Util.RunThis(java.lang.String) return integer';
Util.RunThis:
import java.io.*;
import java.lang.*;
public class Util extends Object
{
public static int RunThis(java.lang.String args)
{
Runtime rt = Runtime.getRuntime();
int rc = -1;
try
{
Process p = rt.exec(args);
int bufSize = 4096;
BufferedInputStream bis =
new BufferedInputStream(p.getInputStream(), bufSize);
int len;
byte buffer[] = new byte[bufSize];
// Echo back what the program spit out
while ((len = bis.read(buffer, 0, bufSize)) != -1)
System.out.write(buffer, 0, len);
rc = p.waitFor();
}
catch (Exception e)
{
e.printStackTrace();
rc = -1;
}
finally
{
return rc;
}
}
}
/home/oracle/bin_dir/pytest.py:
#! /usr/bin/python -W ignore::DeprecationWarning
import paramiko
import logging
import datetime
import pwd
import md5
import os
def test_file_open(local_file):
print 'Trying to open: '+ local_file
logging.info('Trying to open: ' + local_file)
local_file_data = open(local_file, "rb").read()
checksum = md5.new(local_file_data).hexdigest()
return checksum
def main():
logging.basicConfig(filename='/mounts/users/dmz/pytest.log', level=logging.INFO)
logging.info('==========================================')
logging.info('START: ' + str(datetime.datetime.now()))
logging.info('getuid: ' + pwd.getpwuid( os.getuid() ).pw_name)
logging.info('geteuid: ' + pwd.getpwuid( os.geteuid() ).pw_name)
checksum = test_file_open('/test.txt')
print 'Success!, checksum: ' + checksum
logging.info('Success! checksum: ' + checksum)
logging.info('END: ' + str(datetime.datetime.now()))
if __name__ == '__main__':
main()
Output (with oracle as file owner):
-rwxrwx---. 1 oracle efs_data 0 Jun 7 19:56 /test.txt
INFO:root:==========================================
INFO:root:START: 2018-06-07 19:45:32.005429
INFO:root:getuid: oracle
INFO:root:geteuid: oracle
INFO:root:Trying to open: /test.txt
INFO:root:Success! checksum: 9f1e1404fd72b59121d45a8beb4dab5d
INFO:root:END: 2018-06-07 19:45:32.007078
Output (with permissions only via group association):
-rwxrwx---. 1 root efs_data 0 Jun 7 19:57 /test.txt
INFO:root:==========================================
INFO:root:START: 2018-06-07 19:44:15.748559
INFO:root:getuid: oracle
INFO:root:geteuid: oracle
INFO:root:Trying to open: /test.txt

I have a similar problem with DIRECTORY and external tables where linux group access is seemingly ignored. I was able to solve by using an acl and letting the oracle user have the rights it needs while letting the ownership of the file stay will another user.
ll test.txt
-rwx------. 1 lunc users 940 Jun 13 09:34 test.txt
setfacl -m u:oracle:rwx test.txt
getfacl test.txt
# file: test.txt
# owner: lunc
# group: users
user::rwx
user:oracle:rwx
group::---
mask::rwx
other::---
ll test.txt
-rwxrwx---+ 1 lunc users 940 Jun 13 09:34 test.txt
Oracle accepts this (at least for external tables) and is able to access the file.

Related

How to make a basic protobuf program work using Python as on Google's Developer's Website?

I am following the tutorial of protobuf using Python (there isn't one for JavaScript). It doesn't work... and I think it might be outdated as proto2 and as a Python 2 program. How to make it work?
So I started with creating a file address.proto:
syntax = "proto2";
package tutorial;
message Person {
optional string name = 1;
optional int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
optional string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phones = 4;
}
message AddressBook {
repeated Person people = 1;
}
And then I installed protoc on the Mac
And then I created two folders In and Out, and moved address.proto into In, and run:
protoc -I=In --python_out=Out In/address.proto
and then there is a file created: Out/address_pb2.py, and I went to Out, and added the file run.py:
#! /usr/bin/python
import addressbook_pb2
import sys
# This function fills in a Person message based on user input.
def PromptForAddress(person):
person.id = int(raw_input("Enter person ID number: "))
person.name = raw_input("Enter name: ")
email = raw_input("Enter email address (blank for none): ")
if email != "":
person.email = email
while True:
number = raw_input("Enter a phone number (or leave blank to finish): ")
if number == "":
break
phone_number = person.phones.add()
phone_number.number = number
type = raw_input("Is this a mobile, home, or work phone? ")
if type == "mobile":
phone_number.type = addressbook_pb2.Person.PhoneType.MOBILE
elif type == "home":
phone_number.type = addressbook_pb2.Person.PhoneType.HOME
elif type == "work":
phone_number.type = addressbook_pb2.Person.PhoneType.WORK
else:
print "Unknown phone type; leaving as default value."
# Main procedure: Reads the entire address book from a file,
# adds one person based on user input, then writes it back out to the same
# file.
if len(sys.argv) != 2:
print "Usage:", sys.argv[0], "ADDRESS_BOOK_FILE"
sys.exit(-1)
address_book = addressbook_pb2.AddressBook()
# Read the existing address book.
try:
f = open(sys.argv[1], "rb")
address_book.ParseFromString(f.read())
f.close()
except IOError:
print sys.argv[1] + ": Could not open file. Creating a new one."
# Add an address.
PromptForAddress(address_book.people.add())
# Write the new address book back to disk.
f = open(sys.argv[1], "wb")
f.write(address_book.SerializeToString())
f.close()
and then I installed and ran:
pip3 install protobuf --user
pip3 install google --user
pip3 install google-cloud --user
python3 run.py addr.dat
and it looks like I have to convert the code in run.py from print 123 to print(123) because it is Python3, not Python2. And it gave:
Traceback (most recent call last):
File "run.py", line 40, in <module>
address_book = addressbook_pb2.AddressBook()
NameError: name 'addressbook_pb2' is not defined
I also copied the file addressbook_pb2.py to foo.py, and then use import foo instead, and it gave:
Traceback (most recent call last):
File "run.py", line 3, in <module>
import foo
File "/Users/peter/code/TryProtobuf_Unzipped/TryIt/Out/foo.py", line 34, in <module>
_descriptor.EnumValueDescriptor(
File "/Users/peter/Library/Python/3.8/lib/python/site-packages/google/protobuf/descriptor.py", line 732, in __new__
_message.Message._CheckCalledFromGeneratedFile()
TypeError: Descriptors should not be created directly, but only retrieved from their parent.
How can it be made to work?
Your address.proto declares the tutorial package. I think you can access it via address_book = tutorial.addressbook_pb2.AddressBook()
As for why it broke after renaming the file to foo.py, I have no idea.

GRANT support in MS ACCESS

ALL,
Does GRANT-ing permissions supported in MS ACCESS?
I am connecting to accdb with ODBC driver from C++ app and trying to issue a GRANT command, but getting an error saying expecting DELETE, INSERT, PROCEDURE, SELECT or UPDATE.
It is on Windows 8.1 with MSVC 2017 Community.
The command I'm trying is:
GRANT SELECT ON MSysObjects TO Admin;
TIA!!
void uc_to_str_cpy(SQLWCHAR *dest, const std::wstring &src)
{
const wchar_t *temp = src.c_str();
while( *dest )
{
dest++;
}
while( *temp )
{
*dest = *temp;
dest++;
temp++;
}
*dest++ = 0;
*dest = 0;
}
std::wstring query8 = L"GRANT SELECT ON MSysObjects TO Admin;";
query = new SQLWCHAR[query8.length() + 2];
memset( query, '\0', query8.length() + 2 );
uc_to_str_cpy( query, query8 );
ret = SQLExecDirect( m_hstmt, query, SQL_NTS );
delete[] query;
query = NULL;
if( ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO )
{
GetErrorMessage( errorMsg, 1 );
result = 1;
}
Grant does exist for Access. In most cases you can query against MSYSobjects. However, you could try several things:
First, try running your program (.exe) with elevated rights (right click and run as admin).
next up. You don't mention if this is JET (mdb) format, or is ACE (accdb format).
HOWEVER - using ODBC (as opposed to the oleDB driver), to my knowledge DOES NOT support Grant. So, quite sure you are out of luck.
You could I suppose consider creating a ADO object.
I find that EVEN inside of Access, if I use the built in ADO object, then grant will work.
but if I use a straight DAO object, then it does not work.
and for ODBC? Well, I find that grant does not seem to be supported - so, this looks like ODBC does NOT support the grant.
Also, use of GRANT in most cases also means that the connection string needs to include the work group file (it is by default automatic opened - even with ODBC, but using oleDB against such a database (from .net), I again find that GRANT does execute with oleDB - but gives an error message about the workgroup file having not been specified.
However, with ODBC - I get a error - syntax. So, at this point? ODBC does not support the grant DDL.

Cannot connect to Oracle 19 with unixODBC

I'm trying to connect to an Oracle 19 database using unixODBC 2.3.7.
I'm using the Oracle Developer Days VirtualBox VM.
When trying to troubleshoot via isql I always get this error:
# isql -v -3 oracledsn
[HY000][unixODBC][Oracle][ODBC][Ora]ORA-12545: Connect failed because target host or object does not exist
[ISQL]ERROR: Could not SQLConnect
Sadly I can't reproduce it now, but when last trying it I always had
[IM004][unixODBC][Driver Manager]Driver's SQLAllocHandle on SQL_HANDLE_HENV failed
[ISQL]ERROR: Could not SQLConnect
This is the same error message I get from my (proprietary) C++ code, so I'm pretty sure the problem is just the connection settings.
I have checked https://www.connectionstrings.com/oracle/ but none of the combinations work.
Here are all my config settings:
# odbcinst -j -130-
unixODBC 2.3.7
DRIVERS............: /usr/local/etc/odbcinst.ini
SYSTEM DATA SOURCES: /usr/local/etc/odbc.ini
FILE DATA SOURCES..: /usr/local/etc/ODBCDataSources
USER DATA SOURCES..: /home/florian/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8
# cat /usr/local/etc/odbcinst.ini
[oraclex]
Description = Oracle ODBC driver for Oracle 19
Driver = /mnt/libsqora.so.19.1
Setup =
FileUsage =
CPTimeout =
CPReuse =
Driver Logging = 7
[ODBC]
Trace = Yes
TraceFile = /tmp/odbc.log
ForceTrace = Yes
Pooling = No
DEBUG = 1
# cat ~/.odbc.ini
[oracledsn]
Driver = oraclex
Server = 10.1.6.19
Port = 1521
Uid = system
Pwd = oracle
Database = orclcdb/orcl/"<empty>"
ORA-12545: Connect failed because target host or object does not exist
I also tried ServerName
ServerName = //10.1.6.19/orclcdb or //10.1.6.19/orcl
[28000][unixODBC][Oracle][ODBC][Ora]ORA-01017: invalid username/password; logon denied
Here's the /tmp/odbc.log:
[ODBC][18832][1564563250.044774][__handles.c][460]
Exit:[SQL_SUCCESS]
Environment = 0x1fd7780
[ODBC][18832][1564563250.044854][SQLSetEnvAttr.c][189]
Entry:
Environment = 0x1fd7780
Attribute = SQL_ATTR_ODBC_VERSION
Value = 0x3
StrLen = 0
[ODBC][18832][1564563250.044886][SQLSetEnvAttr.c][381]
Exit:[SQL_SUCCESS]
[ODBC][18832][1564563250.044914][SQLAllocHandle.c][377]
Entry:
Handle Type = 2
Input Handle = 0x1fd7780
[ODBC][18832][1564563250.044944][SQLAllocHandle.c][493]
Exit:[SQL_SUCCESS]
Output Handle = 0x1fd8090
[ODBC][18832][1564563250.044983][SQLConnect.c][3721]
Entry:
Connection = 0x1fd8090
Server Name = [oracledsn][length = 9 (SQL_NTS)]
User Name = [NULL]
Authentication = [NULL]
UNICODE Using encoding ASCII 'ANSI_X3.4-1968' and UNICODE 'UCS-2LE'
DIAG [HY000] [Oracle][ODBC][Ora]ORA-12545: Connect failed because target host or object does not exist
[ODBC][18832][1564563250.082037][SQLConnect.c][4244]
Exit:[SQL_ERROR]
[ODBC][18832][1564563250.082070][SQLGetDiagRec.c][677]
Entry:
Connection = 0x1fd8090
Rec Number = 1
SQLState = 0x7fffeabcac60
Native = 0x7fffeabcac5c
Message Text = 0x7fffeabcac70
Buffer Length = 500
Text Len Ptr = 0x7fffeabcac5a
[ODBC][18832][1564563250.082092][SQLGetDiagRec.c][726]
Exit:[SQL_SUCCESS]
SQLState = HY000
Native = 0x7fffeabcac5c -> 12545
Message Text = [[unixODBC][Oracle][ODBC][Ora]ORA-12545: Connect failed because target host or object does not exist
I've also been trying out this C code from https://www.easysoft.com/developer/languages/c/odbc_tutorial.html#connect_full - basically the same result.
# cat test2.c
# compile with gcc -I ../include test2.c -o test2 -lodbc
#include <stdio.h>
#include <sql.h>
#include <sqlext.h>
/*
* see Retrieving ODBC Diagnostics
* for a definition of extract_error().
*/
static void extract_error(
char *fn,
SQLHANDLE handle,
SQLSMALLINT type);
main() {
SQLHENV env;
SQLHDBC dbc;
SQLHSTMT stmt;
SQLRETURN ret; /* ODBC API return status */
SQLCHAR outstr[1024];
SQLSMALLINT outstrlen;
/* Allocate an environment handle */
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
/* We want ODBC 3 support */
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
/* Allocate a connection handle */
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
/* Connect to the DSN mydsn */
ret = SQLDriverConnect(dbc, NULL, "DSN=oracledsn;", SQL_NTS,
outstr, sizeof(outstr), &outstrlen,
SQL_DRIVER_COMPLETE);
if (SQL_SUCCEEDED(ret)) {
printf("Connected\n");
printf("Returned connection string was:\n\t%s\n", outstr);
if (ret == SQL_SUCCESS_WITH_INFO) {
printf("Driver reported the following diagnostics\n");
//extract_error("SQLDriverConnect", dbc, SQL_HANDLE_DBC);
}
SQLDisconnect(dbc); /* disconnect from driver */
} else {
fprintf(stderr, "Failed to connect\n");
//extract_error("SQLDriverConnect", dbc, SQL_HANDLE_DBC);
}
/* free up allocated handles */
SQLFreeHandle(SQL_HANDLE_DBC, dbc);
SQLFreeHandle(SQL_HANDLE_ENV, env);
}
As another point reference I can connect to said Oracle Dev VM with sqlplus from another machine like this:
./sqlplus sys/oracle#10.1.6.19/orclcdb as sysdba
SQL>
./sqlplus system/oracle#10.1.6.19/orclcdb
SQL>
On the VM I have a file /u01/app/oracle/product/version/db_1/network/admin/tnsnames.ora but I am not completely sure if I also need one on the client?
ORCLCDB=localhost:1521/orclcdb
ORCL=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 0.0.0.0)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl)
)
)
I finally found the solution, although this is for 12.2.0.1 and not 19
# cat .odbc.ini
[oracledsn]
Driver=oracle
UID=system
PWD=oracle
DBQ=192.168.178.32:1521/ORCLCDB
ServerName=//192.168.178.32:1521/ORCLCDB
cat /usr/local/etc/odbcinst.ini
[oracle]
Description = foo
Driver = /mnt/libsqora.so.19.1
Driver Logging = 7
UsageCount=1
FileUsage=1
[ODBC]
Trace = Yes
TraceFile = /tmp/odbc.log
ForceTrace = Yes
Pooling = No
# LD_LIBRARY_PATH=. isql -v oracledsn system oracle
+---------------------------------------+
| Connected! |
I have no Oracle-specific environment variables set, but if it works if I take the value of ServerName verbatim for TWO_TASK.
I had success with oracle 19c, with one minor change here - remove the "//" from ServerName i.e.
ServerName=192.168.178.32:1521/ORCLCDB

How to interact with a running python script

As a start ive got a basic script which reads local unix syslog (/var/log/messages)
i want to build a tool which opens a socket (19999) locally and allows admin commands to be sent / processed.
As something i can build on basically i want to have the script on start up do the follow :
- open port 19999 locally
- start reading syslog storing "line" as the last line it has processed.
- when admin command of "printline" is seen print last known variable for "line"
Ive got basics done i think (script is below) where i have it open the relevant ports and it prints the commands sent to it from another client tool however it never starts to read the syslog.
#!/usr/bin/python
import socket
import subprocess
import sys
import time
from threading import Thread
MAX_LENGTH = 4096
def handle(clientsocket):
while 1:
buf = clientsocket.recv(MAX_LENGTH)
if buf == '': return #client terminated connection
print buf
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
PORT = 19999
HOST = '127.0.0.1'
serversocket.bind((HOST, PORT))
serversocket.listen(10)
while 1:
#accept connections from outside
(clientsocket, address) = serversocket.accept()
ct = Thread(target=handle, args=(clientsocket,))
ct.start()
def follow(thefile):
thefile.seek(0,2)
while True:
line = thefile.readline()
if not line:
time.sleep(0.1)
continue
yield line
if __name__ == '__main__':
logfile = open("/capture/log/uifitz/messages","r")
loglines = follow(logfile)
for line in loglines:
print line,
Any help would be appreciated. Python 2.6 by the way.

OSX: shm_open returns ENAMETOOLONG

I am trying atm to create a shared memory file for my process. The filename constists of several parts to identify the process the SHM belongs to and whats its content. An example would be:
shm_pl_dev_system_25077
I create all the files in a directory I created in /tmp where I have full write and read permissions.
So the complete Path would be:
/tmp/pl_dev/shm_pl_dev_system_25077
I create several files there, some fifo pipes and other stuff and also the shm. The only Problem I get is that shm_open will always return the errno 63 (ENAMETOOLONG).
Can you tell me what the issue here is?
Here is the code:
handle_ = ::shm_open(shm_name.get(), O_RDWR, 0755);
if (handle_ == -1 && errno == ENOENT)
{
// SHM does not yet exists, so create it!
handle_ = ::shm_open(shm_name.get(), O_CREAT | O_RDWR, 0755);
if (handle_ != -1) {
created_ = true;
}
else
{
if (!silent_)
{
log.error("Couldn't create the SHM (%d).", errno);
}
return false;
}
}
Okay. As it seems OSX is very limited in the filename of SHMs... The maximum length for a filename currently is 31 chars per section (see PSHMNAMELENGTH in /usr/include/sys/posix_shm.h)

Resources