Added source code
This commit is contained in:
parent
d1186a6dd5
commit
22dcaa9714
23
README.md
23
README.md
|
@ -1,3 +1,24 @@
|
||||||
# libparzel-shadow
|
# libparzel-shadow
|
||||||
|
|
||||||
A parser for the /etc/shadow - file on Linux systems
|
A simple parser for reading the `/etc/shadow`-file on a linux-system.
|
||||||
|
The API should be self-explanatory for anyone in the know of the concept
|
||||||
|
of iterators.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
Run `bash build.bash <PROFILE>` where profile can be one of `small`,
|
||||||
|
`release` or `debug`. Alternatively, the script can just be started for getting
|
||||||
|
a prompt of what should be done.
|
||||||
|
|
||||||
|
After that, the binary files can be removed using `bash build.bash cleanup`.
|
||||||
|
|
||||||
|
## Test Executable
|
||||||
|
|
||||||
|
The test executable writes out the names of all users in the file at `/etc/shadow`
|
||||||
|
to STDOUT. It needs superuser permission.
|
||||||
|
|
||||||
|
## TO-DO
|
||||||
|
|
||||||
|
Currently, only the user can be read out by the parser. More isn't needed
|
||||||
|
at the moment. Once more is needed, it will be done.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
mkdir -p build/
|
||||||
|
|
||||||
|
build_debug() {
|
||||||
|
gcc -g -c -o build/shadow_parser.o src/shadow_parser.c -I inc/
|
||||||
|
|
||||||
|
ar -rvs build/libparzel-shadow.a \
|
||||||
|
build/shadow_parser.o
|
||||||
|
mv build/libparzel-shadow.a .
|
||||||
|
|
||||||
|
gcc -g -o write_shadow_names.elf main.c libparzel-shadow.a -I inc/
|
||||||
|
}
|
||||||
|
|
||||||
|
build_fast() {
|
||||||
|
gcc -O3 -c -o build/shadow_parser.o src/shadow_parser.c -I inc/
|
||||||
|
|
||||||
|
ar -rvs build/libparzel-shadow.a \
|
||||||
|
build/shadow_parser.o
|
||||||
|
mv build/libparzel-shadow.a .
|
||||||
|
|
||||||
|
gcc -O3 -o write_shadow_names.elf main.c libparzel-shadow.a -I inc/
|
||||||
|
}
|
||||||
|
|
||||||
|
build_small() {
|
||||||
|
gcc -Os -c -o build/shadow_parser.o src/shadow_parser.c -I inc/
|
||||||
|
|
||||||
|
ar -rvs build/libparzel-shadow.a \
|
||||||
|
build/shadow_parser.o
|
||||||
|
mv build/libparzel-shadow.a .
|
||||||
|
|
||||||
|
gcc -Os -o write_shadow_names.elf main.c libparzel-shadow.a -I inc/
|
||||||
|
}
|
||||||
|
|
||||||
|
BUILD_PROFILE=$1
|
||||||
|
REMAINING_TRIES=3
|
||||||
|
|
||||||
|
while [[ $REMAINING_TRIES > 0 ]] do
|
||||||
|
case $BUILD_PROFILE in
|
||||||
|
"debug")
|
||||||
|
build_debug
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
"release" | "fast")
|
||||||
|
build_fast
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
"small")
|
||||||
|
build_small
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
"cleanup")
|
||||||
|
rm write_shadow_names.elf
|
||||||
|
rm libparzel-shadow.a
|
||||||
|
rm -r build/
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
printf "Profile (debug | release | small): "
|
||||||
|
read BUILD_PROFILE
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
let REMAINING_TRIES--
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Tries exhausted"
|
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
#ifndef LIBPARZEL_SHADOW_H
|
||||||
|
#define LIBPARZEL_SHADOW_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct shadow_user
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
} shadow_user_s;
|
||||||
|
|
||||||
|
typedef struct shadow_iterator
|
||||||
|
{
|
||||||
|
uint32_t num_users;
|
||||||
|
shadow_user_s *users;
|
||||||
|
|
||||||
|
int32_t index;
|
||||||
|
|
||||||
|
} shadow_iterator_s;
|
||||||
|
|
||||||
|
shadow_iterator_s shadow_parse (char *source, uint32_t len_source);
|
||||||
|
shadow_iterator_s shadow_new_iterator (char *path);
|
||||||
|
void shadow_cleanup (shadow_iterator_s iterator);
|
||||||
|
|
||||||
|
bool shadow_next_user (shadow_iterator_s *iterator, shadow_user_s *user);
|
||||||
|
void shadow_rewind (shadow_iterator_s *iterator);
|
||||||
|
void shadow_seek (shadow_iterator_s *iterator, int32_t distance);
|
||||||
|
|
||||||
|
uint32_t shadow_length (shadow_iterator_s *iterator);
|
||||||
|
uint32_t shadow_remaining (shadow_iterator_s *iterator);
|
||||||
|
|
||||||
|
#endif // SHADOW_PARSER_H
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include <libparzel_shadow.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
shadow_iterator_s iterator = shadow_new_iterator("/etc/shadow");
|
||||||
|
|
||||||
|
shadow_user_s user;
|
||||||
|
while(shadow_next_user(&iterator, &user))
|
||||||
|
{
|
||||||
|
printf("User's Name: %s\n", user.name);
|
||||||
|
}
|
||||||
|
shadow_cleanup(iterator);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
#include <libparzel_shadow.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
shadow_iterator_s shadow_parse(char *source, uint32_t len_source)
|
||||||
|
{
|
||||||
|
uint32_t users_capacity = 32;
|
||||||
|
|
||||||
|
shadow_iterator_s iterator;
|
||||||
|
iterator.users = malloc(sizeof(shadow_user_s) * users_capacity);
|
||||||
|
iterator.num_users = 0;
|
||||||
|
iterator.index = 0;
|
||||||
|
|
||||||
|
uint32_t index = 0;
|
||||||
|
while(index < len_source)
|
||||||
|
{
|
||||||
|
if(iterator.num_users >= users_capacity)
|
||||||
|
{
|
||||||
|
users_capacity *= 2;
|
||||||
|
iterator.users = realloc(iterator.users, sizeof(shadow_user_s) * users_capacity);
|
||||||
|
}
|
||||||
|
uint32_t name_start = index;
|
||||||
|
|
||||||
|
// Extract username
|
||||||
|
while(index < len_source)
|
||||||
|
{
|
||||||
|
if(source[index] == ':') break;
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
uint32_t len_name = index - name_start;
|
||||||
|
|
||||||
|
shadow_user_s user;
|
||||||
|
user.name = malloc(len_name+1);
|
||||||
|
memcpy(user.name, &source[name_start], len_name);
|
||||||
|
user.name[len_name] = 0;
|
||||||
|
|
||||||
|
iterator.users[iterator.num_users] = user;
|
||||||
|
++iterator.num_users;
|
||||||
|
|
||||||
|
// Skip to newline
|
||||||
|
while(index < len_source)
|
||||||
|
{
|
||||||
|
if(source[index] == '\n') break;
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
free(source);
|
||||||
|
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
shadow_iterator_s shadow_new_iterator(char *path)
|
||||||
|
{
|
||||||
|
FILE *file = fopen(path, "r");
|
||||||
|
|
||||||
|
if(file == NULL)
|
||||||
|
{
|
||||||
|
printf("Error in %s at line %u!\n", __FILE__, __LINE__);
|
||||||
|
printf("Failed opening file: %s\n", path);
|
||||||
|
shadow_iterator_s invalid_iterator;
|
||||||
|
invalid_iterator.index = -1;
|
||||||
|
invalid_iterator.num_users = 0;
|
||||||
|
invalid_iterator.users = NULL;
|
||||||
|
return invalid_iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
uint32_t len_file = ftell(file);
|
||||||
|
fseek(file, 0, SEEK_SET);
|
||||||
|
|
||||||
|
char *source = malloc(len_file+1);
|
||||||
|
if(fread(source, len_file, 1, file) == 0)
|
||||||
|
{
|
||||||
|
puts("Read wrong amount of bytes!");
|
||||||
|
}
|
||||||
|
source[len_file] = 0x00;
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return shadow_parse(source, len_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shadow_cleanup(shadow_iterator_s iterator)
|
||||||
|
{
|
||||||
|
uint32_t index = 0;
|
||||||
|
while(index < iterator.num_users)
|
||||||
|
{
|
||||||
|
free(iterator.users[index].name);
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
free(iterator.users);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool shadow_next_user(shadow_iterator_s *iterator, shadow_user_s *user)
|
||||||
|
{
|
||||||
|
if(iterator->index >= iterator->num_users)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
(*user) = iterator->users[iterator->index];
|
||||||
|
++iterator->index;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shadow_rewind(shadow_iterator_s *iterator)
|
||||||
|
{
|
||||||
|
iterator->index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shadow_seek(shadow_iterator_s *iterator, int32_t distance)
|
||||||
|
{
|
||||||
|
iterator->index += distance;
|
||||||
|
if(iterator->index > iterator->num_users)
|
||||||
|
{
|
||||||
|
iterator->index = iterator->num_users;
|
||||||
|
}
|
||||||
|
if(iterator->index < 0)
|
||||||
|
{
|
||||||
|
iterator->index = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t shadow_length(shadow_iterator_s *iterator)
|
||||||
|
{
|
||||||
|
return iterator->num_users;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t shadow_remaining(shadow_iterator_s *iterator)
|
||||||
|
{
|
||||||
|
return iterator->num_users - iterator->index;
|
||||||
|
}
|
||||||
|
|
Reference in New Issue