Added source code
This commit is contained in:
parent
d1186a6dd5
commit
22dcaa9714
23
README.md
23
README.md
|
@ -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.
|
||||
|
||||
|
|
|
@ -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