-
Notifications
You must be signed in to change notification settings - Fork 117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added authgroup PAM option for challenge-response mode #94
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,3 +42,7 @@ Drop permissions before opening user files. | |
|
||
Fredrik Thulin <[email protected]> | ||
Maintainer alumni, helped on drop_privs.c, utils.c, and more. | ||
|
||
Jonathan D. Hall <[email protected]> | ||
Added authgroup PAM module option for challenge-response | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -109,6 +109,7 @@ struct cfg | |
int try_first_pass; | ||
int use_first_pass; | ||
const char *auth_file; | ||
const char *auth_group; | ||
const char *capath; | ||
const char *cainfo; | ||
const char *proxy; | ||
|
@@ -439,7 +440,7 @@ do_challenge_response(pam_handle_t *pamh, struct cfg *cfg, const char *username) | |
char *userfile = NULL, *tmpfile = NULL; | ||
FILE *f = NULL; | ||
char buf[CR_RESPONSE_SIZE + 16], response_hex[CR_RESPONSE_SIZE * 2 + 1]; | ||
int ret, fd; | ||
int ret, fd, result; | ||
|
||
unsigned int response_len = 0; | ||
YK_KEY *yk = NULL; | ||
|
@@ -449,6 +450,18 @@ do_challenge_response(pam_handle_t *pamh, struct cfg *cfg, const char *username) | |
|
||
struct passwd *p; | ||
struct stat st; | ||
|
||
if(cfg->auth_group) { | ||
result = check_user_group((char*)username,(char*)cfg->auth_group); | ||
|
||
if(result == 1) { | ||
errstr = NULL; | ||
errno = 0; | ||
ret = PAM_SUCCESS; | ||
DBG(("User %s is not in group %s - skipping YubiKey requirement for login!", username, cfg->auth_group)); | ||
goto out; | ||
} | ||
} | ||
|
||
/* we must declare two sepparate privs structures as they can't be reused */ | ||
PAM_MODUTIL_DEF_PRIVS(privs); | ||
|
@@ -711,6 +724,8 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg) | |
cfg->use_first_pass = 1; | ||
if (strncmp (argv[i], "authfile=", 9) == 0) | ||
cfg->auth_file = argv[i] + 9; | ||
if (strncmp (argv[i], "authgroup=", 10) == 0) | ||
cfg->auth_group = argv[i] + 10; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. very minor: the indentation is miss-aligned here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an odd one that I keep fighting with my IDE over... When I open the source, all of the if statements are indented twice and the blocks under them are inverse-indented two back... It could be due to me using (I'm going to duck for cover as I type this) Xcode... I'll pop it open in vim and fix it. :) |
||
if (strncmp (argv[i], "capath=", 7) == 0) | ||
cfg->capath = argv[i] + 7; | ||
if (strncmp (argv[i], "cainfo=", 7) == 0) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -226,6 +226,28 @@ check_firmware_version(YK_KEY *yk, bool verbose, bool quiet) | |
return 1; | ||
} | ||
|
||
int | ||
check_user_group(char *username, char *group) | ||
{ | ||
struct group *group_ptr; | ||
char **group_member; | ||
|
||
if((group_ptr = getgrnam(group)) == NULL) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use getgrnam_r() instead of getgrnam() here. One issue here is that group membership defined in the user record is not checked by the getgrnam functions, that has to be fetched with getpwnam_r() and getgrgid_r(). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not certain about whether or not getgrnam_r provides any additional checking over getgrnam, as they both essentially return a list of members of a specified group. But I believe the biggest difference between the two is that getgrnam stores the data in a single buffer and returns a pointer to it, but the buffer is overwritten on subsequent calls. However, I don't mind making the modifications to use getgrnam_r instead as it would provide a starting grounds for expansion with regards to remote authentication and threading... I have some ideas for developing a means of making challenge-response capable of remotely authenticating via a centralized server and using SSL to keep the challenge/response safe between the client/server. We can chat more about that outside of here some time. If you could drop me an email at [email protected], I'd love to send you over the details of what I'd like to take on and contribute to the project. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it's the thread safety of getgrnam_r() that I'm after since the calling application might be threaded. |
||
// Group was not found... Return a fail | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use c style comments (/* */) as the rest of the project uses only that |
||
D(("Group %s does not exist... Skipping group verification and returning valid!\n",group)); | ||
return 1; | ||
} | ||
|
||
for (group_member = group_ptr->gr_mem; *group_member != NULL; group_member++) { | ||
if(strcmp(*group_member,username) == 0) { | ||
// We found the user... | ||
D(("User: %s is part of the Group: %s\n", username,group)); | ||
return 0; | ||
} | ||
} | ||
return 1; | ||
} | ||
|
||
int | ||
init_yubikey(YK_KEY **yk) | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not convinced PAM_SUCCESS is the appropriate return value here, PAM_IGNORE or PAM_USER_UNKNOWN might be more appropriate (but might also require more complex config).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're right. I believe PAM_IGNORE would be more appropriate, as PAM_USER_UNKNOWN is going to have an adverse affect if the particular auth module is required by the PAM config. If PAM_IGNORE is returned, it should force PAM to skip it - whether it's required or optional... I'll do some playing with it.