diff options
Diffstat (limited to 'hw1/session.c')
-rw-r--r-- | hw1/session.c | 84 |
1 files changed, 83 insertions, 1 deletions
diff --git a/hw1/session.c b/hw1/session.c index dd416a8..40a0e65 100644 --- a/hw1/session.c +++ b/hw1/session.c @@ -8,6 +8,7 @@ #include "socktool.h" #include "connection.h" #include "server.h" +#include "basic-array.h" #include <errno.h> #include <grp.h> @@ -92,7 +93,7 @@ int ras_session_read_header (RasSession* session) { next = oneline + onelinelen; } else { *space = '\0'; - for (space++; *space != '\0' && *space != ' '; space++); + for (space++; *space == '\0' && *space == ' '; space++); next = space; } @@ -110,6 +111,87 @@ int ras_session_read_header (RasSession* session) { return -1; } + struct passwd* login_user = NULL; + if (*next != '\0') { + login_user = getpwnam (next); + if (login_user == NULL) { + const char baduser_msg[] = "Error: User not found.\n"; + const int baduser_len = STATIC_STRLEN (baduser_msg); + ras_socktool_write_string (RAS_CONN (session)->fd, baduser_msg, baduser_len); + ras_session_log (session, "user %s cannot be found", next); + free (oneline); + return -1; + } + } + + free (oneline); + + if (RAS_CONN (session)->perm == RAS_CONN_PERM_RESTRICTED) { + uid_t real_uid = getuid (); + if (login_user != NULL && login_user->pw_uid != real_uid) { + const char rest_msg[] = "Error: You are not permitted to login from here.\n"; + const int rest_len = STATIC_STRLEN (rest_msg); + ras_socktool_write_string (RAS_CONN (session)->fd, rest_msg, rest_len); + ras_session_log (session, "user %s is not permitted", login_user->pw_name); + return -1; + } + setuid (real_uid); + } else { + const char sufail_msg[] = "Error: Unable to change the user credential.\n"; + const int sufail_len = STATIC_STRLEN (sufail_msg); + int rval; + +#if defined(HAVE_INITGROUPS) + rval = initgroups (login_user->pw_name, login_user->pw_gid); +#elif defined(HAVE_SETGROUPS) + struct group* groupentry; + Array* grouplist = array_create (sizeof (gid_t), 1); + int errno_saved; + + array_pushback (grouplist, &login_user->pw_gid); + setgrent (); + while ((groupentry = getgrent ()) != NULL) { + for (int i = 0; groupentry->gr_mem[i] != NULL; i++) { + if (strcmp (groupentry->gr_mem[i], login_user->pw_name) == 0) { + array_pushback (grouplist, &groupentry->gr_gid); + } + } + } + endgrent (); + + rval = setgroups (array_getlen (grouplist), array_data (grouplist)); + + errno_saved = errno; + array_free (grouplist); + errno = errno_saved; +#endif + + if (rval < 0) { + write (RAS_CONN (session)->fd, sufail_msg, sufail_len); + ras_session_log (session, + "cannot set supplementary groups: %s", strerror (errno)); + return -1; + } + + rval = setgid (login_user->pw_gid); + if (rval < 0) { + write (RAS_CONN (session)->fd, sufail_msg, sufail_len); + ras_session_log (session, + "cannot set primary group to %d: %s", + login_user->pw_gid, strerror (errno)); + return -1; + } + + rval = setuid (login_user->pw_uid); + if (rval < 0) { + write (RAS_CONN (session)->fd, sufail_msg, sufail_len); + ras_session_log (session, + "cannot set user to %s (uid = %d): %s", + login_user->pw_name, login_user->pw_uid, strerror (errno)); + return -1; + } + } + return 0; } |