Originally Posted by dlrosen
auth include system-auth
auth sufficient pam_winbind.so
account required pam_nologin.so
account [default=2 success=ignore] pam_succeed_if.so quiet uid >= 16777216
account sufficient pam_succeed_if.so user ingroup windows_group_1
account required pam_succeed_if.so user ingroup windows_group_2
account include system-auth
password include system-auth
Just wanted to point out (yes, I know this is an old thread, but shows up near the top of Google for "Pam Multiple Group" and a few other related topics), this suggested config would completely bypass the system-auth include line if the user is in the windows_group_1 group. The sufficient mode will immediately return success for that check. The way to require one of a set of requirements without breaking the basic checks in the include line is to change to the following:
account [default=ignore success=2] pam_succeed_if.so quiet uid < 16777216
account [default=ignore success=1] pam_succeed_if.so user ingroup windows_group_1
account [default=bad success=ignore] pam_succeed_if.so user ingroup windows_group_2
What happens here is it first checks if the user is local or not (same as OP suggested just flipped the compare to keep syntax the same) and skips the group checking if so (via success=2). Next, it checks for membership in windows_group_1, if a member, it skips out of the group checking and continues at the include system-auth line, otherwise it checks for membership in windows_group_2, and fails the account section if not in that group. You can add as many groups as you like here, just duplicate the windows_group_1 line and increment the numbers in the first two lines (success=3 and success=2, new line stays at success=1) so it will properly skip out of the group checking. The last check line should always have default=bad to fail the section. You probably want to add quiet to both the group checking lines as well so it doesnt log a failure every time someone in windows_group_2 logs in.
This basically sets up a logical OR across a bunch of checks. As shown here, it checks that UID is below a certain minimal value, or that the user is a member of one of either groups presented (ie: ( uid<$x || $user.ingroup(windows_group_1) || $user.ingroup(windows_group_2)) ).