# HG changeset patch # User stellarpower # Date 1519092715 0 # Node ID ed930fd6f60f35ad4f83a4cf05a433a8a593f778 # Parent 47fcbdd12d9b9921222cb0858d45e31fd77d7e70 Added the -G option to allow logins only for users that are members of a certain group. This allows finer control of an instance on who can and cannot login over a certain instance (e.g. password and not key). Needs double-checking and ensuring it meets platform requirements. diff -r 47fcbdd12d9b -r ed930fd6f60f runopts.h --- a/runopts.h Mon Feb 19 23:04:46 2018 +0800 +++ b/runopts.h Tue Feb 20 02:11:55 2018 +0000 @@ -92,6 +92,8 @@ #endif int norootlogin; + char *grouploginname; + gid_t *grouploginid; int noauthpass; int norootpass; diff -r 47fcbdd12d9b -r ed930fd6f60f svr-auth.c --- a/svr-auth.c Mon Feb 19 23:04:46 2018 +0800 +++ b/svr-auth.c Tue Feb 20 02:11:55 2018 +0000 @@ -25,6 +25,8 @@ /* This file (auth.c) handles authentication requests, passing it to the * particular type (auth-passwd, auth-pubkey). */ +#include + #include "includes.h" #include "dbutil.h" #include "session.h" @@ -232,6 +234,10 @@ char* listshell = NULL; char* usershell = NULL; uid_t uid; + int ngroups = 32, ret; + gid_t *grouplist; + + TRACE(("enter checkusername")) if (userlen > MAX_USERNAME_LEN) { return DROPBEAR_FAILURE; @@ -278,6 +284,46 @@ return DROPBEAR_FAILURE; } + /* check for login restricted to certain group if desired */ + if (svr_opts.grouploginid) { + + for ( ; (ngroups <= NGROUPS_MAX) && (ngroups <= INT_MAX / 8); ngroups *= 2){ + + grouplist = malloc(sizeof(gid_t) * ngroups); + + ret = getgrouplist(ses.authstate.pw_name, ses.authstate.pw_gid, grouplist, &ngroups); + + if (ret != -1){ + break; + } + + free(grouplist); + ngroups *= 2; + } + + if ((ngroups > NGROUPS_MAX / 8) || (ngroups > INT_MAX / 8)){ + + TRACE(("Cannot walk group structure for current user, too many groups")) + dropbear_log(LOG_ERR, "Cannot walk group structure for current user, too many groups"); + return DROPBEAR_FAILURE; + } + + ngroups = 0; + for (int i = 0; i < ret; i++){ + if (grouplist[i] == *svr_opts.grouploginid){ + ngroups = 1; //Just used as a flag to indicate success; + break; + } + + } + + if (!ngroups){ + TRACE(("leave checkusername: user not in permitted group")) + dropbear_log(LOG_WARNING, "logins are restricted to the group %s but user %s is not a member", svr_opts.grouploginname, ses.authstate.pw_name); + return DROPBEAR_FAILURE; + } + } + TRACE(("shell is %s", ses.authstate.pw_shell)) /* check that the shell is set */ diff -r 47fcbdd12d9b -r ed930fd6f60f svr-runopts.c --- a/svr-runopts.c Mon Feb 19 23:04:46 2018 +0800 +++ b/svr-runopts.c Tue Feb 20 02:11:55 2018 +0000 @@ -30,6 +30,8 @@ #include "algo.h" #include "ecdsa.h" +#include + svr_runopts svr_opts; /* GLOBAL */ static void printhelp(const char * progname); @@ -68,6 +70,7 @@ "-m Don't display the motd on login\n" #endif "-w Disallow root logins\n" + "-G Restrict logins to members of specified group\n" #if DROPBEAR_SVR_PASSWORD_AUTH || DROPBEAR_SVR_PAM_AUTH "-s Disable password logins\n" "-g Disable password logins for root\n" @@ -132,6 +135,8 @@ svr_opts.forced_command = NULL; svr_opts.forkbg = 1; svr_opts.norootlogin = 0; + svr_opts.grouploginname = NULL; + svr_opts.grouploginid = NULL; svr_opts.noauthpass = 0; svr_opts.norootpass = 0; svr_opts.allowblankpass = 0; @@ -230,6 +235,11 @@ case 'w': svr_opts.norootlogin = 1; break; + + case 'G': + next = &svr_opts.grouploginname; + break; + case 'W': next = &recv_window_arg; break; @@ -331,6 +341,18 @@ } buf_setpos(svr_opts.banner, 0); } + + if (svr_opts.grouploginname) { + struct group *restrictedgroup = getgrnam(svr_opts.grouploginname); + + if (restrictedgroup){ + svr_opts.grouploginid = malloc(sizeof(gid_t)); + *svr_opts.grouploginid = restrictedgroup->gr_gid; + } else { + dropbear_exit("Cannot restrict logins to group '%s' as the group does not exist", svr_opts.grouploginname); + } + + } if (recv_window_arg) { opts.recv_window = atol(recv_window_arg);