Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions iterate_ssh_agent_keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,15 @@ pamsshagentauth_session_id2_gen(Buffer * session_id2, const char * user,
return;
}

int
const char *
pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename)
{
Buffer session_id2 = { 0 };
Identity *id;
Key *key;
AuthenticationConnection *ac;
char *comment;
uint8_t retval = 0;
const char *key_file = 0;
uid_t uid = getpwnam(ruser)->pw_uid;

OpenSSL_add_all_digests();
Expand All @@ -199,13 +199,11 @@ pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, cons
id->key = key;
id->filename = comment;
id->ac = ac;
if(userauth_pubkey_from_id(ruser, id, &session_id2)) {
retval = 1;
}
key_file = userauth_pubkey_from_id(ruser, id, &session_id2);
pamsshagentauth_xfree(id->filename);
pamsshagentauth_key_free(id->key);
pamsshagentauth_xfree(id);
if(retval == 1)
if(key_file)
break;
}
}
Expand All @@ -217,5 +215,5 @@ pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, cons
}
/* pamsshagentauth_xfree(session_id2); */
EVP_cleanup();
return retval;
return key_file;
}
2 changes: 1 addition & 1 deletion iterate_ssh_agent_keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@
#ifndef _ITERATE_SSH_AGENT_KEYS_H
#define _ITERATE_SSH_AGENT_KEYS_H

int pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename);
const char * pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename);

#endif
30 changes: 14 additions & 16 deletions pam_ssh_agent_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
#define strncasecmp_literal(A,B) strncasecmp( A, B, sizeof(B) - 1)
#define UNUSED(expr) do { (void)(expr); } while (0)

char *authorized_keys_file = NULL;
uint8_t allow_user_owned_authorized_keys_file = 0;
char *authorized_keys_command = NULL;
char *authorized_keys_command_user = NULL;
Expand Down Expand Up @@ -173,23 +172,21 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv)
goto cleanexit;
}

if(authorized_keys_file_input && user) {
/*
* user is the name of the target-user, and so must be used for validating the authorized_keys file
*/
parse_authorized_key_file(user, authorized_keys_file_input);
} else {
pamsshagentauth_verbose("Using default file=/etc/security/authorized_keys");
authorized_keys_file = pamsshagentauth_xstrdup("/etc/security/authorized_keys");
}
if (!authorized_keys_file_input || !user)
authorized_keys_file_input = "/etc/security/authorized_keys";

/*
* user is the name of the target-user, and so must be used for validating the authorized_keys file
*/
parse_authorized_key_files(user, authorized_keys_file_input);

/*
* PAM_USER and PAM_RUSER do not necessarily have to get set by the calling application, and we may be unable to divine the latter.
* In those cases we should fail
*/

