Enumerating supplementary groups in a C Program - c

I'm wanting to get a list of supplementary groups for the user by sending a request through NSS. To my reckoning, the following program should let me enumerate all the groups (so I can then compare members):
#include <stdio.h>
#include <grp.h>
#include <stdlib.h>
struct group *groupStruct;
int main(){
setgrent();
while ( groupStruct=getgrent() )
printf("%s\n", groupStruct->gr_name);
endgrent();
return 0;
}
I'm basing this assumption on this part of the source code for id that gets executed with id -Gn (since that's the functionality I want to replicate). Looking at that it looks like it gets the list of groups via getugroups (0, NULL, username, gid) with getugroups() being defined in another file (essentially the same code found here). It looks like that is going through the same setgrent()/getgrent() procedure as above, so my feeling is that my simple program ought to enumerate the system's groups (instead, it only does the groups in /etc/group but I have winbind on this machine and id -Gn pulls in the winbind groups the user is a member of).

For posterity:
I still don't know why the id -Gn code works but not mine, but I think I fixed my own issue after a lot of back and forth. Basically I'm building a shared object and enumerating their current memberships by way of a helper program that uses initgroups/getgroups to set the running processes's (the helper executable) persona to the target user's default persona (what they would get after logging in. This is the full code of the helper program:
#include <stdio.h>
#include <unistd.h>
struct group *groupStruct;
int main(int argc, char *argv[]){
int numgroups, iter, retCode;
int numgroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
gid_t groupList[numgroups_max];
if (argc != 2){
printf("Insufficient Arguments.\n");
return 1;
}
retCode=initgroups(argv[1], 0);
if (retCode != 0){
printf("Unspecified failure: %d\n\n", retCode);
return 1;
}
numgroups = getgroups(numgroups_max, groupList);
for (iter=0; iter <= numgroups; iter++){
if (iter != 0 && iter != numgroups )
printf(" ");
// "zero" means both "nothing more" and could be the root user's primary group, allow the first one through
if ( groupList[iter] == 0 && getuid() == 0 ){
if ( iter != 0 )
break;
}else if ( groupList[iter] == 0 )
break;
printf("%d", groupList[iter]);
}
return 0;
}
Username is hard coded just for testing purposes. After compiling and testing it produces the group ID's for the user. Changing the hard coded value (or pushing it into argv) resolves the problem. I pushed this into a helper executable because it's changing the running process's persona (at least the group membership portion).
I'll probably move it into the library's calling routine for performance/security (I can save the supplementary and primary groups before with getgroups and setgroups), but it was quicker for me to do a proof of concept in a separate executable.

Related

GetModuleHandleW / A - not working. Returning null every call excluding empty string

#include <Windows.h>
int main(){
printf("Enter name of program. \n");
char prog[300];
scanf("%s", prog);
HMODULE hModule = GetModuleHandleW((LPCWSTR)prog);
if (hModule){
IMAGE_DOS_HEADER* pIDH = (IMAGE_DOS_HEADER*)hModule;
IMAGE_NT_HEADERS* pNTH =(IMAGE_NT_HEADERS*)((BYTE*)pIDH + pIDH->e_lfanew);
IMAGE_OPTIONAL_HEADER pOPH = (IMAGE_OPTIONAL_HEADER)pNTH->OptionalHeader;
IMAGE_DATA_DIRECTORY* pIDD = (IMAGE_DATA_DIRECTORY*)pOPH.DataDirectory;
printf("%x", pIDD->VirtualAddress);
}
else {
printf("Error");
}
return 0;
}
That's my basic script for now only to check if I get into the IMAGE_DATA_DIRECTORY.
My goal is to print every dll and all of it's imported functions of a certain running process - GetModuleHandleA / W.
Every call its returning null - printing "Error" as I checked, excluding the empty call in which it prints '0' for some reason..
Besides the obvious (LPCWSTR)prog casting bug, GetModuleHandle is never going to work because it only handles modules in the current process.
Call CreateToolhelp32Snapshot to get a list of all processes and then call CreateToolhelp32Snapshot again to get the modules of a specific process. Note that you cannot read the DOS/NT headers of a remote process directly, you would have to use ReadProcessMemory.
DataDirectory is an array, you have to specify the directory you are interested in (resource, import, export etc.).

HWUT choice order

I am using choices in my HWUT test.
If in the command line, I don't specify the choice, then the test runs for all the choices.
And the test is run for each choice as per alphabetical order. But, I would the like the test to run the choices based on the order specified in the test file, as specified below.
For example:
printf("CHOICES: start, do_something, end");
I would like to it execute in the same order.
I did see some information regarding ordering of choices in this page.
This mentions about FIRST, NOT_LAST, NOT_FIRST, LAST. I couldn't figure out how to use this. Also, I'm not sure if this is the solution.
A HWUT Test's choice relates to a test that is completely independent. Your setup procedure must create a deterministic environment and the results must not depend on external things and must not depend on the history of HWUT tests!
If you have such a history dependency, then you must code the tests in a single choice (or, not having any choices at all).
Sometimes you 'make/build' things that are useful for all tests. For example, you might generate a huge database that is used by all CHOICES. When the last test finishes, the huge database shall be remove from the file system. Then, it makes sense to consider FIRST and LAST.
So, let us assume your case is case 3. Then, you check whether it is the first and/or last CHOICE by checking on argv[2] and argv[3] as described in the page that you reference.
/* Begin of 'main()' */
if( argc > 2 && strmp(argv[2], "FIRST") == 0 ) {
/* Build some stuff to be used by all CHOICES. */
}
... test current CHOICE ...
/* End of 'main()' */
if( argc > 3 && strmp(argv[3], "LAST") == 0 ) {
/* Delete some stuff that has been used by all CHOICES. */
}
If 'start' 'do_something', and 'end' must be executed in that order, then create three functions 'test_start(...)', 'test_do_something(...)', and 'test_end(...)' which execute your tests -- as suggested in item 2.
int main(int argc, char** argv)
{
...
test_start(...);
test_do_something(...);
test_end(...);
}
If something happens in 'start', 'do_domething', and 'end' that can be tested,
but testing all at once is too much for you, then
#include "hwut_unit.h"
int print_index = 0;
int main(int argc, char** argv)
{
...
hwut_if_choice("start") print_index = 0;
hwut_if_choice("do_something") print_index = 1;
hwut_if_choice("end") print_index = 2;
...
}
And in the 'test_start(...)' function do
void test_start(...)
{
...
if( print_index == 0 ) {
printf(...);
}
}
That is, make your print statements dependent on a 'print_index'.
The 'print_index' in turn must be set according to the CHOICE.

Obtaining List of all Xorg Displays

I would like to know how I can obtain a list of all Xorg displays on my system, along with a list of screens associated with each display. I spent some time looking through the Xlib documentation, but was not able to find a function that does what I want. Please assume that I have no other dependencies other than a POSIX-complaint OS and X (e.g., no GTK). If what I ask is not possible assuming these minimal dependencies, then a solution using other libraries is fine.
Thank you very much for your help!
The only way I know of to get a list of displays is to check the /tmp/.X11-unix directory.
Once you do that, you can use Xlib to query each display for more information.
Per example:
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <X11/Xlib.h>
int main(void) {
DIR* d = opendir("/tmp/.X11-unix");
if (d != NULL) {
struct dirent *dr;
while ((dr = readdir(d)) != NULL) {
if (dr->d_name[0] != 'X')
continue;
char display_name[64] = ":";
strcat(display_name, dr->d_name + 1);
Display *disp = XOpenDisplay(display_name);
if (disp != NULL) {
int count = XScreenCount(disp);
printf("Display %s has %d screens\n",
display_name, count);
int i;
for (i=0; i<count; i++)
printf(" %d: %dx%d\n",
i, XDisplayWidth(disp, i), XDisplayHeight(disp, i));
XCloseDisplay(disp);
}
}
closedir(d);
}
return 0;
}
Running the above gives me this output with my current displays/screens:
Display :0 has 1 screens
0: 3046x1050
Display :1 has 2 screens
0: 1366x768
1: 1680x1050
Never found a better way of listing X displays other than that. I'd very much like to know if any better alternative exists.
Like netcoder wrote, the problem has two distinct parts:
Connection to the X server
The process establishes a connection to an X server using XOpenDisplay(). The connection is torn down using XCloseDisplay(). netcoders code in this thread is a good example of how to do it correctly.
As netcoder mentioned, the problem is that there is no reliable way find out which X servers a process can connect to. His code checks the typical location where the X sockets are, /tmp/.X11-unix/. That approach does not work at all if the user is remotely connected, for example via SSH (with X forwarding enabled). In that case there is really only the DISPLAY environment variable (and perhaps some trickery wrt. ~/.Xauthority files).
Unfortunately, I do not know of any better method either. I personally prefer to use a per-user configuration file -- say ~/.application/displays --, where the user can list the server names the application should try to connect in the same format as the DISPLAY environment variable, in addition to the default one. It is not automatic (netcoder's code is), but this approach suits me better.
Finding out about the screens provided by an X server
XScreenCount() will return the number of screens provided by the X server the process is currently connected to. If you only need the screen dimensions, follow netcoders example. For more detailed information, use XScreenOfDisplay(Display,index) to obtain the Screen pointers; 0 <= index < XScreenCount(Display).
In C code, the macros ScreenCount() and ScreenOfDisplay() are usually a bit more efficient than the actual function calls.

How do you check if a directory exists on Windows in C?

Question
In a Windows C application I want to validate a parameter passed into a function to ensure that the specified path exists.*
How do you check if a directory exists on Windows in C?
*I understand that you can get into race conditions where between the time you check for the existance and the time you use the path that it no longer exists, but I can deal with that.
Additional Background
Knowing explicitly that a directory does or does not exist can get tricky when permissions come into play. It's possible that in attempting to determine if the directory exists, the process doesn't have permissions to access the directory or a parent directory. This is OK for my needs. If the directory doesn't exist OR I can't access it, both are treated as an invalid path failure in my application, so I don't need to differentiate. (Virtual) bonus points if your solution provides for this distinction.
Any solution in the C language, C runtime library, or Win32 API is fine, but ideally I'd like to stick to libraries that are commonly loaded (e.g. kernel32, user32, etc.) and avoid solutions that involve loading non-standard libraries (like PathFileExists in Shlwapi.dll). Again, (Virtual) bonus points if your solution is cross-platform.
Related
How can we check if a file Exists or not using Win32 program?
Do something like this:
BOOL DirectoryExists(LPCTSTR szPath)
{
DWORD dwAttrib = GetFileAttributes(szPath);
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
The GetFileAttributes() method is included in Kernel32.dll.
Here's a totally platform-agnostic solution (using the standard C library)
Edit: For this to compile in Linux, replace <io.h> with <unistd.h> and _access with access. For a real platform agnostic solution, use the Boost FileSystem library.
#include <io.h> // For access().
#include <sys/types.h> // For stat().
#include <sys/stat.h> // For stat().
bool DirectoryExists( const char* absolutePath ){
if( _access( absolutePath, 0 ) == 0 ){
struct stat status;
stat( absolutePath, &status );
return (status.st_mode & S_IFDIR) != 0;
}
return false;
}
A Windows-specific implementation that supports both MBCS and UNICODE builds:
#include <io.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <tchar.h>
BOOL directory_exists( LPCTSTR absolutePath )
{
if( _taccess_s( absolutePath, 0 ) == 0 )
{
struct _stat status;
_tstat( absolutePath, &status );
return (status.st_mode & S_IFDIR) != 0;
}
return FALSE;
}
If linking to the Shell Lightweight API (shlwapi.dll) is ok for you, you can use the PathIsDirectory function.
Another option is the shell function PathFileExists()
PathFileExists() documentation
This function "Determines whether a path to a file system object such as a file or directory is valid."
So, this question is full of edge cases. A real answer would be like this:
BOOL DirectoryExists(LPCTSTR szPath, BOOL *exists)
{
*exists = FALSE;
size_t szLen = _tcslen(szPath);
if (szLen > 0 && szPath[szLen - 1] == '\\') --szLen;
HANDLE heap = GetProcessHeap();
LPCTSTR szPath2 = HeapAlloc(heap, 0, (szlen + 3) * sizeof(TCHAR));
if (!szPath2) return FALSE;
CopyMemory(szPath2, szPath, szLen * sizeof(TCHAR));
szPath2[szLen] = '\\';
szPath2[szLen + 1] = '.';
szPath2[szLen + 2] = 0;
DWORD dwAttrib = GetFileAttributes(szPath2);
HeapFree(heap, 0, szPath2);
if (dwAttrib != INVALID_FILE_ATTRIBUTES) {
*exists = TRUE; /* no point checking FILE_ATTRIBUTE_DIRECTORY on "." */
return TRUE;
}
/*
* If we get anything other than ERROR_PATH_NOT_FOUND then something's wrong.
* Could be hardware IO, lack of permissions, a symbolic link pointing to somewhere
* you don't have access, etc.
*/
return GetLastError() != ERROR_PATH_NOT_FOUND;
}
The correct result of DirectoryExists is tri-state. There are three cases and you need to handle all of them. Either it exists, it doesn't exist, or you were unable to check. I've lost data in production because a SAN returned NO to the check function and then let me create something clobbering it on the very next line of code. Don't make the same mistake Microsoft did when designing the File.Exists() API in C#.
However I see a lot of checks that are supliferous. Don't write thinks like if (directory doesn't exist) CreateDirectory(); just write CreateDirectory() if (GetLastError() != 0 && GetLastError() != ERROR_ALREADY_EXISTS. Or the converse with RemoveDirectory(); just remove it and check for either no error or path not found.

How can I get the keyboard state in Linux?

I want to check if the user pressed down the Shift key when the program starts. (That means, press down the Shift key before the program is started) It's a simple console program, nothing related to X.
This maybe similar to the Win32 GetKeyboardState() function.
I want to know whether I can do this and how, but not any pros and cons with accessing the terminal directly.
I think there would be a way to do this. The thing is that you would have to read directly from the keyboard device. You would not be getting input from the terminal. I have the same problem. I have a program that runs (in the background) and I want to know if the user is holding down the shift key.
I believe this is possible and a place to start might be /dev/input/by-path/*-kbd.
This file does give input every time a key is pressed or reptadly if it is held down so it might be worth a look. (Try cat /dev/input/by-path/*-kbd)
If you do figure this out I would love to hear how you did it.
EDIT: I have found the solution
I have figured out how do do this. My program is as follows:
#include <stdlib.h>
#include <stdio.h>
#include <linux/input.h>
void usage ( int argc, char *argv[] )
{
printf("Usage:\n\t%s key\n\nvalid keys are:\n\tlshift\t- Left Shift key\n" , argv[0]);
exit(EXIT_FAILURE);
}
int main ( int argc, char *argv[], char *env[] )
{
if ( argc != 2 ) usage(argc, argv);
int key;
if ( strcmp(argv[1], "lshift") == 0 ) key = KEY_LEFTSHIFT;
else if ( strcmp(argv[1], "rshift") == 0 ) key = KEY_RIGHTSHIFT;
else if ( strcmp(argv[1], "lalt") == 0 ) key = KEY_LEFTALT;
else if ( strcmp(argv[1], "ralt") == 0 ) key = KEY_RIGHTALT;
else if ( strcmp(argv[1], "lctrl") == 0 ) key = KEY_LEFTCTRL;
else if ( strcmp(argv[1], "rctrl") == 0 ) key = KEY_RIGHTCTRL;
FILE *kbd = fopen("/dev/input/by-path/platform-i8042-serio-0-event-kbd", "r");
char key_map[KEY_MAX/8 + 1]; // Create a byte array the size of the number of keys
memset(key_map, 0, sizeof(key_map)); // Initate the array to zero's
ioctl(fileno(kbd), EVIOCGKEY(sizeof(key_map)), key_map); // Fill the keymap with the current keyboard state
int keyb = key_map[key/8]; // The key we want (and the seven others arround it)
int mask = 1 << (key % 8); // Put a one in the same column as out key state will be in;
return !(keyb & mask); // Returns true if pressed otherwise false
}
The info message is lacking (I'm too lazy). But essentially the first argument is compared to a list of keys and the appropriate key identifier is used. It returns true if the key is pressed and false if not.
Please Note
You will need to change the name of they keyboard device. I do not know of a way to find the default keyboard device. (if you know I would love to hear ;) )
This works beautifully: I use it to start the autostart of Xorg if I hold down the shift key.
AFAIK this cannot be done without Xlib (aka. X) with no root level permissions.
Using XQueryKeymap() will do what you want. however you pointed out that X cannot be used. Regardless, opening display connection will also be required.
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <stdbool.h>
#include <stdio.h>
int main()
{
Display* dpy = XOpenDisplay(NULL);
char keys_return[32];
XQueryKeymap( dpy, keys_return );
KeyCode kc2 = XKeysymToKeycode( dpy, XK_Shift_L );
bool bShiftPressed = !!( keys_return[ kc2>>3 ] & ( 1<<(kc2&7) ) );
printf("Shift is %spressed\n", bShiftPressed ? "" : "not ");
XCloseDisplay(dpy);
}
I have found a very simple way through gtk/gdk.
int main ( int argc, char *argv[], char *env[] )
{
gtk_init(&argc, &argv);
GdkModifierType button_state;
gdk_window_get_pointer(NULL, NULL, NULL, &button_state);
if(button_state & GDK_CONTROL_MASK) {
printf("ctrl key is pressed");
}
}
You can't.
The Shift key isn't considered as a character key, so even if you access the terminal directly, you won't be able to detect this key.
Maybe you shouldn't have to. Imagine for example that you are using a US keyboard where numbers are accessible on the top row without modifiers, and also checking for the Shift key. People with other keyboard layout may have to use Shift modifiers to access the numbers. If your program react to this Shift press, then your program is basically unusable. The same thing applies for other modifier keys : you may detect some of them only after a normal character key is pressed. Or worse, they may need to use the Shift key to use 'enter' to run your program.
Also, what Shift key do you want to monitor? the one on the local machine, or the one where the user is? remember that SSH exists and is commonly used to access a pseudoterminal remotely.
If you are root and want to monitor the Shift key on the local machine, you can read the evdev devices for events about the Shift key. But this is only possible because of automatic key repeating, so you won't detect a Shift key that is pressed right before running your program, but only a few second before.
Of course you can't do that on the remote machine, that would be a security flaw.
And anyway, why would you want to do that? Wouldn't an X application be the right thing to do in your case?

Resources