first commit
This commit is contained in:
commit
b63786cc92
274
.clang-format
Normal file
274
.clang-format
Normal file
@ -0,0 +1,274 @@
|
||||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCaseArrows: false
|
||||
AlignCaseColons: false
|
||||
AlignConsecutiveTableGenBreakingDAGArgColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveTableGenCondOperatorColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveTableGenDefinitionColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments:
|
||||
Kind: Always
|
||||
OverEmptyLines: 0
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowBreakBeforeNoexceptSpecifier: Never
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseExpressionOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortCompoundRequirementOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: All
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BitFieldColonSpacing: Both
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterControlStatement: Always
|
||||
AfterEnum: true
|
||||
AfterExternBlock: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterObjCDeclaration: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: true
|
||||
IndentBraces: true
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakAdjacentStringLiterals: true
|
||||
BreakAfterAttributes: Leave
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakAfterReturnType: AllDefinitions
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: All
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeBraces: GNU
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakFunctionDefinitionParameters: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakStringLiterals: true
|
||||
BreakTemplateDeclarations: MultiLine
|
||||
ColumnLimit: 79
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: false
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: false
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: false
|
||||
InsertNewlineAtEOF: false
|
||||
InsertTrailingCommas: None
|
||||
IntegerLiteralSeparator:
|
||||
Binary: 0
|
||||
BinaryMinDigits: 0
|
||||
Decimal: 0
|
||||
DecimalMinDigits: 0
|
||||
Hex: 0
|
||||
HexMinDigits: 0
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLines:
|
||||
AtEndOfFile: false
|
||||
AtStartOfBlock: true
|
||||
AtStartOfFile: true
|
||||
LambdaBodyIndentation: Signature
|
||||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MainIncludeChar: Quote
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PackConstructorInitializers: BinPack
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakScopeResolution: 500
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
PPIndentWidth: -1
|
||||
QualifierAlignment: Leave
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
RemoveBracesLLVM: false
|
||||
RemoveParentheses: Leave
|
||||
RemoveSemicolon: false
|
||||
RequiresClausePosition: OwnLine
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SkipMacroDefinitionBody: false
|
||||
SortIncludes: CaseSensitive
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: LexicographicNumeric
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeJsonColon: false
|
||||
SpaceBeforeParens: Always
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: false
|
||||
AfterForeachMacros: false
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: false
|
||||
AfterOverloadedOperator: false
|
||||
AfterPlacementOperator: true
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParens: Never
|
||||
SpacesInParensOptions:
|
||||
ExceptDoubleParentheses: false
|
||||
InCStyleCasts: false
|
||||
InConditionalStatements: false
|
||||
InEmptyParentheses: false
|
||||
Other: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: c++03
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TableGenBreakInsideDAGArg: DontBreak
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
VerilogBreakBetweenInstancePorts: true
|
||||
WhitespaceSensitiveMacros:
|
||||
- BOOST_PP_STRINGIZE
|
||||
- CF_SWIFT_NAME
|
||||
- NS_SWIFT_NAME
|
||||
- PP_STRINGIZE
|
||||
- STRINGIZE
|
||||
...
|
||||
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
*.o
|
||||
#*#
|
||||
*~
|
||||
bin/beroot
|
34
Makefile
Normal file
34
Makefile
Normal file
@ -0,0 +1,34 @@
|
||||
CC=gcc
|
||||
ECHO=echo -e
|
||||
|
||||
CFLAGS=-Wall -Werror -std=gnu99 -O0 -g
|
||||
LIBS=-lcrypt
|
||||
|
||||
FILES=build/main.o
|
||||
OUT=bin/beroot
|
||||
|
||||
all: $(FILES)
|
||||
@$(ECHO) "Linking program"
|
||||
@$(CC) $(CFLAGS) $(FILES) -o $(OUT) $(LIBS)
|
||||
@$(ECHO) "Linking finished"
|
||||
|
||||
build/main.o: src/main.c src/config.h
|
||||
@$(ECHO) "CC\t\t"$<
|
||||
@$(CC) $(CFLAGS) $< -c -o $@ $(LIBS)
|
||||
|
||||
install: all
|
||||
@$(ECHO) "Installing beroot (you MUST be root to install beroot)"
|
||||
@cp $(OUT) /usr/bin
|
||||
@chown root:root /usr/bin/beroot # set permissions
|
||||
@chmod u+s /usr/bin/beroot
|
||||
@$(ECHO) "Installation successful"
|
||||
|
||||
uninstall: all
|
||||
@$(ECHO) "Uninstalling beroot (you MUST be root to uninstall beroot)"
|
||||
@rm -f /usr/bin/beroot
|
||||
@$(ECHO) "Uninstallation successful"
|
||||
|
||||
clean:
|
||||
@$(ECHO) "Cleaning files..."
|
||||
@rm -f $(FILES) $(OUT)
|
||||
@$(ECHO) "Cleaning complete :)"
|
102
Readme.org
Normal file
102
Readme.org
Normal file
@ -0,0 +1,102 @@
|
||||
* Beroot
|
||||
|
||||
Beroot is just another privilege escalation tool. I made Beroot for two reasons:
|
||||
- I wanted to learn (I discovered a lot of new functions in the standard
|
||||
library)
|
||||
- Sudo is bloated, and wanted to do something smaller - but usable - than doas.
|
||||
|
||||
** Usage
|
||||
|
||||
Beroot is just two files: ~main.c~ the source of beroot, ~config,h~ the
|
||||
configurations of the tool. Beroot doesn't have any ~.conf~ files that need to be
|
||||
parsed or something similar, all the changes are made to the ~config.h~ file.
|
||||
|
||||
First, you'll need to build the program:
|
||||
|
||||
#+begin_src bash
|
||||
make
|
||||
#+end_src
|
||||
|
||||
Now, you'll need to login as root to execute the following commands:
|
||||
|
||||
#+begin_src bash
|
||||
make install
|
||||
#+end_src
|
||||
|
||||
That command will copy ~./bin/beroot~ to ~/usr/bin~ and set the appropriate permissions to it.
|
||||
|
||||
** Configuration
|
||||
|
||||
The only thing you need to modify is the ~permissions~ variable in ~config.h~. This
|
||||
file contains the following structure:
|
||||
|
||||
#+begin_src C
|
||||
struct user_permissions
|
||||
{
|
||||
const char name[16384];
|
||||
const char target_user[16384];
|
||||
unsigned char permissions;
|
||||
};
|
||||
#+end_src
|
||||
|
||||
It only has three fields:
|
||||
- ~name~: The name of the user you expect can use beroot (like the ones that
|
||||
belong to the ~wheel~ group)
|
||||
- ~target_user~: In case you want a user not to be root, but rather a different
|
||||
user that exists on the machine, you can specify their name using this
|
||||
variable.
|
||||
- ~permissions~: Here you can set some of the following permission bits:
|
||||
- ~PERM_ROOT~: If this is set, the user will execute commands as root,
|
||||
~target_user~ will be ignored in this case.
|
||||
- ~PERM_USER~: If this bit is present, the user will execute commands as
|
||||
~target_user~ instead of root. If both ~PERM_ROOT~ and ~PERM_USER~ are present,
|
||||
the last one is ignored as ~PERM_ROOT~ is checked first in the code.
|
||||
- ~PERM_PASSWD~: If this is set, beroot will ask for the target user password
|
||||
every time that the command is ran.
|
||||
- ~PERM_NOPASSWD~: If this bit is present, beroot won't ask for the target user
|
||||
password, it will just execute the specified command. Notice that either
|
||||
~PERM_PASSWD~ or ~PERM_NOPASSWD~ must be present, if none of them are, beroot
|
||||
will display an error.
|
||||
|
||||
For example, if we have a user called ~lain~ and we want this user to execute
|
||||
commands as root, and not ask for a password, we'd add the following to the
|
||||
~permissions~ variable in ~config.h~:
|
||||
|
||||
#+begin_src C
|
||||
const static struct user_permissions permissions[] = {
|
||||
{ .name = "lain",
|
||||
.target_user = "\0",
|
||||
.permissions = PERM_ROOT | PERM_NOPASSWD }
|
||||
};
|
||||
#+end_src
|
||||
|
||||
In that case, we are setting the user ~lain~ with the permissions of ~PERM_ROOT~
|
||||
(execute commands as root) and ~PERM_NOPASSWD~ (don't ask for a password).
|
||||
|
||||
If we want to have multiple rules, we can just separate them by a comma (,):
|
||||
|
||||
#+begin_src C
|
||||
const static struct user_permissions permissions[]
|
||||
= { { .name = "lain",
|
||||
.target_user = "\0",
|
||||
.permissions = PERM_ROOT | PERM_NOPASSWD },
|
||||
{ .name = "alyssa",
|
||||
.target_user = "dbuser",
|
||||
.permissions = PERM_USER | PERM_PASSWD } };
|
||||
#+end_src
|
||||
|
||||
In that code now we have two users: ~lain~ with the settings we mentioned before,
|
||||
and a new user ~alyssa~ that will execute commands as ~dbuser~ and ~PERM_PASSWD~ will
|
||||
make that she has to enter her password every time she runs ~beroot~.
|
||||
|
||||
** TODO
|
||||
|
||||
I don't want to make this a big program, I want to keep everything as simple as
|
||||
possible, but there are some things that I want to do:
|
||||
- Optimise the code, I wrote this in like 1 hour just to test things in the
|
||||
standard library.
|
||||
- Some kind of persistency (there can be a ~PERM_PERSIST~ flag) so the password
|
||||
doesn't need to be entered every time.
|
||||
- Hide the password while it's being typed.
|
||||
|
||||
Those are the only things I have planned adding to beroot.
|
0
bin/.gitkeep
Normal file
0
bin/.gitkeep
Normal file
0
build/.gitkeep
Normal file
0
build/.gitkeep
Normal file
25
src/config.h
Normal file
25
src/config.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef __CONFIG_H
|
||||
#define __CONFIG_H
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#define LOGIN_PASSWD_MAX 16384 // i think this is enough for a password?
|
||||
|
||||
#define PERM_ROOT 1 << 0 /* will be the root user */
|
||||
#define PERM_USER 1 << 1 /* will be a custom specified user */
|
||||
#define PERM_PASSWD 1 << 2 /* password is required */
|
||||
#define PERM_NOPASSWD 1 << 3 /* password is not required */
|
||||
|
||||
struct user_permissions
|
||||
{
|
||||
const char name[LOGIN_NAME_MAX];
|
||||
const char target_user[LOGIN_NAME_MAX];
|
||||
unsigned char permissions;
|
||||
};
|
||||
|
||||
const static struct user_permissions permissions[]
|
||||
= { { .name = "lain",
|
||||
.target_user = "\0",
|
||||
.permissions = PERM_ROOT | PERM_NOPASSWD } };
|
||||
|
||||
#endif
|
181
src/main.c
Normal file
181
src/main.c
Normal file
@ -0,0 +1,181 @@
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pwd.h>
|
||||
#include <shadow.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
void
|
||||
print_usage ()
|
||||
{
|
||||
puts ("usage: beroot command [args]");
|
||||
}
|
||||
|
||||
char *
|
||||
get_current_user_name ()
|
||||
{
|
||||
struct passwd *pwd = getpwuid (getuid ());
|
||||
if (!pwd)
|
||||
{
|
||||
puts ("couldn't obtain your pwd");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pwd->pw_name;
|
||||
}
|
||||
|
||||
const struct user_permissions *
|
||||
user_in_permitted_users (char *name)
|
||||
{
|
||||
int total_users
|
||||
= (int)(sizeof (permissions) / sizeof (struct user_permissions));
|
||||
|
||||
for (int i = 0; i < total_users; i++)
|
||||
{
|
||||
const struct user_permissions *current_user = &permissions[i];
|
||||
if (!current_user)
|
||||
continue;
|
||||
|
||||
if (strncmp (name, current_user->name, LOGIN_NAME_MAX) == 0)
|
||||
return current_user;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct spwd *
|
||||
obtain_target_swpd (const char *name)
|
||||
{
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
return getspnam (name);
|
||||
}
|
||||
|
||||
_Bool
|
||||
authenticate_user (char *password, char *entered_password)
|
||||
{
|
||||
// the entered password ends with a \n, we remove it here
|
||||
entered_password[strcspn (entered_password, "\n")] = '\0';
|
||||
size_t password_len = strlen (password);
|
||||
|
||||
char *encrypted_password = crypt (entered_password, password);
|
||||
int result = strncmp (password, encrypted_password, password_len);
|
||||
if (result == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
execute (char **command)
|
||||
{
|
||||
size_t total_commands = 0;
|
||||
size_t maximum_commands = 10;
|
||||
char **commands = calloc (sizeof (char *), maximum_commands);
|
||||
if (!commands)
|
||||
{
|
||||
fputs ("Couldn't parse the commands\n", stderr);
|
||||
return;
|
||||
}
|
||||
|
||||
while (*command != NULL)
|
||||
{
|
||||
if (total_commands >= maximum_commands)
|
||||
{
|
||||
maximum_commands *= 2;
|
||||
commands = realloc (commands, sizeof (char *) * maximum_commands);
|
||||
}
|
||||
|
||||
commands[total_commands] = *command;
|
||||
|
||||
command++;
|
||||
total_commands++;
|
||||
}
|
||||
|
||||
commands[total_commands] = NULL;
|
||||
execvp (commands[0], commands);
|
||||
|
||||
free (commands);
|
||||
commands = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
print_usage ();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
char *user_name = get_current_user_name ();
|
||||
if (!user_name)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
const struct user_permissions *user = user_in_permitted_users (user_name);
|
||||
if (!user)
|
||||
{
|
||||
fprintf (stderr, "%s is not allowed to run commands, aborting\n",
|
||||
user_name);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
struct spwd *target_swpd = user->permissions & PERM_ROOT
|
||||
? obtain_target_swpd ("root")
|
||||
: obtain_target_swpd (user->target_user);
|
||||
if (!target_swpd)
|
||||
{
|
||||
fputs ("couldn't obtain the target user's shadow\n", stderr);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
struct passwd *target_passwd = getpwnam (target_swpd->sp_namp);
|
||||
if (!target_passwd)
|
||||
{
|
||||
fputs ("couldn't obtain the passwd for the target user\n", stderr);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// TODO: Give the user 3 attempts
|
||||
_Bool is_authenticated = 0;
|
||||
if (user->permissions & PERM_NOPASSWD)
|
||||
{
|
||||
is_authenticated = 1;
|
||||
}
|
||||
else if (user->permissions & PERM_PASSWD)
|
||||
{
|
||||
printf ("Enter the %s password: ", user->target_user);
|
||||
char entered_password[LOGIN_PASSWD_MAX] = { 0 };
|
||||
fgets (entered_password, LOGIN_PASSWD_MAX - 1, stdin);
|
||||
is_authenticated
|
||||
= authenticate_user (target_swpd->sp_pwdp, entered_password);
|
||||
}
|
||||
else
|
||||
{
|
||||
fputs (
|
||||
"Please specify an authentication way, either PASSWD or NOPASSWD\n",
|
||||
stderr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!is_authenticated)
|
||||
{
|
||||
fputs ("Couldn't authenticate you, please try again\n", stderr);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (setuid (target_passwd->pw_uid) != 0)
|
||||
{
|
||||
fputs ("Couldn't switch to the target user\n", stderr);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
execute (argv + 1);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user