comparison svr-auth.c @ 1537:6a83b1944432

Fix restricted group code for BSDs, move to separate function
author Matt Johnston <matt@ucc.asn.au>
date Mon, 26 Feb 2018 21:17:13 +0800
parents ed930fd6f60f
children f20038b513a5
comparison
equal deleted inserted replaced
1536:a55a6901a181 1537:6a83b1944432
224 m_free(username); 224 m_free(username);
225 m_free(servicename); 225 m_free(servicename);
226 m_free(methodname); 226 m_free(methodname);
227 } 227 }
228 228
229 /* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
230 static int check_group_membership(gid_t check_gid, const char* username, gid_t user_gid) {
231 int ngroups, i, ret;
232 gid_t *grouplist = NULL;
233 int match = DROPBEAR_FAILURE;
234
235 for (ngroups = 32; ngroups <= DROPBEAR_NGROUP_MAX; ngroups *= 2) {
236 grouplist = m_malloc(sizeof(gid_t) * ngroups);
237
238 /* BSD returns ret==0 on success. Linux returns ret==ngroups on success */
239 ret = getgrouplist(username, user_gid, grouplist, &ngroups);
240 if (ret >= 0) {
241 break;
242 }
243 m_free(grouplist);
244 grouplist = NULL;
245 }
246
247 if (!grouplist) {
248 dropbear_log(LOG_ERR, "Too many groups for user '%s'", username);
249 return DROPBEAR_FAILURE;
250 }
251
252 for (i = 0; i < ngroups; i++) {
253 if (grouplist[i] == check_gid) {
254 match = DROPBEAR_SUCCESS;
255 break;
256 }
257 }
258 m_free(grouplist);
259
260 return match;
261 }
262
229 263
230 /* Check that the username exists and isn't disallowed (root), and has a valid shell. 264 /* Check that the username exists and isn't disallowed (root), and has a valid shell.
231 * returns DROPBEAR_SUCCESS on valid username, DROPBEAR_FAILURE on failure */ 265 * returns DROPBEAR_SUCCESS on valid username, DROPBEAR_FAILURE on failure */
232 static int checkusername(char *username, unsigned int userlen) { 266 static int checkusername(char *username, unsigned int userlen) {
233 267
234 char* listshell = NULL; 268 char* listshell = NULL;
235 char* usershell = NULL; 269 char* usershell = NULL;
236 uid_t uid; 270 uid_t uid;
237 int ngroups = 32, ret;
238 gid_t *grouplist;
239
240 271
241 TRACE(("enter checkusername")) 272 TRACE(("enter checkusername"))
242 if (userlen > MAX_USERNAME_LEN) { 273 if (userlen > MAX_USERNAME_LEN) {
243 return DROPBEAR_FAILURE; 274 return DROPBEAR_FAILURE;
244 } 275 }
282 TRACE(("leave checkusername: root login disabled")) 313 TRACE(("leave checkusername: root login disabled"))
283 dropbear_log(LOG_WARNING, "root login rejected"); 314 dropbear_log(LOG_WARNING, "root login rejected");
284 return DROPBEAR_FAILURE; 315 return DROPBEAR_FAILURE;
285 } 316 }
286 317
287 /* check for login restricted to certain group if desired */ 318 /* check for login restricted to certain group if desired */
288 if (svr_opts.grouploginid) { 319 if (svr_opts.restrict_group) {
289 320 if (check_group_membership(svr_opts.restrict_group_gid,
290 for ( ; (ngroups <= NGROUPS_MAX) && (ngroups <= INT_MAX / 8); ngroups *= 2){ 321 ses.authstate.pw_name, ses.authstate.pw_gid) == DROPBEAR_FAILURE) {
291 322 dropbear_log(LOG_WARNING,
292 grouplist = malloc(sizeof(gid_t) * ngroups); 323 "Logins are restricted to the group %s but user '%s' is not a member",
293 324 svr_opts.restrict_group, ses.authstate.pw_name);
294 ret = getgrouplist(ses.authstate.pw_name, ses.authstate.pw_gid, grouplist, &ngroups); 325 return DROPBEAR_FAILURE;
295 326 }
296 if (ret != -1){ 327 }
297 break;
298 }
299
300 free(grouplist);
301 ngroups *= 2;
302 }
303
304 if ((ngroups > NGROUPS_MAX / 8) || (ngroups > INT_MAX / 8)){
305
306 TRACE(("Cannot walk group structure for current user, too many groups"))
307 dropbear_log(LOG_ERR, "Cannot walk group structure for current user, too many groups");
308 return DROPBEAR_FAILURE;
309 }
310
311 ngroups = 0;
312 for (int i = 0; i < ret; i++){
313 if (grouplist[i] == *svr_opts.grouploginid){
314 ngroups = 1; //Just used as a flag to indicate success;
315 break;
316 }
317
318 }
319
320 if (!ngroups){
321 TRACE(("leave checkusername: user not in permitted group"))
322 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);
323 return DROPBEAR_FAILURE;
324 }
325 }
326 328
327 TRACE(("shell is %s", ses.authstate.pw_shell)) 329 TRACE(("shell is %s", ses.authstate.pw_shell))
328 330
329 /* check that the shell is set */ 331 /* check that the shell is set */
330 usershell = ses.authstate.pw_shell; 332 usershell = ses.authstate.pw_shell;