Using Oracle Wallet authentication from OCI - c++

I'm wondering if anyone has any success in writing a C/C++ application that uses the Oracle OCI API and authenticates using an Oracle wallet.
I have successfully created the wallet using mkstore and have stored the credentials in it. My tnsnames.ora and sqlnames.ora files have the correct contents, and my ORACLE_HOME and ORACLE_SID environment variables are set correctly as I can use sqlplus /#XE to authenticate a sqlplus session successfully using it.
Within the same terminal I have created a simple C program that allocates the OCIEnv, OCIServer, OCIError and OCIsvcCtx handles and calls OCIEnvCreate(). That all works fine.
I then try calling any one of the "connect" functions, such as OCILogon (also tried OCILogon2 and OCISessionPoolCreate as well), and I always get "invalid username/password". I am trying to call it as I see it defined for my invocation of sqlplus i.e null username and password with 0 length, and dbname of "XE" with appropriate length. (I've also tried dbnames of "#XE" and "/#XE" for completeness)
I see there is a security API for opening wallets and interrogating their contents, but I assumed this was application that want to interact directly with the contents of the wallet (i.e add/remove credentials etc). Maybe this is an incorrect assumption on my part...
There is precious little info out there as to how to do this programatically, so if anyone has any pointers, or a small working example that can simply connect to the database in this way I would be very grateful.
Many thanks
Ben

That's what I found also, there is precious little info out there on how to do this programatically. I finally figured it out by experiementing. It seems you have your sqlnet.ora and tnsnames.ora files set up correctly, so all you need to do is modify your code for attaching to the server and starting the session.
When attaching to the server, your dblink text string should be your connect string in tnsnames.ora for your oracle wallet entry. In your case "XE".
OCIServerAttach (OCIServer *srvhp,
OCIError *errhp,
CONST text *dblink,
sb4 dblink_len,
ub4 mode )
When beginning your session, credt should be set to OCI_CRED_EXT. This validates the credentials externally and since SQLNET.WALLET_OVERRIDE = TRUE is in sqlnet.ora, It uses oracle wallet to validate the connect string. Also, having credt set to OCI_CRED_EXT ignores the username and password session attributes.
OCISessionBegin (OCISvcCtx *svchp,
OCIError *errhp,
OCISession *usrhp,
ub4 credt,
ub4 mode );
That's it. I didn't use OCILogin or OCISessionPoolCreate in my code.
Good luck,
David M.

Related

Zend framework ACL fails for the first time to switch the server

Hi guys!
I'm not native to English, so I'll appreciate if you correct my sentence!
To explain my issue, here is our development environment.
language : PHP7.3.11
framework : Zend framework v3.3.11
server : aws ec2×4
server OS : Amazonlinux 2
redis was enabled, there are two project like a-project/ec2×2(a-ec2) b-project/ec2×2(b-ec2)
the only differences between a-ec2 and b-ec2 are source code, the other setting like nginx, php-fpm, redis also DB setting are same.
if I lack some info, please let me know
When we joint these project, the problems happen.
After logged in our service, the zend works oddly.
the loginAction is on the a-ec2, we can successfully login with that.
And we save that session information on redis, and it works normally.
But only for the first time that we switch the server from a-ec2 to b-ec2, zend acl error has occur.
We use isAllowed function for checking the privilege for whether the user has enough privilege to access certain service.
The isAllowd function which located at line 827, /library/ZendAcl.php return false for the first time.
Then, we reload the page, the isAllowed function return true so that we can access to the service.
In detail, something went wrong around &_getRules function which is at line 1161, which is used _getRuleType function.
In those process, somehow one of the array contain "TYPE_DENY".
But when try to reload(ctrl + f5), that value turn into "TYPE_ALLOW".
How can this happen?
And how to fix this?
We are trying to figure this out like 2 weeks or more...
Thanks in advance!!
[update]
we found that this method which is written in under doesn't work well, so that we can't get $auth properly.
The $auth return "".
self::$_auth = $auth = Zend_Auth::getInstance()->getStorage()->read();
[update 2]
we might solve this issue, so I'll leave our solution.
we use
Zend_Auth::getInstance()->getStorage()->read()
to get $auth from session.
But for the first time, the session information which has saved at a-ec2 can't read at b-ec2.
So, we decided to use session information at redis, so we changed method to get $auth like
require_once 'Zend/Session.php';
Zend_Session::start();
self::$_auth = $auth = Common_Model_Redis::get();
start the session before connect to the redis server and just get session information form it!
I hope this will work you too!

Whats the most secure way I can use python-ldap in my script to connect to my ldap server?

I have a script that is using the python-ldap module.
Here is my basic code that makes a connection to my ldap server:
server = 'ldap://example.com'
dn = 'uid=user1,cn=users,cn=accounts,dc=example,dc=com'
pw = "password!"
con = ldap.initialize(server)
con.start_tls_s()
con.simple_bind_s(dn,pw)
This works...but does the actual literal password have to be stored in the variable pw?? it seems like a bad idea to have a password stored right there in a script.
Is there a way to make a secure connection to my ldap server without needing to store my actual password in the script??
Placing the password in a separate file with restricted permissions is pretty much it. You can for example source that file from the main script:
. /usr/local/etc/secret-password-here
You could also restrict the permissions of the main script so that only authorized persons can execute it, but it's probably better to do as you suggest and store only the password itself in a restricted file. That way you can allow inspection of the code itself (without sensitive secrets), version-control and copy around the script more easily, etc...

error 5 when starting a service

i created a windows service in c++ and when i try start the service i get the message error 5: access denied.
my user account is set to admin and i even tried using the default admin account on the computer and it still doesn't work.
i can install/uninstall the service through the cmd without problems but i can't start the service
the code isn't the problem here its the user account. any suggestions on how to fix this?
"Running a service" is not simply "starting a program on my desktop". It does not necessarily run as "you".
The service is detached from any desktops and it actually ignores your user account. The service will have its own account/password configuration stored in the OS and when you run it, you only order it to start up. It will startup on its own user account. If you have put your .exe/.dll files in some protected folder, and if you have not configured neither the accessrights to that files nor user-pass for the service, then there's great odds that the service tries to run at default service user account like 'LocalService' or 'NetworkService' and that it simply cannot touch the files.
If you installed the service properly, go to ControlPanel - AdministrativeTools - Services, find your service and check the (if I remember well) second tab and verify that the username presented here has access to the files that are tried to be loaded and run. If the username is wrong, correct it. If you don't care about the username, then just peek that name and set accessrights on the folder and/or files such that at least both "read directry contents" and "read" and "execute" are available for that-username-the-service-tries-to-run-as.

How to add software update subscription

We want to add auto-update or update notification to our products (C++).
Update should be subscription-based:
user buys subscription for 1 year of updates
when subscription expires, no more updates are available.
Can someone suggest software or provider for implementing such a service?
I found a few examples of auto-update but they all are unlimited in time.
This service must be limited on per-user basis and allow extensions.
What you would need, in terms of ingredients, would be:
a method to download the updates - I would suggest HTTP(S) for that
a method to encode the license, including what kind of updates you're entitled to and how long you're entitled to it. Ideally, this would be opaque to the user but easily verifiable on both ends (so an erroneous entry can be notified to the user without having to contact the server)
an easy way to know whether updates are available, and perhaps when to check again
What I would suggest would be to define a simple XML over HTTP service using an embeddable HTTP client, such as (shameless plug) Arachnida, with a simple API - something like:
class UpdateAgent
{
/* boilerplate */
public :
/* set the key to use. Throws an InvalidKey exception if not valid
* validity is checked locally - no HTTP queries are used.
* Key may have been invalidated on the server without notification
* at this point */
void setKey(const std::string &key);
// Get the key currently set
std::string getKey() const;
/* using a synchronous HTTPS query, check with the server if updates are
* available for the current key. Throws on error: one of the QueryError
* subclasses if there has been a query error, or InvalidKey is the
* key is either not set or is not valid (i.e. invalidated server-side) */
bool isUpdateAvailable() const;
/* etc. */
};
They key itself would, as seen above, be a string that, through its encoding, would contain some kind of information as to its validity - e.g. some kind of CRC to know whether the entered string is valid. The rest of the key - including its expiration date - could be managed server-side, although expiration information could also be encoded in the key itself (but that would mean changing the key if the user extends the license).
As for the server-side, when presented with a key and a request for an update, the server would
check the validity of the key
check whether any updates are available for the software the key is for (information that may or may not be part of the key itself, depending on whether you want to manage it in a database or want it to be part of the license key)
copy or hardlink the file into a place it can be downloaded, with a unique and hard-to-guess name
provide the URL for download to the client - e.g. in an XML stream returned for the HTTP request
start a time-out to remove the file after it hasn't been downloaded for N seconds/minutes/hours
remove the file once it has been downloaded by the client
If a download fails, it can be restarted or asked for again. If you want to charge for individual downloads, you'd need the client to confirm a successful download - or report an error on failure - so you don't count individual downloads twice.
Of course, all this is off the top of my head - there might be some details I haven't thought of here. Each of the ingredients are pretty easy to come by. An open source version of Arachnida is available on SourceForge and I have some code to encode license keys if you need it (used it for another of my products), but I'm sure that you can write that if you don't want to use mine.
A few things you might want to think of are secure authentication of your clients - so they don't share license keys - securing your HTTP connection so you don't end up publishing your updates to the world, etc. Neither the server nor the client need be very complicated to implement, as most of the building blocks already exist.
HTH
rlc

Exchange Web Services, try to use ExchangeImpersonationType

I am trying to use EWS, first time trying to use the ExchangeServiceBinding. The code I am using is below:
_service = new ExchangeServiceBinding();
//_service.Credentials = new NetworkCredential(userName, userPassword, this.Domain);
_service.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
_service.Url = this.ServiceURL;
ExchangeImpersonationType ei = new ExchangeImpersonationType();
ConnectingSIDType sid = new ConnectingSIDType();
sid.PrimarySmtpAddress = this.ExchangeAccount;
ei.ConnectingSID = sid;
_service.ExchangeImpersonation = ei;
The application is an aspnet 3.5 trying to create a task using EWS. I have tried to use impersonation because I will not know the logon user's domain password, so I thought impersonation would be the best fit. Any thoughts on how I can utilize impersonation? Am I setting this correctly, I get an error while trying to run my application. I also tried without impersonation just to try to see if I can create a task, no luck either. Any help would be appreciated. Thanks.
Without broader context of your code snip, I can't tell for sure what's wrong, but here are a few things you might find useful...
You mention you had trouble connecting without impersonation.
I'm assuming you are using Exchange Server 2007 SP1, yes?
Do you have a mailbox for which you do know the username and password? If so, consider trying to connect to that mailbox, just to see if you can send an email or query for inbox count. That will help verify your connection at least.
As to exchange impersonation,
have the permissions been set on the Client Access Server (CAS) to enable impersonation?
Have the permissions been set on either the mailbox or mailbox database (containing the mailbox you are attempting to access)?
are you in a cross-forest scenario that requires additional trust relationships?
If not, that might explain why you cannot connect.
Some links you might find useful
Configuring (http://msdn.microsoft.com/en-us/library/bb204095.aspx)
Using Exchange impersonation (http://msdn.microsoft.com/en-us/library/bb204088.aspx)
Access multiple resource mailboxes (http://msexchangeteam.com/archive/2007/12/13/447731.aspx)