if(user && strlen(ruser) > 0) {
pamsshagentauth_verbose("Attempting authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file);
pamsshagentauth_verbose("Attempting authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file_input);

/*
* Attempt to read data from the sshd if we're being called as an auth agent.
Expand All @@ -200,19 +197,20 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv)
pamsshagentauth_verbose("Got SSH_AUTH_INFO_0: `%.20s...'", ssh_user_auth);
if (userauth_pubkey_from_pam(ruser, ssh_user_auth) > 0) {
retval = PAM_SUCCESS;
pamsshagentauth_logit("Authenticated (sshd): `%s' as `%s' using %s", ruser, user, authorized_keys_file);
pamsshagentauth_logit("Authenticated (sshd): `%s' as `%s' using %s", ruser, user, authorized_keys_file_input);
goto cleanexit;
}
}

/*
* this pw_uid is used to validate the SSH_AUTH_SOCK, and so must be the uid of the ruser invoking the program, not the target-user
*/
if(pamsshagentauth_find_authorized_keys(user, ruser, servicename)) { /* getpwnam(ruser)->pw_uid)) { */
pamsshagentauth_logit("Authenticated (agent): `%s' as `%s' using %s", ruser, user, authorized_keys_file);
const char *key_file;
if((key_file = pamsshagentauth_find_authorized_keys(user, ruser, servicename))) { /* getpwnam(ruser)->pw_uid)) { */
pamsshagentauth_logit("Authenticated (agent): `%s' as `%s' using %s", ruser, user, key_file);
retval = PAM_SUCCESS;
} else {
pamsshagentauth_logit("Failed Authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file);
pamsshagentauth_logit("Failed Authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file_input);
}
} else {
pamsshagentauth_logit("No %s specified, cannot continue with this form of authentication", (user) ? "ruser" : "user" );
Expand All @@ -224,7 +222,7 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv)
free(__progname);
#endif

free(authorized_keys_file);
free_authorized_key_files();

return retval;
}
Expand Down
2 changes: 1 addition & 1 deletion pam_ssh_agent_auth.pod
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ This configuration would permit anyone who originally authenticated to sshd with

=item file=<path to authorized_keys>

Specify the path to the authorized_keys file(s) you would like to use for authentication. Subject to tilde and % EXPANSIONS (below)
Specify the path(s) to the authorized_keys file(s) you would like to use for authentication. Subject to tilde and % EXPANSIONS (below). Paths are separated using colons.

=item allow_user_owned_authorized_keys_file

Expand Down
143 changes: 78 additions & 65 deletions pam_user_authorized_keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,12 @@

#include "identity.h"
#include "pam_user_key_allowed2.h"
#include "pam_user_authorized_keys.h"

extern char *authorized_keys_file;
#define MAX_AUTHORIZED_KEY_FILES 16

char *authorized_keys_files[MAX_AUTHORIZED_KEY_FILES];
unsigned int nr_authorized_keys_files = 0;

extern char *authorized_keys_command;

Expand All @@ -91,79 +95,88 @@ extern uint8_t allow_user_owned_authorized_keys_file;
uid_t authorized_keys_file_allowed_owner_uid;

void
parse_authorized_key_file(const char *user,
const char *authorized_keys_file_input)
parse_authorized_key_files(const char *user,
const char *authorized_keys_file_input)
{
char fqdn[HOST_NAME_MAX] = "";
const char *pos = authorized_keys_file_input;
char hostname[HOST_NAME_MAX] = "";
char auth_keys_file_buf[4096] = "";
char *slash_ptr = NULL;
char owner_uname[128] = "";
size_t owner_uname_len = 0;

/*
* temporary copy, so that both tilde expansion and percent expansion both
* get to apply to the path
*/
strncat(auth_keys_file_buf, authorized_keys_file_input,
sizeof(auth_keys_file_buf) - 1);

if(allow_user_owned_authorized_keys_file)
authorized_keys_file_allowed_owner_uid = getpwnam(user)->pw_uid;

if(*auth_keys_file_buf == '~') {
if(*(auth_keys_file_buf + 1) == '/') {
authorized_keys_file_allowed_owner_uid = getpwnam(user)->pw_uid;
} else {
slash_ptr = strchr(auth_keys_file_buf, '/');
if(!slash_ptr)
pamsshagentauth_fatal
("cannot expand tilde in path without a `/'");

owner_uname_len = slash_ptr - auth_keys_file_buf - 1;
if(owner_uname_len > (sizeof(owner_uname) - 1))
pamsshagentauth_fatal("Username too long");

strncat(owner_uname, auth_keys_file_buf + 1, owner_uname_len);
if(!authorized_keys_file_allowed_owner_uid)
authorized_keys_file_allowed_owner_uid =
getpwnam(owner_uname)->pw_uid;
}
authorized_keys_file =
pamsshagentauth_tilde_expand_filename(auth_keys_file_buf,
authorized_keys_file_allowed_owner_uid);
strncpy(auth_keys_file_buf, authorized_keys_file,
sizeof(auth_keys_file_buf) - 1);
pamsshagentauth_xfree(authorized_keys_file) /* when we
percent_expand
later, we'd step
on this, so free
it immediately */ ;
}
char fqdn[HOST_NAME_MAX] = "";

if(strstr(auth_keys_file_buf, "%h")) {
authorized_keys_file_allowed_owner_uid = getpwnam(user)->pw_uid;
}
#if HAVE_GETHOSTNAME
*hostname = '\0';
gethostname(fqdn, HOST_NAME_MAX);
strncat(hostname, fqdn, strcspn(fqdn, "."));
strncat(hostname, fqdn, strcspn(fqdn,"."));
#endif
authorized_keys_file =
pamsshagentauth_percent_expand(auth_keys_file_buf, "h",
getpwnam(user)->pw_dir, "H", hostname,
"f", fqdn, "u", user, NULL);

while (pos) {
const char *colon = strchr(pos, ':');
char auth_keys_file_buf[4096] = "";
char *slash_ptr = NULL;
char owner_uname[128] = "";
size_t owner_uname_len = 0;

strncat(auth_keys_file_buf, pos, sizeof(auth_keys_file_buf) - 1);
if (colon) {
auth_keys_file_buf[colon - pos] = 0;
pos = colon + 1;
} else {
pos = 0;
}

if(allow_user_owned_authorized_keys_file)
authorized_keys_file_allowed_owner_uid = getpwnam(user)->pw_uid;

if(*auth_keys_file_buf == '~') {
if(*(auth_keys_file_buf+1) == '/') {
authorized_keys_file_allowed_owner_uid = getpwnam(user)->pw_uid;
}
else {
slash_ptr = strchr(auth_keys_file_buf,'/');
if(!slash_ptr)
pamsshagentauth_fatal("cannot expand tilde in path without a `/'");

owner_uname_len = slash_ptr - auth_keys_file_buf - 1;
if(owner_uname_len > (sizeof(owner_uname) - 1) )
pamsshagentauth_fatal("Username too long");

strncat(owner_uname, auth_keys_file_buf + 1, owner_uname_len);
if(!authorized_keys_file_allowed_owner_uid)
authorized_keys_file_allowed_owner_uid = getpwnam(owner_uname)->pw_uid;
}
char *tmp = pamsshagentauth_tilde_expand_filename(auth_keys_file_buf, authorized_keys_file_allowed_owner_uid);
strncpy(auth_keys_file_buf, tmp, sizeof(auth_keys_file_buf) - 1 );
pamsshagentauth_xfree(tmp);
}

if(strstr(auth_keys_file_buf, "%h")) {
authorized_keys_file_allowed_owner_uid = getpwnam(user)->pw_uid;
}

if (nr_authorized_keys_files >= MAX_AUTHORIZED_KEY_FILES)
pamsshagentauth_fatal("Too many authorized key files");
authorized_keys_files[nr_authorized_keys_files++] =
pamsshagentauth_percent_expand(auth_keys_file_buf, "h", getpwnam(user)->pw_dir, "H", hostname, "f", fqdn, "u", user, NULL);
}
}

void
free_authorized_key_files()
{
unsigned int n;
for (n = 0; n < nr_authorized_keys_files; n++)
free(authorized_keys_files[n]);
nr_authorized_keys_files = 0;
}

int
const char *
pam_user_key_allowed(const char *ruser, Key * key)
{
return
pamsshagentauth_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid),
key, authorized_keys_file)
|| pamsshagentauth_user_key_allowed2(getpwuid(0), key,
authorized_keys_file)
|| pamsshagentauth_user_key_command_allowed2(authorized_keys_command,
authorized_keys_command_user,
getpwnam(ruser), key);
unsigned int n;
for (n = 0; n < nr_authorized_keys_files; n++) {
if (pamsshagentauth_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid), key, authorized_keys_files[n])
|| pamsshagentauth_user_key_allowed2(getpwuid(0), key, authorized_keys_files[n])
|| pamsshagentauth_user_key_command_allowed2(authorized_keys_command, authorized_keys_command_user, getpwnam(ruser), key))
return authorized_keys_files[n];
}
return 0;
}
9 changes: 5 additions & 4 deletions pam_user_authorized_keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@
*/


