-
-
Notifications
You must be signed in to change notification settings - Fork 15k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pam_ssh_agent_auth: Allow multiple authorized keys files
We need this because of NixOS/nixos#52.
- Loading branch information
Showing
2 changed files
with
344 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
338 changes: 338 additions & 0 deletions
338
pkgs/os-specific/linux/pam_ssh_agent_auth/multiple-key-files.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,338 @@ | ||
diff -ru -x '*~' pam_ssh_agent_auth-0.9.4-orig/iterate_ssh_agent_keys.c pam_ssh_agent_auth-0.9.4/iterate_ssh_agent_keys.c | ||
--- pam_ssh_agent_auth-0.9.4-orig/iterate_ssh_agent_keys.c 2012-06-28 01:47:49.000000000 +0000 | ||
+++ pam_ssh_agent_auth-0.9.4/iterate_ssh_agent_keys.c 2012-12-17 19:29:16.014226336 +0000 | ||
@@ -69,14 +69,14 @@ | ||
return cookie; | ||
} | ||
|
||
-int | ||
+const char * | ||
pamsshagentauth_find_authorized_keys(uid_t uid) | ||
{ | ||
Identity *id; | ||
Key *key; | ||
AuthenticationConnection *ac; | ||
char *comment; | ||
- uint8_t retval = 0; | ||
+ const char *key_file = 0; | ||
|
||
OpenSSL_add_all_digests(); | ||
session_id2 = pamsshagentauth_session_id2_gen(); | ||
@@ -90,13 +90,11 @@ | ||
id->key = key; | ||
id->filename = comment; | ||
id->ac = ac; | ||
- if(userauth_pubkey_from_id(id)) { | ||
- retval = 1; | ||
- } | ||
+ key_file = userauth_pubkey_from_id(id); | ||
pamsshagentauth_xfree(id->filename); | ||
pamsshagentauth_key_free(id->key); | ||
pamsshagentauth_xfree(id); | ||
- if(retval == 1) | ||
+ if(key_file) | ||
break; | ||
} | ||
} | ||
@@ -107,5 +105,5 @@ | ||
} | ||
pamsshagentauth_xfree(session_id2); | ||
EVP_cleanup(); | ||
- return retval; | ||
+ return key_file; | ||
} | ||
diff -ru -x '*~' pam_ssh_agent_auth-0.9.4-orig/iterate_ssh_agent_keys.h pam_ssh_agent_auth-0.9.4/iterate_ssh_agent_keys.h | ||
--- pam_ssh_agent_auth-0.9.4-orig/iterate_ssh_agent_keys.h 2012-06-28 01:47:49.000000000 +0000 | ||
+++ pam_ssh_agent_auth-0.9.4/iterate_ssh_agent_keys.h 2012-12-17 19:28:57.454334806 +0000 | ||
@@ -31,6 +31,6 @@ | ||
#ifndef _ITERATE_SSH_AGENT_KEYS_H | ||
#define _ITERATE_SSH_AGENT_KEYS_H | ||
|
||
-int pamsshagentauth_find_authorized_keys(uid_t); | ||
+const char * pamsshagentauth_find_authorized_keys(uid_t); | ||
|
||
#endif | ||
diff -ru -x '*~' pam_ssh_agent_auth-0.9.4-orig/pam_ssh_agent_auth.c pam_ssh_agent_auth-0.9.4/pam_ssh_agent_auth.c | ||
--- pam_ssh_agent_auth-0.9.4-orig/pam_ssh_agent_auth.c 2012-06-28 01:47:49.000000000 +0000 | ||
+++ pam_ssh_agent_auth-0.9.4/pam_ssh_agent_auth.c 2012-12-17 19:30:24.013830673 +0000 | ||
@@ -60,7 +60,6 @@ | ||
|
||
#define strncasecmp_literal(A,B) strncasecmp( A, B, sizeof(B) - 1) | ||
|
||
-char *authorized_keys_file = NULL; | ||
uint8_t allow_user_owned_authorized_keys_file = 0; | ||
|
||
#if ! HAVE___PROGNAME || HAVE_BUNDLE | ||
@@ -161,15 +160,13 @@ | ||
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. | ||
@@ -177,16 +174,17 @@ | ||
*/ | ||
|
||
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); | ||
|
||
/* | ||
* 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(getpwnam(ruser)->pw_uid)) { | ||
- pamsshagentauth_logit("Authenticated: `%s' as `%s' using %s", ruser, user, authorized_keys_file); | ||
+ const char *key_file; | ||
+ if((key_file = pamsshagentauth_find_authorized_keys(getpwnam(ruser)->pw_uid))) { | ||
+ pamsshagentauth_logit("Authenticated: `%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" ); | ||
@@ -198,7 +196,7 @@ | ||
free(__progname); | ||
#endif | ||
|
||
- free(authorized_keys_file); | ||
+ free_authorized_key_files(); | ||
|
||
return retval; | ||
} | ||
diff -ru -x '*~' pam_ssh_agent_auth-0.9.4-orig/pam_ssh_agent_auth.pod pam_ssh_agent_auth-0.9.4/pam_ssh_agent_auth.pod | ||
--- pam_ssh_agent_auth-0.9.4-orig/pam_ssh_agent_auth.pod 2012-06-28 01:47:49.000000000 +0000 | ||
+++ pam_ssh_agent_auth-0.9.4/pam_ssh_agent_auth.pod 2012-12-17 19:52:35.968965448 +0000 | ||
@@ -26,7 +26,7 @@ | ||
|
||
=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 | ||
|
||
diff -ru -x '*~' pam_ssh_agent_auth-0.9.4-orig/pam_user_authorized_keys.c pam_ssh_agent_auth-0.9.4/pam_user_authorized_keys.c | ||
--- pam_ssh_agent_auth-0.9.4-orig/pam_user_authorized_keys.c 2012-06-28 01:47:49.000000000 +0000 | ||
+++ pam_ssh_agent_auth-0.9.4/pam_user_authorized_keys.c 2012-12-17 19:32:20.830157313 +0000 | ||
@@ -79,66 +79,96 @@ | ||
|
||
#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 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); | ||
+ char fqdn[HOST_NAME_MAX] = ""; | ||
+ | ||
+#if HAVE_GETHOSTNAME | ||
+ *hostname = '\0'; | ||
+ gethostname(fqdn, HOST_NAME_MAX); | ||
+ strncat(hostname, fqdn, strcspn(fqdn,".")); | ||
+#endif | ||
|
||
- if(allow_user_owned_authorized_keys_file) | ||
- authorized_keys_file_allowed_owner_uid = getpwnam(user)->pw_uid; | ||
+ 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(*auth_keys_file_buf == '~') { | ||
- if(*(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; | ||
+ } | ||
+ 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); | ||
} | ||
- 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; | ||
+ | ||
+ if(strstr(auth_keys_file_buf, "%h")) { | ||
+ authorized_keys_file_allowed_owner_uid = getpwnam(user)->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 */; | ||
- } | ||
|
||
- 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); | ||
} | ||
+} | ||
|
||
-#if HAVE_GETHOSTNAME | ||
- *hostname = '\0'; | ||
- gethostname(fqdn, HOST_NAME_MAX); | ||
- 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); | ||
+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(Key * key) | ||
{ | ||
- return pam_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid), key, authorized_keys_file) | ||
- || pam_user_key_allowed2(getpwuid(0), key, authorized_keys_file); | ||
+ unsigned int n; | ||
+ for (n = 0; n < nr_authorized_keys_files; n++) { | ||
+ if (pam_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid), key, authorized_keys_files[n]) | ||
+ || pam_user_key_allowed2(getpwuid(0), key, authorized_keys_files[n])) | ||
+ return authorized_keys_files[n]; | ||
+ } | ||
+ return 0; | ||
} | ||
diff -ru -x '*~' pam_ssh_agent_auth-0.9.4-orig/pam_user_authorized_keys.h pam_ssh_agent_auth-0.9.4/pam_user_authorized_keys.h | ||
--- pam_ssh_agent_auth-0.9.4-orig/pam_user_authorized_keys.h 2010-01-13 02:17:01.000000000 +0000 | ||
+++ pam_ssh_agent_auth-0.9.4/pam_user_authorized_keys.h 2012-12-17 19:24:34.477894517 +0000 | ||
@@ -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(Key *); | ||
-void parse_authorized_key_file(const char *, const char *); | ||
+const char * pam_user_key_allowed(Key *); | ||
+void parse_authorized_key_files(const char *, const char *); | ||
+void free_authorized_key_files(); | ||
|
||
#endif | ||
diff -ru -x '*~' pam_ssh_agent_auth-0.9.4-orig/userauth_pubkey_from_id.c pam_ssh_agent_auth-0.9.4/userauth_pubkey_from_id.c | ||
--- pam_ssh_agent_auth-0.9.4-orig/userauth_pubkey_from_id.c 2012-06-28 01:47:49.000000000 +0000 | ||
+++ pam_ssh_agent_auth-0.9.4/userauth_pubkey_from_id.c 2012-12-17 19:27:30.813843933 +0000 | ||
@@ -51,7 +51,7 @@ | ||
extern u_char *session_id2; | ||
extern uint8_t session_id_len; | ||
|
||
-int | ||
+const char * | ||
userauth_pubkey_from_id(Identity * id) | ||
{ | ||
Buffer b = { 0 }; | ||
@@ -59,11 +59,12 @@ | ||
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(id->key)) | ||
+ if(!(key_file = pam_user_key_allowed(id->key))) | ||
goto user_auth_clean_exit; | ||
|
||
if(pamsshagentauth_key_to_blob(id->key, &pkblob, &blen) == 0) | ||
@@ -96,5 +97,5 @@ | ||
if(pkblob != NULL) | ||
pamsshagentauth_xfree(pkblob); | ||
CRYPTO_cleanup_all_ex_data(); | ||
- return authenticated; | ||
+ return authenticated ? key_file : 0; | ||
} | ||
diff -ru -x '*~' pam_ssh_agent_auth-0.9.4-orig/userauth_pubkey_from_id.h pam_ssh_agent_auth-0.9.4/userauth_pubkey_from_id.h | ||
--- pam_ssh_agent_auth-0.9.4-orig/userauth_pubkey_from_id.h 2010-01-13 02:17:01.000000000 +0000 | ||
+++ pam_ssh_agent_auth-0.9.4/userauth_pubkey_from_id.h 2012-12-17 19:25:54.893412987 +0000 | ||
@@ -32,6 +32,6 @@ | ||
#define _USERAUTH_PUBKEY_FROM_ID_H | ||
|
||
#include <identity.h> | ||
-int userauth_pubkey_from_id(Identity *); | ||
+const char * userauth_pubkey_from_id(Identity *); | ||
|
||
#endif |