Added source code

This commit is contained in:
Eric-Paul Ickhorn 2023-10-07 09:12:30 +02:00
parent d1186a6dd5
commit 22dcaa9714
5 changed files with 281 additions and 1 deletions

View File

@ -1,3 +1,24 @@
# 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.

67
build.bash Normal file
View File

@ -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"

35
inc/libparzel_shadow.h Normal file
View File

@ -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

16
main.c Normal file
View File

@ -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);
}

141
src/shadow_parser.c Normal file
View File

@ -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;
}