| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: pam_ssh.c,v 1.25 2018/04/07 19:28:32 christos Exp $ */ | | 1 | /* $NetBSD: pam_ssh.c,v 1.26 2018/08/26 08:54:03 christos Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2003 Networks Associates Technology, Inc. | | 4 | * Copyright (c) 2003 Networks Associates Technology, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This software was developed for the FreeBSD Project by ThinkSec AS and | | 7 | * This software was developed for the FreeBSD Project by ThinkSec AS and |
8 | * NAI Labs, the Security Research Division of Network Associates, Inc. | | 8 | * NAI Labs, the Security Research Division of Network Associates, Inc. |
9 | * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the | | 9 | * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the |
10 | * DARPA CHATS research program. | | 10 | * DARPA CHATS research program. |
11 | * | | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | | 12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions | | 13 | * modification, are permitted provided that the following conditions |
14 | * are met: | | 14 | * are met: |
| @@ -28,62 +28,62 @@ | | | @@ -28,62 +28,62 @@ |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
34 | * SUCH DAMAGE. | | 34 | * SUCH DAMAGE. |
35 | */ | | 35 | */ |
36 | | | 36 | |
37 | #include <sys/cdefs.h> | | 37 | #include <sys/cdefs.h> |
38 | #ifdef __FreeBSD__ | | 38 | #ifdef __FreeBSD__ |
39 | __FBSDID("$FreeBSD: src/lib/libpam/modules/pam_ssh/pam_ssh.c,v 1.40 2004/02/10 10:13:21 des Exp $"); | | 39 | __FBSDID("$FreeBSD: src/lib/libpam/modules/pam_ssh/pam_ssh.c,v 1.40 2004/02/10 10:13:21 des Exp $"); |
40 | #else | | 40 | #else |
41 | __RCSID("$NetBSD: pam_ssh.c,v 1.25 2018/04/07 19:28:32 christos Exp $"); | | 41 | __RCSID("$NetBSD: pam_ssh.c,v 1.26 2018/08/26 08:54:03 christos Exp $"); |
42 | #endif | | 42 | #endif |
43 | | | 43 | |
44 | #include <sys/param.h> | | 44 | #include <sys/param.h> |
45 | #include <sys/wait.h> | | 45 | #include <sys/wait.h> |
46 | | | 46 | |
47 | #include <errno.h> | | 47 | #include <errno.h> |
48 | #include <fcntl.h> | | 48 | #include <fcntl.h> |
49 | #include <paths.h> | | 49 | #include <paths.h> |
50 | #include <pwd.h> | | 50 | #include <pwd.h> |
51 | #include <signal.h> | | 51 | #include <signal.h> |
52 | #include <stdio.h> | | 52 | #include <stdio.h> |
53 | #include <string.h> | | 53 | #include <string.h> |
54 | #include <unistd.h> | | 54 | #include <unistd.h> |
55 | | | 55 | |
56 | #define PAM_SM_AUTH | | 56 | #define PAM_SM_AUTH |
57 | #define PAM_SM_SESSION | | 57 | #define PAM_SM_SESSION |
58 | | | 58 | |
59 | #include <security/pam_appl.h> | | 59 | #include <security/pam_appl.h> |
60 | #include <security/pam_modules.h> | | 60 | #include <security/pam_modules.h> |
61 | #include <security/openpam.h> | | 61 | #include <security/openpam.h> |
62 | | | 62 | |
63 | #include <openssl/evp.h> | | 63 | #include <openssl/evp.h> |
64 | | | 64 | |
65 | #include "key.h" | | 65 | #include "sshkey.h" |
66 | #include "buffer.h" | | 66 | #include "sshbuf.h" |
67 | #include "authfd.h" | | 67 | #include "authfd.h" |
68 | #include "authfile.h" | | 68 | #include "authfile.h" |
69 | | | 69 | |
70 | #define ssh_add_identity(auth, key, comment) \ | | 70 | #define ssh_add_identity(auth, key, comment) \ |
71 | ssh_add_identity_constrained(auth, key, comment, 0, 0, 0) | | 71 | ssh_add_identity_constrained(auth, key, comment, 0, 0, 0) |
72 | | | 72 | |
73 | extern char **environ; | | 73 | extern char **environ; |
74 | | | 74 | |
75 | struct pam_ssh_key { | | 75 | struct pam_ssh_key { |
76 | Key *key; | | 76 | struct sshkey *key; |
77 | char *comment; | | 77 | char *comment; |
78 | }; | | 78 | }; |
79 | | | 79 | |
80 | static const char *pam_ssh_prompt = "SSH passphrase: "; | | 80 | static const char *pam_ssh_prompt = "SSH passphrase: "; |
81 | static const char *pam_ssh_have_keys = "pam_ssh_have_keys"; | | 81 | static const char *pam_ssh_have_keys = "pam_ssh_have_keys"; |
82 | | | 82 | |
83 | static const char *pam_ssh_keyfiles[] = { | | 83 | static const char *pam_ssh_keyfiles[] = { |
84 | ".ssh/identity", /* SSH1 RSA key */ | | 84 | ".ssh/identity", /* SSH1 RSA key */ |
85 | ".ssh/id_rsa", /* SSH2 RSA key */ | | 85 | ".ssh/id_rsa", /* SSH2 RSA key */ |
86 | ".ssh/id_dsa", /* SSH2 DSA key */ | | 86 | ".ssh/id_dsa", /* SSH2 DSA key */ |
87 | ".ssh/id_ecdsa", /* SSH2 ECDSA key */ | | 87 | ".ssh/id_ecdsa", /* SSH2 ECDSA key */ |
88 | NULL | | 88 | NULL |
89 | }; | | 89 | }; |
| @@ -93,77 +93,78 @@ static const char *const pam_ssh_agent_a | | | @@ -93,77 +93,78 @@ static const char *const pam_ssh_agent_a |
93 | static const char *const pam_ssh_agent_envp[] = { NULL }; | | 93 | static const char *const pam_ssh_agent_envp[] = { NULL }; |
94 | | | 94 | |
95 | /* | | 95 | /* |
96 | * Attempts to load a private key from the specified file in the specified | | 96 | * Attempts to load a private key from the specified file in the specified |
97 | * directory, using the specified passphrase. If successful, returns a | | 97 | * directory, using the specified passphrase. If successful, returns a |
98 | * struct pam_ssh_key containing the key and its comment. | | 98 | * struct pam_ssh_key containing the key and its comment. |
99 | */ | | 99 | */ |
100 | static struct pam_ssh_key * | | 100 | static struct pam_ssh_key * |
101 | pam_ssh_load_key(const char *dir, const char *kfn, const char *passphrase, | | 101 | pam_ssh_load_key(const char *dir, const char *kfn, const char *passphrase, |
102 | int nullok) | | 102 | int nullok) |
103 | { | | 103 | { |
104 | struct pam_ssh_key *psk; | | 104 | struct pam_ssh_key *psk; |
105 | char fn[PATH_MAX]; | | 105 | char fn[PATH_MAX]; |
| | | 106 | int r; |
106 | char *comment; | | 107 | char *comment; |
107 | Key *key; | | 108 | struct sshkey *key; |
108 | | | 109 | |
109 | if (snprintf(fn, sizeof(fn), "%s/%s", dir, kfn) > (int)sizeof(fn)) | | 110 | if (snprintf(fn, sizeof(fn), "%s/%s", dir, kfn) > (int)sizeof(fn)) |
110 | return (NULL); | | 111 | return (NULL); |
111 | comment = NULL; | | 112 | comment = NULL; |
112 | /* | | 113 | /* |
113 | * If the key is unencrypted, OpenSSL ignores the passphrase, so | | 114 | * If the key is unencrypted, OpenSSL ignores the passphrase, so |
114 | * it will seem like the user typed in the right one. This allows | | 115 | * it will seem like the user typed in the right one. This allows |
115 | * a user to circumvent nullok by providing a dummy passphrase. | | 116 | * a user to circumvent nullok by providing a dummy passphrase. |
116 | * Verify that the key really *is* encrypted by trying to load it | | 117 | * Verify that the key really *is* encrypted by trying to load it |
117 | * with an empty passphrase, and if the key is not encrypted, | | 118 | * with an empty passphrase, and if the key is not encrypted, |
118 | * accept only an empty passphrase. | | 119 | * accept only an empty passphrase. |
119 | */ | | 120 | */ |
120 | key = key_load_private(fn, "", &comment); | | 121 | r = sshkey_load_private(fn, "", &key, &comment); |
121 | if (key != NULL && !(*passphrase == '\0' && nullok)) { | | 122 | if (r && !(*passphrase == '\0' && nullok)) { |
122 | key_free(key); | | 123 | sshkey_free(key); |
123 | free(comment); | | 124 | free(comment); |
124 | return (NULL); | | 125 | return (NULL); |
125 | } | | 126 | } |
126 | if (key == NULL) | | 127 | if (r) |
127 | key = key_load_private(fn, passphrase, &comment); | | 128 | sshkey_load_private(fn, passphrase, &key, &comment); |
128 | if (key == NULL) { | | 129 | if (r) { |
129 | openpam_log(PAM_LOG_DEBUG, "failed to load key from %s", fn); | | 130 | openpam_log(PAM_LOG_DEBUG, "failed to load key from %s", fn); |
130 | if (comment != NULL) | | 131 | if (comment != NULL) |
131 | free(comment); | | 132 | free(comment); |
132 | return (NULL); | | 133 | return (NULL); |
133 | } | | 134 | } |
134 | | | 135 | |
135 | openpam_log(PAM_LOG_DEBUG, "loaded '%s' from %s", comment, fn); | | 136 | openpam_log(PAM_LOG_DEBUG, "loaded '%s' from %s", comment, fn); |
136 | if ((psk = malloc(sizeof(*psk))) == NULL) { | | 137 | if ((psk = malloc(sizeof(*psk))) == NULL) { |
137 | key_free(key); | | 138 | sshkey_free(key); |
138 | free(comment); | | 139 | free(comment); |
139 | return (NULL); | | 140 | return (NULL); |
140 | } | | 141 | } |
141 | psk->key = key; | | 142 | psk->key = key; |
142 | psk->comment = comment; | | 143 | psk->comment = comment; |
143 | return (psk); | | 144 | return (psk); |
144 | } | | 145 | } |
145 | | | 146 | |
146 | /* | | 147 | /* |
147 | * Wipes a private key and frees the associated resources. | | 148 | * Wipes a private key and frees the associated resources. |
148 | */ | | 149 | */ |
149 | static void | | 150 | static void |
150 | pam_ssh_free_key(pam_handle_t *pamh __unused, | | 151 | pam_ssh_free_key(pam_handle_t *pamh __unused, |
151 | void *data, int pam_err __unused) | | 152 | void *data, int pam_err __unused) |
152 | { | | 153 | { |
153 | struct pam_ssh_key *psk; | | 154 | struct pam_ssh_key *psk; |
154 | | | 155 | |
155 | psk = data; | | 156 | psk = data; |
156 | key_free(psk->key); | | 157 | sshkey_free(psk->key); |
157 | free(psk->comment); | | 158 | free(psk->comment); |
158 | free(psk); | | 159 | free(psk); |
159 | } | | 160 | } |
160 | | | 161 | |
161 | PAM_EXTERN int | | 162 | PAM_EXTERN int |
162 | pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, | | 163 | pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, |
163 | int argc __unused, const char *argv[] __unused) | | 164 | int argc __unused, const char *argv[] __unused) |
164 | { | | 165 | { |
165 | const char **kfn, *passphrase, *user; | | 166 | const char **kfn, *passphrase, *user; |
166 | const void *item; | | 167 | const void *item; |
167 | struct passwd *pwd, pwres; | | 168 | struct passwd *pwd, pwres; |
168 | struct pam_ssh_key *psk; | | 169 | struct pam_ssh_key *psk; |
169 | int nkeys, nullok, pam_err, pass; | | 170 | int nkeys, nullok, pam_err, pass; |