#ifndef _PAM_USER_KEY_ALLOWED_H
#define _PAM_USER_KEY_ALLOWED_H
#ifndef _PAM_USER_AUTHORIZED_KEYS_H
#define _PAM_USER_AUTHORIZED_KEYS_H

#include "identity.h"
int pam_user_key_allowed(const char *, Key *);
void parse_authorized_key_file(const char *, const char *);
const char * pam_user_key_allowed(const char *, Key *);
void parse_authorized_key_files(const char *, const char *);
void free_authorized_key_files();

#endif
7 changes: 4 additions & 3 deletions userauth_pubkey_from_id.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,20 @@
extern uint8_t session_id_len;
*/

int
const char *
userauth_pubkey_from_id(const char *ruser, Identity * id, Buffer * session_id2)
{
Buffer b = { 0 };
char *pkalg = NULL;
u_char *pkblob = NULL, *sig = NULL;
u_int blen = 0, slen = 0;
int authenticated = 0;
const char *key_file;

pkalg = (char *) key_ssh_name(id->key);

/* first test if this key is even allowed */
if(! pam_user_key_allowed(ruser, id->key))
if(!(key_file = pam_user_key_allowed(ruser, id->key)))
goto user_auth_clean_exit;

if(pamsshagentauth_key_to_blob(id->key, &pkblob, &blen) == 0)
Expand Down Expand Up @@ -97,5 +98,5 @@ userauth_pubkey_from_id(const char *ruser, Identity * id, Buffer * session_id2)
if(pkblob != NULL)
pamsshagentauth_xfree(pkblob);
CRYPTO_cleanup_all_ex_data();
return authenticated;
return authenticated ? key_file : 0;
}
2 changes: 1 addition & 1 deletion userauth_pubkey_from_id.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@
#define _USERAUTH_PUBKEY_FROM_ID_H

#include <identity.h>
int userauth_pubkey_from_id(const char *, Identity *, Buffer *);
const char * userauth_pubkey_from_id(const char *, Identity *, Buffer *);

#endif