Use of getlogin function in Linux - c++

When I login in Linux Suse10 machine and check for getlogin_r() through a C++ program, i get a proper result as my login name.
int main()
{
char szUserName[64] = {0};
int nGet = getlogin_r(szUserName, sizeof(szUserName)-1);
if(0 != nGet)
{
printerr();
}
printf("%s\n", szUserName);
char * szHome = getlogin();
printf("%s\n", szHome);
return 0;
}
But after using the su - name2
i have changed the login now.
But getlogin_r() still shows the older usename.
One solution is the use of geteuid(). But what is the reason of above problem

"after using su - name2 I have changed the login" - No, you haven't. You've changed the user id, not the login.
The man page for su says this about the - option: "Provide an environment similar to what the user would expect had the user logged in directly." Apparently "similar" is different than "identical to". Specifically, su - does not store a login record in /var/run/utmp.

Related

CrerdWriteW storing credentials in Mandarin on Windows

I used the answer here to add credentials programmatically to Windows Credential Manager. The code is inspired by the code in the answer. When I run it however, the credentials in the cred manager show up in Mandarin. I am not sure what am I doing wrong. Would appreciate any pointers. TIA .
For references this is the code I have
#include <iostream>
#include "windows.h"
#include "wincred.h"
#pragma hdrstop
using namespace std;
int main()
{
const char* password = "testpass";
CREDENTIALW creds = { 0 };
creds.Type = CRED_TYPE_GENERIC;
creds.TargetName = (LPWSTR)("testaccount");
creds.CredentialBlobSize = strlen(password) + 1;
creds.CredentialBlob = (LPBYTE)password;
creds.Persist = CRED_PERSIST_LOCAL_MACHINE;
creds.UserName = (LPWSTR)("testuser");
BOOL result = CredWriteW(&creds, 0);
if (result != TRUE)
{
cout << "Some error occurred" << endl;
}
else
{
cout << "Stored the password successfully" << endl;
}
return 0;
}
To ensure there is no default language problem, I manually created a credential from within the credential manager for test.com and had no problems with it. Snapshot of the Cred Manager -
Appearantly, TargetName needs to refer to a mutable array, i.e. not a string literal. It also needs to be a wide string, or else the characters will be interpreted wrongly, in this case resulting in Chinese characters.
The solution is to define a mutable array that is initialized with a wide string, and have TargetName point to it:
WCHAR targetName [] = L"testuser";
creds.TargetName = targetName;
This way, no suspicious cast is needed to make it compile. When you want to input non-hardcoded strings (e.g. from user input or a file), you need to make sure they are correctly encoded and convert appropriately.

get current Logged in user name from within a C++ windows service

I have a service (written in C++), running under Windows 10. I need to get the name of the currently logged in user, but most Windows APIs I have found return the username of the calling thread, which when run as a system, is always "SYSTEM".
My use case is below:
Install the service with Administrator account
Log off from administrator
Login as a Non-Admin user
Query the service to get the current logged user name
You need to enumerate all sessions and identify the active session using WTSEnumerateSessions. Then you can query username of the active session using WTSQuerySessionInformation and query class WTSUsername.
WTS_SESSION_INFO *SessionInfo;
unsigned long SessionCount;
unsigned long ActiveSessionId = -1;
std::cout<<"Active Console Session Id : "<<WTSGetActiveConsoleSessionId()<<"\n";
if(WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &SessionInfo, &SessionCount))
{
for (auto i = 0; i < SessionCount; i++)
{
if (SessionInfo[i].State == WTSActive)
{
ActiveSessionId = SessionInfo[i].SessionId;
break;
}
}
char *UserName;
if (ActiveSessionId != -1)
{
unsigned long BytesReturned;
if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, ActiveSessionId, WTSUserName, &UserName, &BytesReturned))
{
std::cout<<UserName;
WTSFreeMemory(UserName);
}
}
WTSFreeMemory(SessionInfo);
}
Note that this will only work if there is only one active session (unlike terminal servers)
in addition to answer above, the following line
if (SessionInfo[i].State == WTSActive)
should be changed to
if (SessionInfo[i].State == WTSActive || SessionInfo[i].State == WTSConnected)
to include remote session too

