Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

pam_ssh: Don't allow a bogus passphrase for unencrypted keys.

key_load_private() ignores the passphrase argument if the private key
is unencrypted.  This defeats the nullok check, because it means a
non-null passphrase will successfully unlock the key.

To address this, try at first to load the key without a passphrase.
If this succeeds and the user provided a non-empty passphrase *or*
nullok is false, reject the key.

While I'm here: Load the ECDSA key if there is one.

Obtained-from:  FreeBSD 227757, 219426, & 226101
  • Loading branch information...
commit 09e61f6cd8073fbb48eab8523b4bcc4f82dac34d 1 parent 3254d1d
authored
9  lib/pam_module/pam_ssh/pam_ssh.8
... ...
@@ -1,6 +1,6 @@
1 1
 .\" Copyright (c) 2001 Mark R V Murray
2  
-.\" All rights reserved.
3 2
 .\" Copyright (c) 2001-2003 Networks Associates Technology, Inc.
  3
+.\" Copyright (c) 2004-2011 Dag-Erling Smørgrav
4 4
 .\" All rights reserved.
5 5
 .\"
6 6
 .\" This software was developed for the FreeBSD Project by ThinkSec AS and
@@ -32,10 +32,9 @@
32 32
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 33
 .\" SUCH DAMAGE.
34 34
 .\"
35  
-.\" $FreeBSD: src/lib/libpam/modules/pam_ssh/pam_ssh.8,v 1.14 2005/09/22 05:35:24 des Exp $
36  
-.\" $DragonFly: src/lib/pam_module/pam_ssh/pam_ssh.8,v 1.1 2005/07/12 23:26:49 joerg Exp $
  35
+.\" $FreeBSD: src/lib/libpam/modules/pam_ssh/pam_ssh.8,v 1.15 2011/10/07 12:58:33 des Exp $
37 36
 .\"
38  
-.Dd November 26, 2001
  37
+.Dd December 24, 2011
39 38
 .Dt PAM_SSH 8
40 39
 .Os
41 40
 .Sh NAME
@@ -136,6 +135,8 @@ SSH1 RSA key
136 135
 SSH2 RSA key
137 136
 .It Pa $HOME/.ssh/id_dsa
138 137
 SSH2 DSA key
  138
+.It Pa $HOME/.ssh/id_ecdsa
  139
+SSH2 ECDSA key
139 140
 .El
140 141
 .Sh SEE ALSO
141 142
 .Xr ssh-agent 1 ,
42  lib/pam_module/pam_ssh/pam_ssh.c
... ...
@@ -1,5 +1,6 @@
1 1
 /*-
2 2
  * Copyright (c) 2003 Networks Associates Technology, Inc.
  3
+ * Copyright (c) 2004-2011 Dag-Erling Smørgrav
3 4
  * All rights reserved.
4 5
  *
5 6
  * This software was developed for the FreeBSD Project by ThinkSec AS and
@@ -31,7 +32,7 @@
31 32
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 33
  * SUCH DAMAGE.
33 34
  *
34  
- * $FreeBSD: src/lib/libpam/modules/pam_ssh/pam_ssh.c,v 1.45 2007/12/21 12:00:15 des Exp $
  35
+ * $FreeBSD: src/lib/libpam/modules/pam_ssh/pam_ssh.c,v 1.49 2011/11/20 15:18:49 des Exp $
35 36
  */
36 37
 
37 38
 #include <sys/param.h>
@@ -77,6 +78,7 @@ static const char *pam_ssh_keyfiles[] = {
77 78
 	".ssh/identity",	/* SSH1 RSA key */
78 79
 	".ssh/id_rsa",		/* SSH2 RSA key */
79 80
 	".ssh/id_dsa",		/* SSH2 DSA key */
  81
+	".ssh/id_ecdsa",	/* SSH2 ECDSA key */
80 82
 	NULL
81 83
 };
82 84
 
@@ -90,7 +92,8 @@ static char *const pam_ssh_agent_envp[] = { NULL };
90 92
  * struct pam_ssh_key containing the key and its comment.
91 93
  */
92 94
 static struct pam_ssh_key *
93  
-pam_ssh_load_key(const char *dir, const char *kfn, const char *passphrase)
  95
