Writing a custom nss hosts module - glibc

I'm seeking to implement a custom nss module for the getent hosts lookup. Based on glibc's resolv/nss-dns/dns-host.c and gnunet's src/gns/nss/nss_gns.c I wrote the following minimal implementation that I hoped at least should write something to syslog - which it sadly doesn't.
#include <netdb.h>
#include <nss.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#define _nss_lash_gethostbyname2_r _nss_lash_gethostbyname_r
#define _nss_lash_gethostbyname3_r _nss_lash_gethostbyname_r
#define _nss_lash_gethostbyname4_r _nss_lash_gethostbyname_r
#define _nss_lash_getcanonname_r _nss_lash_gethostbyaddr_r
#define _nss_lash_gethostbyaddr2_r _nss_lash_gethostbyaddr_r
#define _nss_lash_getnetbyname_r _nss_lash_gethostbyaddr_r
#define _nss_lash_getnetbyaddr_r _nss_lash_gethostbyaddr_r
typedef char addr[1];
const addr default_addrs[2] = {0x01, 0x00};
enum nss_status
_nss_lash_gethostbyname_r (const char *name, struct hostent *result,
char *buffer, size_t buflen, int *errnop,
int *h_errnop)
{
syslog(LOG_WARNING, name);
if (!strcmp(name, "lash")) {
return NSS_STATUS_UNAVAIL;
}
*(result->h_aliases) = 0x0;
result->h_addrtype = AF_INET;
result->h_length = 1;
*(result->h_addr_list) = (char *)default_addrs;
*errnop = 0;
*h_errnop = NETDB_SUCCESS;
return NSS_STATUS_SUCCESS;
}
enum nss_status
_nss_lash_gethostbyaddr_r (const char *name, struct hostent *result,
char *buffer, size_t buflen, int *errnop,
int *h_errnop)
{
syslog(LOG_ERR, name);
if (!strcmp(name, "lash")) {
return NSS_STATUS_UNAVAIL;
}
*(result->h_aliases) = 0x0;
result->h_addrtype = AF_INET;
result->h_length = 1;
*(result->h_addr_list) = (char *)default_addrs;
*errnop = 0;
*h_errnop = NETDB_SUCCESS;
return NSS_STATUS_SUCCESS;
}
I've added lash to /etc/nsswitch.conf. strace shows that the /lib/libnss_lash.so.2 file is being successfully opened. However the return value from the nss lookup is NSS_UNAVAIL / ENOENT. If I add [unavail=return] to /etc/nsswitch.conf after the lash entry, I get the same result.
Anyone have any clues to what I'm missing?
(the #define lines attempt to catch all symbols found in objdump -T /lib/libnss_dns.so, which seems to be the simpler implementation)
Using:
glibc 2.30
gnunet 0.11.6-ish
nss 3.49.2

Related

How to drive my credential provider with CredUIPromptForWindowsCredentials

I've been working on a credential provider and I've been debugging it through logging. Recently learned about CredUIPromptForWindowsCredentials() API to be able to invoke it from other than login screen or remote desktop connection. The only way at this time I can seem to get my credential to display is to set the last param to CREDUIWIN_SECURE_PROMPT. I've tried various schemes of the flags with no luck. My CP works, that's not the problem. Problem is easier debugging. Only once have I had to go to rescue mode when I made my laptop unbootable. ;) The problem with using the CREDUIWIN_SECURE_PROMPT flag is that then I don't have access to the debugger because login takes over the screen and I can't get back to my debugger. I suppose the only workaround would be to remote debug on another machine with this API, but I'd prefer not to hassle with that.
My CP is registered at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{55157584-ff0f-48ce-9178-a4e290901663} and the default property is "MyCredProvider" (for this example). (GUID, prop name changed to protect the guilty. Also ignore LsaString where bad things would happen on a copy--of which I'm not doing.)
Any way to get my custom CP without using the secure prompt?
#include <windows.h>
#include <iostream>
#include <EvoApi.h>
#include <decrypt.h>
#include <atlbase.h>
#include <Lmwksta.h>
#include <StrSafe.h>
#include <LMAPIbuf.h>
#include <LMJoin.h>
#include <wincred.h>
#include <NTSecAPI.h>
#pragma warning(disable : 4996)
#pragma comment(lib, "netapi32.lib")
#pragma comment(lib, "credui.lib")
#pragma comment(lib, "secur32")
using namespace std;
template <size_t SIZE = 256>
struct LsaString : public LSA_STRING
{
LsaString()
{
MaximumLength = SIZE;
Length = 0;
Buffer = pBuf.get();
}
LsaString(LPCSTR pWhat)
{
MaximumLength = SIZE;
Length = 0;
Buffer = pBuf.get();
Init(pWhat);
}
void Init(LPCSTR pWhat)
{
size_t len = strlen(pWhat);
if (len >= SIZE)
throw;
strcpy(Buffer, pWhat);
Length = (USHORT) len;
}
unique_ptr<char[]> pBuf = make_unique< char[] >(SIZE);
};
int _tmain(int argc, wchar_t* argv[])
{
#if 1
wstring me(_T("MYLOGING"));
wstring url(_T("Header"));
wstring message(_T("Enter credentials for ..."));
CREDUI_INFOW credInfo;
credInfo.pszCaptionText = url.c_str();
credInfo.hbmBanner = nullptr;
credInfo.hwndParent = NULL;
credInfo.pszMessageText = message.c_str();
credInfo.cbSize = sizeof(CREDUI_INFOW);
ULONG authPackage = 0;
LSAHANDLE lsaHandle;
LsaConnectUntrusted(&lsaHandle);
LsaString<> lsaString("MyCredProvider");
//LsaString<> lsaString(MICROSOFT_KERBEROS_NAME_A); // works ... as far as finding in LsaLookupAuth...
//LsaString<> lsaString(NEGOSSP_NAME_A); // works ... as far as finding in LsaLookupAuth...
ULONG ulPackage = 0;
LsaLookupAuthenticationPackage(lsaHandle, &lsaString, &ulPackage);
void* pBlob;
ULONG blobSize = 0;
DWORD dwFlags = CREDUIWIN_GENERIC; //CREDUIWIN_SECURE_PROMPT
CredUIPromptForWindowsCredentials(&credInfo, 0, &ulPackage, NULL, 0, &pBlob, &blobSize, FALSE, dwFlags);
if (pBlob) CoTaskMemFree(pBlob);
return 0;
}

json-c: segmentation fault when in json_tokener_parse

I am using json-c to parse json files in my project. I tried creating json_tokener_parse but this has resulted in seg-fault. could any please check and tell me the reason for segfault.
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h> // O_RDONLY
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<json-c/json.h>
int main() {
int oflag = O_RDONLY;
const char *path = "file.json";
const int fd = open(path, oflag);
// use stat to find the file size
struct stat stat;
int ret = fstat(fd, &stat);
int mflags = MAP_SHARED; // information about handling the mapped data
int mprot = PROT_READ|PROT_WRITE; // access permissions to the data being mapped
size_t size = stat.st_size;
void *addr = mmap(NULL, size, mprot, mflags, fd, 0);
const char *file = (char *)addr;
json_object * jobj = json_tokener_parse(addr);
//json_parse(jobj);
}
json_tokener_parse() takes a null-terminated string. A text file is not null-terminated. You'll have to use json_tokener_parse_ex() and specify the length.

gcc using unlink and readdir, 7 days old files needs to be deleted

Using this code fetched from google.
#include <dirent.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
struct dirent *entry;
DIR *dp;
chdir("/mnt/shared");
dp = opendir(".");
while( (entry = readdir(dp)) != NULL ) {
if ( strcmp(entry->d_name, ".") &&strcmp(entry->d_name, "..") ){
unlink(entry->d_name);
}
}
}`
In this could it be possible to delete files older than 7 days from the current date?
In perl i tried as follows, but wondering this could be achived with your help?
my $now = time();
my $DATEAGE = 60*60*24*7;
for my $file (#file_list) {
my #stats = stat($file);
if ($now-$stats[9] > $DATEAGE) {
print "$file\n";}
Build the full string of the file and use several syscalls(2) (notably stat(2)) ; read Advanced Linux Programming
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
struct dirent *entry;
DIR *dp;
time_t weekago;
time(&weekago);
weekago -= 86400*7;
dp = opendir("/mnt/shared");
if (!dp) { perror("/mnt/shared"); exit(EXIT_FAILURE); };
while( (entry = readdir(dp)) != NULL ) {
if ( strcmp(entry->d_name, ".")
&& strcmp(entry->d_name, "..") ){
char buf[256];
if (snprintf(buf, sizeof(buf),
"/mnt/shared/%s", entry->d_name)
>=sizeof(buf))
{ fprintf(stderr, "too long path %s\n", buf);
exit(EXIT_FAILURE);
};
struct stat st;
if (stat(buf,&st)) {
perror(buf);
exit(EXIT_FAILURE);
};
if ((st.st_mode & S_IFMT) == S_IFREG // a plain file
&& (st.st_mtime < weekago))
{
if (remove(buf)) perror(buf);
}
}
}
My untested code above is imperfect (and not very well indented): it don't handle file paths wider than 255. But you could improve it, e.g. using asprintf(3) to build the path in heap (then you'll need to free it).
Practically speaking, use find(1). If you need to recurse in a file tree in C, use nftw(3)

insmod module param : invalid parameters

I'm developping sample kernel module driver.ko. I want to specify the block size of data_node structure with module parameter BlockSize. when I run insmod driver.ko alone, it works, but when I specify BlockSize insmod driver.ko BlockSize = 10 I get this eror :
Error: could not insert module driver.ko: Invalid parameters
modinfo -p ./driver.ko command give me this :
BlockSize: size of buffer (int)
driver.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/slab.h>
/* parametter */
static int BlockNumber = 8;
static int BlockSize = 512;
module_param( variable name, type, permission); */
module_param(BlockSize, int, S_IRUGO);
MODULE_PARM_DESC(BlockSize , " size of buffer");
/* using 'k' as magic number */
#define SAMPLE_IOC_MAGIC 'k'
#define SAMPLE_IOCRESET _IOWR(SAMPLE_IOC_MAGIC, 0, int)
#define SAMPLE_IOC_MAXNR 0
struct cdev* my_cdev;
dev_t dev;
static int size_to_read;
/* Macro used to compute the minimum */
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
/* data buffer structure */
typedef struct dnode
{
int bufSize;
char *buffer;
struct dnode *next;
} data_node;
/* liste stucture */
typedef struct lnode
{
data_node *head;
data_node *cur_write_node;
data_node *cur_read_node;
int cur_read_offset;
int cur_write_offset;
}liste;
code ..........................
..
It appears that module parameters should be passed without a space between the name and value, ie you should use:
insmod driver.ko BlockSize=10
This makes some sense, as in the command line to insmod itself "BlockSize=10" is a single entry in *argv[] which can be handed off to the kernel as a chunk, while "BlockSize = 10" would be three distinct entries ("BlockSize", "=", "10") which someone would have to write code to re-join.

PDCURSES assignign value to integer make error

I'm using PDCURSES on Windows 7 and my program stops working at the beginning.
I noticed the error is made by assigning value to integer in line: 41 .
Unfortunately I have no idea why.
I'm writing in C in Code blocks.
I would be grateful if someone could help me.
Error message
#include <curses.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define ILOSC_NAZW 5
#define false 0
#define true 1
WINDOW * createwin(int height,int width,int starty,int startx);
void uaktualnij(WINDOW*left,char *nazwa);
void wyswietl_nazwy(WINDOW *right,char **losowe_nazwy);
int poprawnie=0,blednie=0;
int main()
{
char *losowe_nazwy[ILOSC_NAZW]={"JACK","TOM","KEN","JESSY","ANDRIEJ"};
char str[20];
int c,startx,starty,height,width;
WINDOW *right,*left,*console;
initscr();
refresh();
startx=0,starty=0,height=LINES/2,width=COLS/2;
left=createwin(height,width,starty,startx);
startx=COLS/2;
right=createwin(height,width,starty,startx);
startx=0;
starty=LINES/2;
width=COLS;
console=createwin(height,width,starty,startx);
getmaxyx(right,starty,startx);
uaktualnij(right,NULL);
mvwprintw(left,starty/2-starty/4,startx/2-strlen("PODAJ NAZWE UZYTKOWNIKA")/2,"PODAJ NAZWE UZYTKOWNIKA");
wrefresh(left);
wyswietl_nazwy(left,losowe_nazwy);
c=0; // assigning value make error
getmaxyx(console,starty,startx);
wmove(console,starty-2,2);
memset(str,0,sizeof *str);
wclear(console);
wborder(console,0,0,0,0,0,0,0,0);
wrefresh(console);
getch();
endwin();
return 0;
}
WINDOW * createwin(int height,int width,int starty,int startx){
WINDOW *mywin=newwin(height,width,starty,startx);
box(mywin,0,0);
wrefresh(mywin);
return mywin;
}
void czekaj(double sec){
clock_t koniec=clock()+sec*CLOCKS_PER_SEC;
while(clock()<koniec)continue;
}
void wyswietl_nazwy(WINDOW *right,char **losowe_nazwy){
int i=ILOSC_NAZW;
int rstartx,rstarty;
getmaxyx(right,rstarty,rstartx);
while( i>=0)
{
mvwprintw(right,rstarty/2-rstarty/4+2,rstartx/2-strlen(losowe_nazwy[i])/2,"%s",losowe_nazwy[i]);
wrefresh(right);
czekaj(0.2);
wmove(right,rstarty/2-rstarty/4+2,rstartx/2-strlen(losowe_nazwy[i]));
wclrtoeol(right);
mvwaddch(right,rstarty/2-rstarty/4+2,rstartx-1,ACS_VLINE);
wrefresh(right);
i--;
}
}
void uaktualnij(WINDOW*left,char *nazwa){
int startx,starty;
wclear(left);
wborder(left,0,0,0,0,0,0,0,0);
getyx(left,starty,startx);
mvwprintw(left,starty+1,startx+1,"Poprawnie: %i",poprawnie);
mvwprintw(left,starty+2,startx+1,"Blednie: %i",blednie);
if(nazwa!=NULL)
mvwprintw(left,starty+3,startx+1,"Wproawadzona nazwa uzytkowanika: %s",nazwa);
wrefresh(left);
}
Since PDCurses is written in C, I am assuming that you are compiling in C.
Move the
int c;
to just below the line
char *losowe_nazwy[ILOSC_NAZW]={"JACK","TOM","KEN","JESSY","ANDRIEJ"};
int c;
The C language expects those sorts of definitions to be at the top of the function.

Resources