Check if a user is a local or domain account

Given the name of a user in OS X, it is possible to query its Active Directory SID using the BSD membership functions.
However, when a local user name is provided on a machine that is not a member of a directory, an SID is also returned.
A solution for checking if the local logged-in user is a domain account is provided here, but this assumes that the user in question is that of the current session, which may not be the case. In addition, if the user is a mobile account (roaming), then a home directory is found and it returns incorrectly.
So, how would one check if a given username is a local or domain user where the username can be any name, including names used for local processes?
Using OpenDirectory API I've managed to achieve a similar task, here is the modified solution that would fit your query:
bool isDomainUser(std::string currentUser)
{
NSString *queryVal = [NSString stringWithUTF8String:currentUser.c_str()];
ODSession *session = [ODSession defaultSession];
ODNode *node = [ODNode nodeWithSession:session
type:kODNodeTypeAuthentication error:NULL];
ODQuery *query = [ODQuery queryWithNode:node forRecordTypes:kODRecordTypeUsers
attribute:kODAttributeTypeRecordName
matchType:kODMatchEqualTo
queryValues:queryVal
returnAttributes:kODAttributeTypeStandardOnly
maximumResults:0 error:NULL];
NSArray *records = [query resultsAllowingPartial:NO error:NULL];
for (ODRecord *record in records)
{
ODAttributeType type = #"dsAttrTypeStandard:OriginalAuthenticationAuthority";
NSArray *lines = [record valuesForAttribute:type error:nil];
if (lines)
{
for(NSString *line in lines)
{
if ([line hasPrefix:#"NetLogon"])
{
return true;
}
}
}
}
return false;
}

How to determine if the process owner is an administrator on Mac OS X in C++

How do I programmatically check if the user that ran my executable is an administrator?
This is C++ on Mac OS X 10.6 (Snow Leopard) or higher. My many searches have not turned up anything.
Check the groups that the user is in, and confirm that the user is in the required group. I think you want to check that the user belongs to 'admin', but you may instead want to check for other, more specific access. Why do you want to check for admin anyway? It's usually a better idea to directly attempt the task, than to check for a broad level of access and failing if the user doesn't have that access, but does infact have the specific access you want.
#include <grp.h>
#include <pwd.h>
#include <string.h>
bool currentUserIsAdmin ( ) {
// A user cannot be member in more than NGROUPS groups,
// not counting the default group (hence the + 1)
gid_t groupIDs[NGROUPS + 1];
// ID of user who started the process
uid_t userID = getuid();
// Get user password info for that user
struct passwd * pw = getpwuid(userID);
int groupCount;
if (pw) {
// Look up groups that user belongs to
groupCount = NGROUPS + 1;
// getgrouplist returns ints and not gid_t and
// both may not necessarily have the same size
int intGroupIDs[NGROUPS + 1];
getgrouplist(pw->pw_name, pw->pw_gid, intGroupIDs, &groupCount);
// Copy them to real array
for (int i = 0; i < groupCount; i++) groupIDs[i] = intGroupIDs[i];
} else {
// We cannot lookup the user but we can look what groups this process
// currently belongs to (which is usually the same group list).
groupCount = getgroups(NGROUPS + 1, groupIDs);
}
for (int i = 0; i < groupCount; i++) {
// Get the group info for each group
struct group * group = getgrgid(groupIDs[i]);
if (!group) continue;
// An admin user is member of the group named "admin"
if (strcmp(group->gr_name, "admin") == 0) return true;
}
return false;
}
How about checking a user id by calling getuid()? OS X is based on BSD. Thus, I think you might be able to check what ID runs the process by this function.
It looks like Open Directory is the proper way to do this. You might be able to cheap it out by using getegid() and/or setegid()
I haven't tested it but this might work:
// 80 should be the admin group number, but it Apple might change it in a later release.
if (getegid() == 80 || setegid(80) == 0) {
// Yea! I'm an admin.
}
Just a couple of quick ideas to follow up on. I hope they lead you in the right direction.

WMI Remote connection

I have an issue regarding WMI connection through asp.net from Computer A (windows 2003 server) to Computer B (Windows XP)..
The error is as follows:
RPC server is unavailable..
There are a few steps that you must take in order to successfully leverage WMI connectivity. The basics are you must allow remote management on the target box of course. If you can’t RDP into it, chances are, you can’t remote manage anything else. This can also include Windows firewall issues too. Make sure your request can even get in at all.
Next, start simple. Can you even poll for the running processes on that box? Try to output all the running processes on the target box with System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetProcesses("machine-name"). If you can at least get some information on the box then the RPC message you are getting has to do with incorrect arguments being passed in, perhaps?
Anyways, I recently wrote a web application that allowed the users to find a server on the LAN and kill a target process there or start a new one. I did it in C# so the code snippet below is just what I used. It's not the best but its working in production right now:
public static class RemoteProcessAccess
{
public static void KillProcessByProcessID(string NameOfServer, string DomainName, string LogIn, string Password, int processID)
{
//#1 The vars for this static method
#region /// <variables> ...
string userName;
string password;
string machineName;
string myDomain;
Hashtable hs = new Hashtable();
ManagementScope mScope;
ConnectionOptions cnOptions;
ManagementObjectSearcher objSearcher;
ManagementOperationObserver opsObserver;
ManagementClass manageClass;
DirectoryEntry entry;
DirectorySearcher searcher;
DirectorySearcher userSearcher;
#endregion
//#2 Set the basics sent into the method
machineName = NameOfServer;
myDomain = DomainName;
userName = LogIn;
password = Password;
cnOptions = new ConnectionOptions();
cnOptions.Impersonation = ImpersonationLevel.Impersonate;
cnOptions.EnablePrivileges = true;
cnOptions.Username = myDomain + "\\" + userName;
cnOptions.Password = password;
mScope = new ManagementScope(#"\\" + machineName + #"\ROOT\CIMV2", cnOptions);
//#3 Begin Connection to Remote Box
mScope.Connect();
objSearcher = new ManagementObjectSearcher(String.Format("Select * from Win32_Process Where ProcessID = {0}", processID));
opsObserver = new ManagementOperationObserver();
objSearcher.Scope = mScope;
string[] sep = { "\n", "\t" };
//#4 Loop through
foreach (ManagementObject obj in objSearcher.Get())
{
string caption = obj.GetText(TextFormat.Mof);
string[] split = caption.Split(sep, StringSplitOptions.RemoveEmptyEntries);
// Iterate through the splitter
for (int i = 0; i < split.Length; i++)
{
if (split[i].Split('=').Length > 1)
{
string[] procDetails = split[i].Split('=');
procDetails[1] = procDetails[1].Replace(#"""", "");
procDetails[1] = procDetails[1].Replace(';', ' ');
switch (procDetails[0].Trim().ToLower())
{
//You could look for any of the properties here and do something else,
case "processid":
int tmpProc = Convert.ToInt32(procDetails[1].ToString());
//if the process id equals the one passed in....
//(this is redundant since we should have limited the return
//by the query where above, but we're paranoid here
if (tmpProc.Equals(processID))
{
obj.InvokeMethod(opsObserver, "Terminate", null);
}
break;
}//end process ID switch...
}//end our if statement...
}//end our for loop...
}//end our for each loop...
}//end static method
}
Look at KB875605 ("How to troubleshoot WMI-related issues in Windows XP SP2")
You could enable the RPC server on any target machine by running this on the target's command prompt:
[/code]
netsh firewall set service RemoteAdmin
[/code]
Worked for me at least. :)
Try to use wmic command line to get information from the remote computer, also you can install the code of Services+ and try to connect and debug your connection to the server, most likely it is firewall problem or RPC services is down or disabled.