+pam_ssh_load_key(const char *dir, const char *kfn, const char *passphrase,
  96
+    int nullok)
94 97
 {
95 98
 	struct pam_ssh_key *psk;
96 99
 	char fn[PATH_MAX];
@@ -100,13 +103,27 @@ pam_ssh_load_key(const char *dir, const char *kfn, const char *passphrase)
100 103
 	if (snprintf(fn, sizeof(fn), "%s/%s", dir, kfn) > (int)sizeof(fn))
101 104
 		return (NULL);
102 105
 	comment = NULL;
103  
-	key = key_load_private(fn, passphrase, &comment);
  106
+	/*
  107
+	 * If the key is unencrypted, OpenSSL ignores the passphrase, so
  108
+	 * it will seem like the user typed in the right one.  This allows
  109
+	 * a user to circumvent nullok by providing a dummy passphrase.
  110
+	 * Verify that the key really *is* encrypted by trying to load it
  111
+	 * with an empty passphrase, and if the key is not encrypted,
  112
+	 * accept only an empty passphrase.
  113
+	 */
  114
+	key = key_load_private(fn, NULL, &comment);
  115
+	if (key != NULL && !(*passphrase == '\0' && nullok)) {
  116
+		key_free(key);
  117
+		return (NULL);
  118
+	}
  119
+	if (key == NULL)
  120
+		key = key_load_private(fn, passphrase, &comment);
104 121
 	if (key == NULL) {
105  
-		openpam_log(PAM_LOG_DEBUG, "failed to load key from %s\n", fn);
  122
+		openpam_log(PAM_LOG_DEBUG, "failed to load key from %s", fn);
106 123
 		return (NULL);
107 124
 	}
108 125
 
109  
-	openpam_log(PAM_LOG_DEBUG, "loaded '%s' from %s\n", comment, fn);
  126
+	openpam_log(PAM_LOG_DEBUG, "loaded '%s' from %s", comment, fn);
110 127
 	if ((psk = malloc(sizeof(*psk))) == NULL) {
111 128
 		key_free(key);
112 129
 		free(comment);
@@ -167,9 +184,6 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags __unused,
167 184
 	if (pam_err != PAM_SUCCESS)
168 185
 		return (pam_err);
169 186
 
170  
-	if (*passphrase == '\0' && !nullok)
171  
-		goto skip_keys;
172  
-
173 187
 	/* switch to user credentials */
174 188
 	pam_err = openpam_borrow_cred(pamh, pwd);
175 189
 	if (pam_err != PAM_SUCCESS)
@@ -177,7 +191,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags __unused,
177 191
 
178 192
 	/* try to load keys from all keyfiles we know of */
179 193
 	for (kfn = pam_ssh_keyfiles; *kfn != NULL; ++kfn) {
180  
-		psk = pam_ssh_load_key(pwd->pw_dir, *kfn, passphrase);
  194
+		psk = pam_ssh_load_key(pwd->pw_dir, *kfn, passphrase, nullok);
181 195
 		if (psk != NULL) {
182 196
 			pam_set_data(pamh, *kfn, psk, pam_ssh_free_key);
183 197
 			++nkeys;
@@ -187,7 +201,6 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags __unused,
187 201
 	/* switch back to arbitrator credentials */
188 202
 	openpam_restore_cred(pamh);
189 203
 
190  
- skip_keys:
191 204
 	/*
192 205
 	 * If we tried an old token and didn't get anything, and
193 206
 	 * try_first_pass was specified, try again after prompting the
@@ -312,6 +325,7 @@ pam_ssh_add_keys_to_agent(pam_handle_t *pamh)
312 325
 	AuthenticationConnection *ac;
313 326
 	const struct pam_ssh_key *psk;
314 327
 	const char **kfn;
  328
+	const void *item;
315 329
 	char **envlist, **env;
316 330
 	int pam_err;
317 331
 
@@ -324,16 +338,16 @@ pam_ssh_add_keys_to_agent(pam_handle_t *pamh)
324 338
 
325 339
 	/* get a connection to the agent */
326 340
 	if ((ac = ssh_get_authentication_connection()) == NULL) {
  341
+		openpam_log(PAM_LOG_DEBUG, "failed to connect to the agent");
327 342
 		pam_err = PAM_SYSTEM_ERR;
328 343
 		goto end;
329 344
 	}
330 345
 
331 346
 	/* look for keys to add to it */
332 347
 	for (kfn = pam_ssh_keyfiles; *kfn != NULL; ++kfn) {
333  
-		const void *vp;
334  
-		pam_err = pam_get_data(pamh, *kfn, &vp);
335  
-		psk = vp;
336  
-		if (pam_err == PAM_SUCCESS && psk != NULL) {
  348
+		pam_err = pam_get_data(pamh, *kfn, &item);
  349
+		if (pam_err == PAM_SUCCESS && item != NULL) {
  350
+			psk = item;
337 351
 			if (ssh_add_identity(ac, psk->key, psk->comment))
338 352
 				openpam_log(PAM_LOG_DEBUG,
339 353
 				    "added %s to ssh agent", psk->comment);

0 notes on commit 09e61f6

Please sign in to comment.
Something went wrong with that request. Please try again.