Change file owner in Windows - c

Is there an API in Windows similar to Linux's chown?

Taken from here: http://www.perlmonks.org/?node_id=70562
// #includes omitted for the sake of sanity
HANDLE token;
char *filename = "somefile.txt";
char *newuser = "someuser";
DWORD len;
PSECURITY_DESCRIPTOR security = NULL;
PSID sidPtr = NULL;
int retValue = 1;
// Get the privileges you need
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) {
SetPrivilege(token, "SeTakeOwnershipPrivilege", 1);
SetPrivilege(token, "SeSecurityPrivilege", 1);
SetPrivilege(token, "SeBackupPrivilege", 1);
SetPrivilege(token, "SeRestorePrivilege", 1);
} else retValue = 0;
// Create the security descriptor
if (retValue) {
GetFileSecurity(filename, OWNER_SECURITY_INFORMATION, security, 0, &len);
security = (PSECURITY_DESCRIPTOR)malloc(len);
if (!InitializeSecurityDescriptor(security, SECURITY_DESCRIPTOR_REVISION))
retValue = 0;
}
// Get the sid for the username
if (retValue) {
char domainbuf[4096];
DWORD sidSize = 0;
DWORD bufSize = 4096;
SID_NAME_USE sidUse;
LookupAccountName(NULL, newuser, sidPtr, &sidSize, domainbuf, &bufSize, &sidUse);
sid = (PSID)malloc(sidSize);
if (!LookupAccountName(NULL, string, (PSID)sid, &sidSize, domainbuf, &bufSize, &sidUse))
retValue = 0;
}
}
// Set the sid to be the new owner
if (retValue && !SetSecurityDescriptorOwner(security, sidPtr, 0))
retValue = 0;
// Save the security descriptor
if (retValue)
retValue = SetFileSecurity(filename, OWNER_SECURITY_INFORMATION, security);
if (security) free(security);
if (sid) free(sid);
return retValue;
`

You might find the cacls or icacls commands useful... They're not exactly straightforward to use though
Can you provide a bit more information on what you're trying to do?

Related

Copy TCHAR* string from other thread

I want to copy data from another thread to struct and print. _tpintf() doesnt show russian letters corret.
in concole I see this, but I expect to see "IN THREAD текст клиент1". Please explain why tchar doesnt work? Also I noticed that if I use _tcprintf, "клиент1" shows correct, but "текст" become wrong
Code of thread function which tries to copy data from another
static DWORD WINAPI StdinInfo(LPVOID param)
{
struct msg msg;
TCHAR buf[1280] = { 0 };
parameters* p = (parameters*)param;
while (TRUE)
{
_fgetts(buf, 1280, stdin);
while (_tcslen(buf) > 0 && buf[_tcslen(buf) - 1] == TEXT('\n'))
buf[_tcslen(buf) - 1] = TEXT('\0');
buf[128] = TEXT('\0');
if (!_tcscmp(buf, TEXT("stop")))
{
//printf("Terminating...\n");
msg.isEmpty = 0;
msg.type = STOP;
_tcscpy(msg.message, buf);
_tcscpy(msg.nickName, p->nickName);
SendMessage(p, &msg);
break;
}
else if (!_tcscmp(buf, TEXT("exit")))
{
msg.isEmpty = 0;
msg.type = DISCONNECT;
_tcscpy(msg.message, buf);
_tcscpy(msg.nickName, p->nickName);
SendMessage(p, &msg);
break;
}
msg.isEmpty = 0;
msg.type = MESSAGE;
_tcscpy(msg.message, buf);
_tcscpy(msg.nickName, p->nickName);
_tprintf(TEXT(" IN TREAD %s %s\n"), msg.message, p->nickName);
SendMessage(p, &msg);
}
return 0;
}

How to get the product version from an msi file, without installing the msi?

I am looking for a C API that gets an msi path, and returns the product version (major and minor), without installing the API.
Thanks,
Eitan
I wouldn't use the open package thing - this is a static database so MsiOpenDatabase and SQL is the way to go. Missing some includes but this works fine:
#include "stdafx.h"
UINT GetProperty (MSIHANDLE dbHand, LPCTSTR propname, LPTSTR strVal)
{
PMSIHANDLE viewH = NULL;
WCHAR qry [100] = {0};
StringCchCat (qry, 100, L"Select `Value` from `Property` where `Property`='" );
StringCchCat (qry, 100, propname);
StringCchCat (qry, 100, L"'");
UINT res = MsiDatabaseOpenView (dbHand, qry, &viewH);
if (ERROR_SUCCESS!=res)
return res;
res = MsiViewExecute (viewH, 0);
if (ERROR_SUCCESS!=res)
{
MsiCloseHandle (viewH);
return res;
}
PMSIHANDLE recH=NULL;
res = MsiViewFetch (viewH, &recH);
if (ERROR_SUCCESS!=res)
{
MsiCloseHandle (viewH);
return res;
}
WCHAR buff [50] = {0};
DWORD dwlen = 50;
res = MsiRecordGetString (recH, 1, buff, &dwlen);
if (ERROR_SUCCESS!=res)
{
MsiCloseHandle (viewH);
MsiCloseHandle (recH);
return res;
}
StringCchCopy (strVal, dwlen+1, buff);
MsiViewClose (viewH);
MsiCloseHandle (recH);
return (ERROR_SUCCESS);
}
int _tmain(int argc, _TCHAR* argv[])
{
PMSIHANDLE dbH=NULL;
UINT res = MsiOpenDatabase (L"C:\\Phil\\MyDD\\Samples Setup\\GetMsiProperty\\Set2.msi", MSIDBOPEN_READONLY, &dbH);
WCHAR pversion [512] = {0};
res = GetProperty (dbH, L"ProductVersion", pversion);
WCHAR ubuff [50] = {0};
res = GetProperty(dbH, L"UpgradeCode", ubuff);
WCHAR pbuff [50] = {0};
res = GetProperty(dbH, L"ProductCode", pbuff);
WCHAR prodName [512] = {0};
res = GetProperty (dbH, L"ProductName", prodName);
WCHAR prodLang [512] = {0};
res = GetProperty (dbH, L"ProductLanguage", prodLang);
return 0;
}
MsiGetFileVersion() reads the version information from normal files (exe, dll, etc), not the product version from the MSI database.
To get the product version from inside an MSI you could use MsiOpenPackage to get a handle to the MSI and then call MsiGetProductProperty with that handle, asking for the ProductVersion property.
CoInitialize(NULL);
MSIHANDLE hPackage = NULL;
UINT retVal = MsiOpenPackage(_T("TortoiseSVN-1.8.10.26129-x64-svn-1.8.11.msi"), &hPackage);
if (retVal != ERROR_SUCCESS)
{
return retVal;
}
TCHAR versionBuf[64] = { 0 };
DWORD versionBufSize = sizeof(versionBuf) / sizeof(versionBuf[0]);
MsiGetProductProperty(hPackage, _T("ProductVersion"), versionBuf, &versionBufSize);
MsiCloseHandle(hPackage);

How to check if pid belongs to current user session?

I can get the list of running process from the this source code on mac.
Now, I want to filter these processes for different users or at least for current user session.
You can just extend your code like this..
kinfo_proc *mylist;
size_t mycount = 0;
mylist = (kinfo_proc *)malloc(sizeof(kinfo_proc));
GetBSDProcessList(&mylist, &mycount);
char *user = getenv("USER");
for (int i = 0; i < mycount; i++)
{
uid_t uid = mylist[i].kp_eproc.e_pcred.p_ruid;
struct passwd * pwd = getpwuid(uid);
char * username = pwd->pw_name;
if(strcmp(username, user) == 0)
{
printf(" %d - %s \n", mylist[i].kp_proc.p_pid, mylist[i].kp_proc.p_comm);
}
}
To be more precise you can get username buy this technique
SCDynamicStoreRef store;
store = SCDynamicStoreCreate(NULL, CFSTR("com.apple.dts.ConsoleUser"), NULL, NULL);
CFStringRef currentConsoleUser = CopyCurrentConsoleUsername(store);
const int kBufferSize = 256;
char logedinusername[kBufferSize];
CFStringGetCString(currentConsoleUser,logedinusername,kBufferSize,kCFStringEncodingMacRoman);
as getenv("USER"); may not work if you are running as root user and want logged in user.

Read certificate files from memory instead of a file using OpenSSL

I have a server which would listen on HTTPS using OpenSSL. For this, I have to provide the certificate to use. However, the current implementation uses a filename to be provided to the OpenSSL API.
I want the certificate information to be read from memory, so that I don't have to ship the certificate file opening. I tried to google, but I didn't come up with any options.
Is is possible? If so, how do I read certificate files from memory instead of a file using OpenSSL?
EDIT: The following was moved from the comments to the question.
// CURRENT
void start_server()
{
const char *fileName = "cert_and_key.pem";
set_server_ssl_file(fileName);
}
set_server_ssl_file(const char *fileName)
{
//initialize context
SSL_CTX_use_certificate_file(CTX, pem, SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(CTX, pem, SSL_FILETYPE_PEM);
}
//REQUIRED
void start_server()
{
const char *cert = "--BEGIN CERTIFICATE--............";
const char *key = "--BEGIN RSA PRIVATE KEY--.......";
set_server_ssl_options(cert, key);
}
set_server_ssl_options(const char *cert, const char *key)
{
//IMPLEMENTATION REQUIRED
}
The following code did the job for me:
SSL_CTX *CTX;
X509 *cert = NULL;
RSA *rsa = NULL;
BIO *cbio, *kbio;
const char *cert_buffer = "";
const char *key_buffer = "";
cbio = BIO_new_mem_buf((void*)cert_buffer, -1);
cert = PEM_read_bio_X509(cbio, NULL, 0, NULL);
assert(cert != NULL);
SSL_CTX_use_certificate(CTX, cert);
kbio = BIO_new_mem_buf((void*)key_buffer, -1);
rsa = PEM_read_bio_RSAPrivateKey(kbio, NULL, 0, NULL);
assert(rsa != NULL);
SSL_CTX_use_RSAPrivateKey(CTX, rsa);
The other snippets will only load one certificate. The content of files like http://curl.haxx.se/ca/cacert.pem that contain a lot of different certificates need a new approach. This is adapted from openssl 1.0.1p (mostly openssl-1.0.1p\crypto\x509\by_file.c, char* buf contains the content of a *.pem file, ctx is a boost::asio::ssl::context), add error handling on your own:
BIO *cbio = BIO_new_mem_buf((void*)buf, (int)length);
X509_STORE *cts = SSL_CTX_get_cert_store(ctx.native_handle());
if(!cts || !cbio)
return false;
X509_INFO *itmp;
int i, count = 0, type = X509_FILETYPE_PEM;
STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL);
if (!inf)
{
BIO_free(cbio);//cleanup
return false;
}
//itterate over all entries from the pem file, add them to the x509_store one by one
for (i = 0; i < sk_X509_INFO_num(inf); i++) {
itmp = sk_X509_INFO_value(inf, i);
if (itmp->x509) {
X509_STORE_add_cert(cts, itmp->x509);
count++;
}
if (itmp->crl) {
X509_STORE_add_crl(cts, itmp->crl);
count++;
}
}
sk_X509_INFO_pop_free(inf, X509_INFO_free); //cleanup
BIO_free(cbio);//cleanup
unsigned char *cert_data = (....);
int cert_len = (....);
X509 *cert = d2i_X509(NULL, &cert_data, cert_len);
SSL_CTX_use_certificate(ctx, cert);
unsigned char *pkey_data = /* ... */;
int pkey_len = /* ... */;
RSA *pkey = d2i_RSAPrivateKey(NULL, &pkey_data, pkey_len);
SSL_CTX_use_RSAPrivateKey(ctx, pkey);
Don't forget & before cert_data and pkey_data - and note that OpenSSL modifies these pointers.
There is another response that uses X509_STORE_add_cert, which is up-voted but incorrect. That answer is a way to do SSL_CTX_load_verify_locations in memory, but does not load the server certificate chain. Replies to that comment also indicate that it does not work.
The following code is a load-from-memory implementation of SSL_CTX_use_certificate_chain_file based on the implementation of that function in OpenSSL:
bool load_cert_chain_from_shared_mem(SSL_CTX *context, const char *cert_buffer)
{
BIO *cbio = BIO_new_mem_buf((void*)cert_buffer, -1);
if (!cbio)
return false;
X509_INFO *itmp;
int i, count = 0, type = X509_FILETYPE_PEM;
STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL);
if (!inf)
{
BIO_free(cbio);
return false;
}
/* Iterate over contents of the PEM buffer, and add certs. */
BOOL first = TRUE;
for (i = 0; i < sk_X509_INFO_num(inf); i++) {
itmp = sk_X509_INFO_value(inf, i);
if (itmp->x509)
{
/* First cert is server cert. Remaining, if any, are intermediate certs. */
if (first)
{
first = FALSE;
/*
* Set server certificate. Note that this operation increments the
* reference count, which means that it is okay for cleanup to free it.
*/
if (!SSL_CTX_use_certificate(context, itmp->x509))
goto Error;
if (ERR_peek_error() != 0)
goto Error;
/* Get ready to store intermediate certs, if any. */
SSL_CTX_clear_chain_certs(context);
}
else
{
/* Add intermediate cert to chain. */
if (!SSL_CTX_add0_chain_cert(context, itmp->x509))
goto Error;
/*
* Above function doesn't increment cert reference count. NULL the info
* reference to it in order to prevent it from being freed during cleanup.
*/
itmp->x509 = NULL;
}
}
}
sk_X509_INFO_pop_free(inf, X509_INFO_free);
BIO_free(cbio);
return true;
Error:
sk_X509_INFO_pop_free(inf, X509_INFO_free);
BIO_free(cbio);
return false;
}

x509 certificate verification in C

I do have certificates in DER and PEM format, my goal is to retrieve the fields of Issuer and Subject and verify the certificate with the CA public key and simultaneously verify CA certificate with the root public key.
I am able to retrieve all the details of issuer and subject but unable to verify the certificate.
The API used:
x509 = d2i_X509_fp (fp, &x509); //READING DER Format
x509 = PEM_read_X509 (fp, &x509, NULL, NULL); //READING PEM Format
//to retrieve the Subject:
X509_NAME_oneline(X509_get_subject_name(x509), subject, sizeof (subject));
//to retrieve the Issuer:
X509_NAME_oneline(X509_get_issuer_name(x509), issuer, sizeof (issuer));
//To store the CA public key (in unsigned char *key) that will be used to verify the
//certificate (in my case always sha1WithRSAEncryption):
RSA *x = X509_get_pubkey(x509)->pkey.rsa;
bn = x->n;
//extracts the bytes from public key & convert into unsigned char buffer
buf_len = (size_t) BN_num_bytes (bn);
stored_CA_pubKey = (unsigned char *)malloc (buf_len);
i_n = BN_bn2bin (bn, (unsigned char *)stored_CA_pubKey);
if (i_n != buf_len)
LOG(ERROR," : key error\n");
if (key[0] & 0x80)
LOG(DEBUG, "00\n");
stored_CA_pubKeyLen = EVP_PKEY_size(X509_get_pubkey(x509));
For Verification I went through different approaches but I am unable to verify:
a)
i_x509_verify = X509_verify(cert_x509, ca_pubkey);
b)
/* verify the signature */
int iRet1, iRet2, iReason;
iRet1 = EVP_VerifyInit(&md_ctx, EVP_sha1());
iRet2 = EVP_VerifyUpdate(&md_ctx, cert_code, cert_code_len);
rv = EVP_VerifyFinal(&md_ctx, (const unsigned char *)stored_CA_pubKey,
stored_CA_pubKeyLen, cert_pubkey);
NOTE : cert_code and stored_CA_pubKey are unsigned char buffers.
I use following code for verifying a certificate
init CertStore:
X509_STORE* m_store = X509_STORE_new();
X509_LOOKUP* m_lookup = X509_STORE_add_lookup(m_store,X509_LOOKUP_file());
X509_STORE_load_locations(m_store, "CAFile.pem", NULL);
X509_STORE_set_default_paths(m_store);
X509_LOOKUP_load_file(m_lookup,"CAFile.pem",X509_FILETYPE_PEM)
// alternative lookup by hashdir
// X509_LOOKUP* m_lookup=X509_STORE_add_lookup(m_store,X509_LOOKUP_hash_dir());
VerifyCert:
X509_STORE_CTX *storeCtx = X509_STORE_CTX_new();
X509_STORE_CTX_init(storeCtx,m_store,cert,NULL);
X509_STORE_CTX_set_flags(storeCtx, X509_V_FLAG_CB_ISSUER_CHECK);
if (X509_verify_cert(storeCtx) == 1)
{
printf("success");
}
else
{
printf("Verificatione rror: %s",X509_verify_cert_error_string(storeCtx->error));
}
X509_STORE_CTX_free(storeCtx);
you also need to cleanup m_store
if(m_store != NULL)
{
X509_STORE_free(m_store);
m_store = NULL;
}
Take a look at my self-answered question: https://stackoverflow.com/questions/3412032/openssl-c-how-do-you-verify-a-public-key-was-issued-by-your-private-ca it goes a long way to doing what you need.
X509_STORE* m_store = NULL;
X509_LOOKUP *m_lookup = NULL;
X509_STORE_CTX *storeCtx = NULL;
m_store = X509_STORE_new();
if(NULL == m_store) goto exit;
m_lookup = X509_STORE_add_lookup(m_store, X509_LOOKUP_file());
if(NULL == m_lookup) goto exit;
X509_STORE_load_locations(m_store, CA_CERT_PATH, NULL);
X509_STORE_set_default_paths(m_store);
X509_LOOKUP_load_file(m_lookup,CA_CERT_PATH, X509_FILETYPE_ASN1);
m_lookup = X509_STORE_add_lookup(m_store, X509_LOOKUP_hash_dir());
if(NULL == m_lookup) goto exit;
storeCtx = X509_STORE_CTX_new();
if(NULL == storeCtx) goto exit;
X509_STORE_CTX_init(storeCtx,m_store,cer_x509,NULL);
X509_STORE_CTX_set_flags(storeCtx, /*X509_V_FLAG_CHECK_SS_SIGNATURE*/0x4000);
if (X509_verify_cert(storeCtx) == 1)
{
printf("success\n");
}
else
{
printf("Verification error: %s\n",X509_verify_cert_error_string(storeCtx->error));
}
exit:
if(NULL != storeCtx) X509_STORE_CTX_free(storeCtx);
if(m_store != NULL)
{
X509_STORE_free(m_store);
m_store = NULL;
}
After Doing this also I am unable to verify Self signed certificate

Resources