Skip to content

Commit

Permalink
UID mangling functions added.
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomasz bla Fortuna committed Dec 23, 2009
1 parent 62fdf48 commit d7d40e3
Show file tree
Hide file tree
Showing 7 changed files with 479 additions and 41 deletions.
11 changes: 10 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ SET(${PROJECT_NAME}_MINOR_VERSION 1)

ADD_DEFINITIONS("-Wall -ggdb")

# Detect system
IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
ADD_DEFINITIONS("-DOS_LINUX")
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")

IF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
ADD_DEFINITIONS("-OS_FREEBSD")
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")

# Detect include dirs
FIND_PATH(GMP_INCLUDE_DIR gmp.h /usr/include/gmp /usr/local/include/gmp)
FIND_PATH(PAM_INCLUDE_DIR pam_modules.h /usr/include/security /usr/include/pam)
Expand Down Expand Up @@ -60,7 +69,7 @@ ADD_LIBRARY(pam_otpasswd SHARED pam/pam_helpers.c pam/pam_otpasswd.c)
TARGET_LINK_LIBRARIES(pam_otpasswd libotp gmp ssl pam)

# Password management target
ADD_EXECUTABLE(otpasswd utility/otpasswd.c utility/otpasswd_actions.c utility/testcases.c)
ADD_EXECUTABLE(otpasswd utility/otpasswd.c utility/otpasswd_actions.c utility/testcases.c utility/security.c)
TARGET_LINK_LIBRARIES(otpasswd libotp gmp ssl)

##
Expand Down
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Trying to sort tasks according to their priority.
to conversation function. If not, we must build a buffer
(See for example how winscp shows that warning)
* [?] Use PAM_SERVICE_ERR
* [?] Check if OOB script is not SUID?
* [-] right trim values from config?

Low-priority:
Expand Down
90 changes: 90 additions & 0 deletions tests/lock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#define LOCK_FILE ".otpasswd.lck"
int fd = -1;

int lock()
{
struct flock fl;

fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = fl.l_len = 0;

fd = open(LOCK_FILE, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);

if (fd == -1) {
/* Unable to create file, therefore unable to obtain lock */
perror("open");
printf("Unable to open a state file\n");
return 1;
}

if (fcntl(fd, F_SETLK, &fl) == 0) {
printf("Locked\n");
return 0;
}

close(fd);
printf("Unable to lock\n");
return 1;
}

void overwrite()
{
FILE *f = fopen(LOCK_FILE, "w");
if (!f) {
printf("Unable to open for overwrite\n");
return;
}
fprintf(f, "Dupablada\n");
if (fflush(f) != 0) {
printf("Unable to fflush\n");
}
fclose(f);
}

int unlock()
{
struct flock fl;

if (fd < 0) {
printf("No lock to release!\n");
return 1;
}

fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;
fl.l_start = fl.l_len = 0;

int ret = fcntl(fd, F_SETLK, &fl);

close(fd);
fd = -1;

if (ret != 0) {
printf("Strange error while releasing lock\n");
/* Strange error while releasing the lock */
return 1;
}

return 0;
}

int main(int argc, char **argv)
{
if (lock() != 0) {
return 1;
}

// overwrite();
printf("Waiting for keypress\n"); getchar();
unlock();
return 0;
}
153 changes: 153 additions & 0 deletions tests/suid.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@

#define _GNU_SOURCE /* For setres* */

#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>

static int real_uid;
static int set_uid;

static int real_gid;
static int set_gid;

void init()
{
real_uid = getuid();
set_uid = geteuid();

real_gid = getgid();
set_gid = getegid();
}

void print(void)
{
int uid, euid;
int gid, egid;

uid = getuid();
euid = geteuid();

gid = getgid();
egid = getegid();

printf("UID/eUID: %d/%d GID/eGID: %d/%d\n", uid, euid, gid, egid);
}


void check_perms(void)
{
printf("Checking root perms! ");
print();

FILE *f = fopen("/etc/shadow", "r");
if (!f) {
printf("We do not have root access permissions\n");
} else {
fclose(f);
printf("Root permissions\n");
}
}

