FreeBSD Bugzilla – Attachment 11029 Details for
Bug 21877
[PATCH] DSA support for pam_ssh
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
file.diff
file.diff (text/plain), 11.60 KB, created by
ajk
on 2000-10-09 22:00:01 UTC
(
hide
)
Description:
file.diff
Filename:
MIME Type:
Creator:
ajk
Created:
2000-10-09 22:00:01 UTC
Size:
11.60 KB
patch
obsolete
>Index: pam_ssh.c >=================================================================== >RCS file: /var/cvs/src/crypto/openssh/pam_ssh/pam_ssh.c,v >retrieving revision 1.8 >diff -u -r1.8 pam_ssh.c >--- pam_ssh.c 2000/07/16 05:52:28 1.8 >+++ pam_ssh.c 2000/10/09 20:39:35 >@@ -28,11 +28,9 @@ > */ > > >-#include <sys/param.h> > #include <sys/queue.h> >+#include <sys/stat.h> > >-#include <fcntl.h> >-#include <paths.h> > #include <pwd.h> > #include <stdio.h> > #include <stdlib.h> >@@ -45,6 +43,7 @@ > #include <security/pam_mod_misc.h> > > #include <openssl/dsa.h> >+#include <openssl/evp.h> > > #include "includes.h" > #include "rsa.h" >@@ -54,18 +53,26 @@ > #include "authfile.h" > > #define MODULE_NAME "pam_ssh" >-#define NEED_PASSPHRASE "Need passphrase for %s (%s).\nEnter passphrase: " >+#define NEED_PASSPHRASE "SSH passphrase: " > #define PATH_SSH_AGENT "/usr/bin/ssh-agent" > > >+/* >+ * Generic cleanup function for SSH "Key" type. >+ */ >+ > void >-rsa_cleanup(pam_handle_t *pamh, void *data, int error_status) >+key_cleanup(pam_handle_t *pamh, void *data, int error_status) > { > if (data) >- RSA_free(data); >+ key_free(data); > } > > >+/* >+ * Generic PAM cleanup function for this module. >+ */ >+ > void > ssh_cleanup(pam_handle_t *pamh, void *data, int error_status) > { >@@ -107,6 +114,10 @@ > extern char **environ; > > >+/* >+ * Create a new environment list. >+ */ >+ > static ENV * > env_new(void) > { >@@ -123,8 +134,12 @@ > } > > >+/* >+ * Insert a new entry into the list. >+ */ >+ > static int >-env_put(ENV *self, char *s) >+env_put(ENV *self, const char *s) > { > struct env_entry *env; > >@@ -139,13 +154,21 @@ > } > > >+/* >+ * Switch between the original environ string and our crafted one. >+ */ >+ > static void >-env_swap(ENV *self, int which) >+env_swap(const ENV *self, int which) > { > environ = which ? self->e_environ_new : self->e_environ_orig; > } > > >+/* >+ * Craft an environ string out of the list we've built. >+ */ >+ > static int > env_commit(ENV *self) > { >@@ -171,15 +194,20 @@ > } > > >+/* >+ * Destroy our list and environ string. >+ */ >+ > static void > env_destroy(ENV *self) > { > struct env_entry *p; > > env_swap(self, 0); >- SLIST_FOREACH(p, &self->e_head, ee_entries) { >+ while ((p = SLIST_FIRST(&self->e_head))) { > free(p->ee_env); > free(p); >+ SLIST_REMOVE_HEAD(&self->e_head, ee_entries); > } > if (self->e_committed) > free(self->e_environ_new); >@@ -187,6 +215,10 @@ > } > > >+/* >+ * Cleanup function for PAM data storage. >+ */ >+ > void > env_cleanup(pam_handle_t *pamh, void *data, int error_status) > { >@@ -195,6 +227,80 @@ > } > > >+/* >+ * Authenticate a user's key by trying to decrypt it with the password >+ * provided. The key and its comment are then stored for later >+ * retrieval by the session phase. An increasing index is embedded in >+ * the PAM variable names so this function may be called multiple times >+ * for multiple keys. >+ */ >+ >+int >+auth_via_key( >+ pam_handle_t *pamh, >+ int type, >+ const char *file, >+ const struct passwd *user, >+ const char *pass >+) >+{ >+ char *comment; /* private key comment */ >+ char *data_name; /* PAM state */ >+ static int index = 0; /* for saved keys */ >+ Key *key; /* user's key */ >+ char *path; /* to key files */ >+ int retval; /* from calls */ >+ uid_t saved_uid; /* caller's uid */ >+ >+ /* locate the user's private key file */ >+ if (!asprintf(&path, "%s/%s", user->pw_dir, file)) { >+ syslog(LOG_CRIT, "%s: %m", MODULE_NAME); >+ return PAM_SERVICE_ERR; >+ } >+ saved_uid = getuid(); >+ /* >+ * Try to decrypt the private key with the passphrase provided. >+ * If success, the user is authenticated. >+ */ >+ key = key_new(type); >+ (void)setreuid(user->pw_uid, saved_uid); >+ retval = load_private_key(path, pass, key, &comment); >+ free(path); >+ (void)setuid(saved_uid); >+ if (!retval) >+ return retval; >+ /* >+ * Save the key and comment to pass to ssh-agent in the session >+ * phase. >+ */ >+ if (!asprintf(&data_name, "ssh_private_key_%d", index)) { >+ syslog(LOG_CRIT, "%s: %m", MODULE_NAME); >+ free(comment); >+ return PAM_SERVICE_ERR; >+ } >+ retval = pam_set_data(pamh, data_name, key, key_cleanup); >+ free(data_name); >+ if (retval != PAM_SUCCESS) { >+ key_free(key); >+ free(comment); >+ return retval; >+ } >+ if (!asprintf(&data_name, "ssh_key_comment_%d", index)) { >+ syslog(LOG_CRIT, "%s: %m", MODULE_NAME); >+ free(comment); >+ return PAM_SERVICE_ERR; >+ } >+ retval = pam_set_data(pamh, data_name, comment, ssh_cleanup); >+ free(data_name); >+ if (retval != PAM_SUCCESS) { >+ free(comment); >+ return retval; >+ } >+ ++index; >+ return PAM_SUCCESS; >+} >+ >+ > typedef struct passwd PASSWD; > > PAM_EXTERN int >@@ -204,18 +310,11 @@ > int argc, > const char **argv) > { >- char *comment_priv; /* on private key */ >- char *comment_pub; /* on public key */ >- char *identity; /* user's identity file */ >- Key key; /* user's private key */ > int options; /* module options */ > const char *pass; /* passphrase */ >- char *prompt; /* passphrase prompt */ >- Key public_key; /* user's public key */ > const PASSWD *pwent; /* user's passwd entry */ > PASSWD *pwent_keep; /* our own copy */ > int retval; /* from calls */ >- uid_t saved_uid; /* caller's uid */ > const char *user; /* username */ > > options = 0; >@@ -227,70 +326,25 @@ > /* delay? */ > return PAM_AUTH_ERR; > } >- /* locate the user's private key file */ >- if (!asprintf(&identity, "%s/%s", pwent->pw_dir, >- SSH_CLIENT_IDENTITY)) { >- syslog(LOG_CRIT, "%s: %m", MODULE_NAME); >- return PAM_SERVICE_ERR; >- } > /* >- * Fail unless we can load the public key. Change to the >- * owner's UID to appease load_public_key(). >+ * Pass prompt message to application and receive >+ * passphrase. > */ >- key.type = KEY_RSA; >- key.rsa = RSA_new(); >- public_key.type = KEY_RSA; >- public_key.rsa = RSA_new(); >- saved_uid = getuid(); >- (void)setreuid(pwent->pw_uid, saved_uid); >- retval = load_public_key(identity, &public_key, &comment_pub); >- (void)setuid(saved_uid); >- if (!retval) { >- free(identity); >- return PAM_AUTH_ERR; >- } >- RSA_free(public_key.rsa); >- /* build the passphrase prompt */ >- retval = asprintf(&prompt, NEED_PASSPHRASE, identity, comment_pub); >- free(comment_pub); >- if (!retval) { >- syslog(LOG_CRIT, "%s: %m", MODULE_NAME); >- free(identity); >- return PAM_SERVICE_ERR; >- } >- /* pass prompt message to application and receive passphrase */ >- retval = pam_get_pass(pamh, &pass, prompt, options); >- free(prompt); >- if (retval != PAM_SUCCESS) { >- free(identity); >+ if ((retval = pam_get_pass(pamh, &pass, NEED_PASSPHRASE, options)) >+ != PAM_SUCCESS) > return retval; >- } >+ OpenSSL_add_all_algorithms(); /* required for DSA */ > /* >- * Try to decrypt the private key with the passphrase provided. >- * If success, the user is authenticated. >+ * Either the DSA or the RSA key will authenticate us, but if >+ * we can decrypt both, we'll do so here so we can cache them in >+ * the session phase. > */ >- (void)setreuid(pwent->pw_uid, saved_uid); >- retval = load_private_key(identity, pass, &key, &comment_priv); >- free(identity); >- (void)setuid(saved_uid); >- if (!retval) >+ retval = auth_via_key(pamh, KEY_DSA, SSH_CLIENT_ID_DSA, pwent, >+ pass); >+ if (auth_via_key(pamh, KEY_RSA, SSH_CLIENT_IDENTITY, pwent, pass) >+ != PAM_SUCCESS && retval != PAM_SUCCESS) > return PAM_AUTH_ERR; > /* >- * Save the key and comment to pass to ssh-agent in the session >- * phase. >- */ >- if ((retval = pam_set_data(pamh, "ssh_private_key", key.rsa, >- rsa_cleanup)) != PAM_SUCCESS) { >- RSA_free(key.rsa); >- free(comment_priv); >- return retval; >- } >- if ((retval = pam_set_data(pamh, "ssh_key_comment", comment_priv, >- ssh_cleanup)) != PAM_SUCCESS) { >- free(comment_priv); >- return retval; >- } >- /* > * Copy the passwd entry (in case successive calls are made) > * and save it for the session phase. > */ >@@ -333,7 +387,10 @@ > char *env_end; /* end of env */ > char *env_file; /* to store env */ > FILE *env_fp; /* env_file handle */ >- Key key; /* user's private key */ >+ char *data_name; /* PAM state */ >+ int final; /* final return value */ >+ int index; /* for saved keys */ >+ Key *key; /* user's private key */ > FILE *pipe; /* ssh-agent handle */ > const PASSWD *pwent; /* user's passwd entry */ > int retval; /* from calls */ >@@ -351,9 +408,10 @@ > if ((retval = pam_get_item(pamh, PAM_TTY, (const void **)&tty)) > != PAM_SUCCESS) > return retval; >- if (*tty == ':' && gethostname(hname, sizeof hname) == 0) { >- if (asprintf(&env_file, "%s/.ssh/agent-%s%s", >- pwent->pw_dir, hname, tty) == -1) { >+ if (gethostname(hname, sizeof hname) == 0) { >+ if (asprintf(&env_file, "%s/.ssh/agent-%s%s%s", >+ pwent->pw_dir, hname, *tty == ':' ? "" : ":", tty) >+ == -1) { > syslog(LOG_CRIT, "%s: %m", MODULE_NAME); > return PAM_SERVICE_ERR; > } >@@ -371,7 +429,8 @@ > /* start the agent as the user */ > saved_uid = geteuid(); > (void)seteuid(pwent->pw_uid); >- env_fp = fopen(env_file, "w"); >+ if ((env_fp = fopen(env_file, "w"))) >+ (void)chmod(env_file, S_IRUSR); > pipe = popen(PATH_SSH_AGENT, "r"); > (void)seteuid(saved_uid); > if (!pipe) { >@@ -380,6 +439,11 @@ > (void)fclose(env_fp); > return PAM_SESSION_ERR; > } >+ /* >+ * Save environment for application with pam_putenv() >+ * but also with env_* functions for our own call to >+ * ssh_get_authentication_connection(). >+ */ > if (!(ssh_env = env_new())) > return PAM_SESSION_ERR; > if ((retval = pam_set_data(pamh, "ssh_env_handle", ssh_env, >@@ -388,11 +452,6 @@ > while (fgets(parse, sizeof parse, pipe)) { > if (env_fp) > (void)fputs(parse, env_fp); >- /* >- * Save environment for application with pam_putenv() >- * but also with env_* functions for our own call to >- * ssh_get_authentication_connection(). >- */ > if (strchr(parse, '=') && (env_end = strchr(parse, ';'))) { > *env_end = '\0'; > /* pass to the application ... */ >@@ -427,13 +486,8 @@ > env_destroy(ssh_env); > return PAM_SESSION_ERR; > } >- key.type = KEY_RSA; >- /* connect to the agent and hand off the private key */ >- if ((retval = pam_get_data(pamh, "ssh_private_key", >- (const void **)&key.rsa)) != PAM_SUCCESS || >- (retval = pam_get_data(pamh, "ssh_key_comment", >- (const void **)&comment)) != PAM_SUCCESS || >- (retval = env_commit(ssh_env)) != PAM_SUCCESS) { >+ /* connect to the agent */ >+ if ((retval = env_commit(ssh_env)) != PAM_SUCCESS) { > env_destroy(ssh_env); > return retval; > } >@@ -442,11 +496,38 @@ > MODULE_NAME); > env_destroy(ssh_env); > return PAM_SESSION_ERR; >+ } >+ /* hand off each private key to the agent */ >+ final = 0; >+ for (index = 0; ; index++) { >+ if (!asprintf(&data_name, "ssh_private_key_%d", index)) { >+ syslog(LOG_CRIT, "%s: %m", MODULE_NAME); >+ ssh_close_authentication_connection(ac); >+ env_destroy(ssh_env); >+ return PAM_SERVICE_ERR; >+ } >+ retval = pam_get_data(pamh, data_name, (const void **)&key); >+ free(data_name); >+ if (retval != PAM_SUCCESS) >+ break; >+ if (!asprintf(&data_name, "ssh_key_comment_%d", index)) { >+ syslog(LOG_CRIT, "%s: %m", MODULE_NAME); >+ ssh_close_authentication_connection(ac); >+ env_destroy(ssh_env); >+ return PAM_SERVICE_ERR; >+ } >+ retval = pam_get_data(pamh, data_name, >+ (const void **)&comment); >+ free(data_name); >+ if (retval != PAM_SUCCESS) >+ break; >+ retval = ssh_add_identity(ac, key, comment); >+ if (!final) >+ final = retval; > } >- retval = ssh_add_identity(ac, key.rsa, comment); > ssh_close_authentication_connection(ac); >- env_swap(ssh_env, 0); >- return retval ? PAM_SUCCESS : PAM_SESSION_ERR; >+ env_swap(ssh_env, 0); /* restore original environment */ >+ return final ? PAM_SUCCESS : PAM_SESSION_ERR; > } > > >@@ -461,6 +542,7 @@ > int retval; /* from calls */ > ENV *ssh_env; /* env handle */ > >+ /* invoke the cached environment to re-access the agent */ > if ((retval = pam_get_data(pamh, "ssh_env_handle", > (const void **)&ssh_env)) != PAM_SUCCESS) > return retval;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 21877
: 11029