summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstellarpower <stellarpower@googlemail.com>2018-02-20 02:11:55 +0000
committerstellarpower <stellarpower@googlemail.com>2018-02-20 02:11:55 +0000
commit5734ea3ad1008a3daa35cef17e1da58698a92c87 (patch)
tree6c6695c5ae76497055270550d8d80578dc6cbe38
parent26984c5523656e832019c6c09e544ad08608dc36 (diff)
downloaddropbear-5734ea3ad1008a3daa35cef17e1da58698a92c87.tar.gz
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.
-rw-r--r--runopts.h2
-rw-r--r--svr-auth.c46
-rw-r--r--svr-runopts.c22
3 files changed, 70 insertions, 0 deletions
diff --git a/runopts.h b/runopts.h
index 5118769..a3f46d2 100644
--- a/runopts.h
+++ b/runopts.h
@@ -92,6 +92,8 @@ typedef struct svr_runopts {
#endif
int norootlogin;
+ char *grouploginname;
+ gid_t *grouploginid;
int noauthpass;
int norootpass;
diff --git a/svr-auth.c b/svr-auth.c
index 523f91b..9c818d9 100644
--- a/svr-auth.c
+++ b/svr-auth.c
@@ -25,6 +25,8 @@
/* This file (auth.c) handles authentication requests, passing it to the
* particular type (auth-passwd, auth-pubkey). */
+#include <limits.h>
+
#include "includes.h"
#include "dbutil.h"
#include "session.h"
@@ -232,6 +234,10 @@ static int checkusername(char *username, unsigned int userlen) {
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 @@ static int checkusername(char *username, unsigned int userlen) {
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 --git a/svr-runopts.c b/svr-runopts.c
index 3d97023..68b2673 100644
--- a/svr-runopts.c
+++ b/svr-runopts.c
@@ -30,6 +30,8 @@
#include "algo.h"
#include "ecdsa.h"
+#include <grp.h>
+
svr_runopts svr_opts; /* GLOBAL */
static void printhelp(const char * progname);
@@ -68,6 +70,7 @@ static void printhelp(const char * progname) {
"-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 @@ void svr_getopts(int argc, char ** argv) {
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 @@ void svr_getopts(int argc, char ** argv) {
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 @@ void svr_getopts(int argc, char ** argv) {
}
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);