void drop_temporarily(void)
{
/* On systems without setres* use setre*. But make sure it works */
const int gid = getgid(), uid = getuid();
const int egid = getegid(), euid = geteuid();

if (setresuid(uid, uid, euid) != 0)
goto error;
if (setresgid(gid, gid, egid) != 0)
goto error;

/* Paranoid check */
if (geteuid() != getuid() || getegid() != getgid()) {
printf("d_t: fun\n");
goto error;
}
return;
error:
printf("d_t: failure\n");
exit(EXIT_FAILURE);
}

void drop_pernamently(void)
{
/* On systems without setres* use setre*. But make sure it works */
const int gid = getgid(), uid = getuid();

if (setresuid(uid, uid, uid) != 0)
goto error;
if (setresgid(gid, gid, gid) != 0)
goto error;

/* Paranoid check */
if (geteuid() != getuid() || getegid() != getgid()) {
printf("d_t: fun\n");
goto error;
}

return;
error:
printf("d_p: failure\n");
exit(EXIT_FAILURE);
}

void restore(void)
{
/* On systems without setres* use setre*. But make sure it works */

/* 0 should be remembered before! */
if (setresuid(real_uid, set_uid, set_uid) != 0)
goto error;
if (setresgid(real_gid, set_gid, set_gid) != 0)
goto error;

/* Paranoid check */
if (geteuid() != set_uid || getegid() != set_gid) {
printf("d_t: fun\n");
goto error;
}

return;
error:
printf("d_p: failure\n");
exit(EXIT_FAILURE);
}

int main(int argc, char **argv)
{
clearenv();

init();

printf("Initial: ");
print();

check_perms();

printf("* TEMPORARY DROP \n");
drop_temporarily();

check_perms();

printf("* RESTORE \n");
restore();

check_perms();

printf("* PERNAMENT DROP \n");
drop_pernamently();

check_perms();


printf("* RESTORE (we should fail now) \n");
restore();

check_perms();


return 0;
}
55 changes: 15 additions & 40 deletions utility/otpasswd.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@
#include <assert.h>
#include <unistd.h> /* chdir, environ */

/* umask */
#include <sys/types.h>
#include <sys/stat.h>
#include "security.h"

#include "print.h"
#include "crypto.h"
Expand Down Expand Up @@ -398,37 +396,8 @@ int main(int argc, char **argv)
{
int ret;
cfg_t *cfg = NULL;
int uid = getuid(), gid = getgid();

/* As we might be SUID/SGID binary. Clear environment. */
ret = clearenv();
if (ret != 0) {
printf("Unable to clear environment\n");
exit(EXIT_FAILURE);
}

ret = chdir("/");
if (ret != 0) {
printf("Unable to change directory to /\n");
exit(EXIT_FAILURE);
}

if (environ != NULL || (environ && *environ != NULL)) {
printf("Environment not clear!\n");
exit(EXIT_FAILURE);
}

putenv("PATH=/bin:/usr/bin");

/* Set umask so others won't read our files */
if (gid != getegid()) {
/* We are SGID. Don't remove bits from group... */
umask(S_IWOTH | S_IROTH | S_IXOTH);
}
else {
/* Normal or SUID */
umask(S_IWOTH | S_IROTH | S_IXOTH | S_IWGRP | S_IRGRP | S_IXGRP);
}
security_init();

/* Bootstrap logging subsystem. */
if (print_init(PRINT_ERROR, 1, 0, NULL) != 0) {
Expand All @@ -446,15 +415,21 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}

/* If database is not global we can drop permissions now */
/* If database is not global we can drop _pernamently_ permissions now */
if (cfg->db != CONFIG_DB_GLOBAL) {
ret = setgid(gid);
ret += setuid(uid);
if (ret != 0) {
printf("Strange error while dropping permissions\n");
exit(EXIT_FAILURE);
}
security_permanent_drop();
} else {
/* Otherwise - drop them temporarily */
security_temporal_drop();
}

/* TODO/FIXME: If we are SGID and not SUID is there a problem with
* receiving a signal at stupid point of time? */

#ifdef OS_LINUX
/* Drop all permissions except for fsuid? Is it possible? */
#endif

ret = process_cmd_line(argc, argv);
return ret;
}
Loading

0 comments on commit d7d40e3

Please sign in to comment.