2
* Copyright (c) 2000 Markus Friedl. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
7
* 1. Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* 2. Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
13
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
RCSID("$OpenBSD: auth2-pubkey.c,v 1.6 2004/01/19 21:25:15 markus Exp $");
38
#include "pathnames.h"
40
#include "auth-options.h"
42
#include "monitor_wrap.h"
45
extern ServerOptions options;
46
extern u_char *session_id2;
47
extern u_int session_id2_len;
50
userauth_pubkey(Authctxt *authctxt)
56
u_int alen, blen, slen;
58
int authenticated = 0;
60
if (!authctxt->valid) {
61
debug2("userauth_pubkey: disabled because of invalid user");
64
have_sig = packet_get_char();
65
if (datafellows & SSH_BUG_PKAUTH) {
66
debug2("userauth_pubkey: SSH_BUG_PKAUTH");
67
/* no explicit pkalg given */
68
pkblob = packet_get_string(&blen);
70
buffer_append(&b, pkblob, blen);
71
/* so we have to extract the pkalg from the pkblob */
72
pkalg = buffer_get_string(&b, &alen);
75
pkalg = packet_get_string(&alen);
76
pkblob = packet_get_string(&blen);
78
pktype = key_type_from_name(pkalg);
79
if (pktype == KEY_UNSPEC) {
80
/* this is perfectly legal */
81
logit("userauth_pubkey: unsupported public key algorithm: %s",
85
key = key_from_blob(pkblob, blen);
87
error("userauth_pubkey: cannot decode key: %s", pkalg);
90
if (key->type != pktype) {
91
error("userauth_pubkey: type mismatch for decoded key "
92
"(received %d, expected %d)", key->type, pktype);
96
sig = packet_get_string(&slen);
99
if (datafellows & SSH_OLD_SESSIONID) {
100
buffer_append(&b, session_id2, session_id2_len);
102
buffer_put_string(&b, session_id2, session_id2_len);
104
/* reconstruct packet */
105
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
106
buffer_put_cstring(&b, authctxt->user);
107
buffer_put_cstring(&b,
108
datafellows & SSH_BUG_PKSERVICE ?
111
if (datafellows & SSH_BUG_PKAUTH) {
112
buffer_put_char(&b, have_sig);
114
buffer_put_cstring(&b, "publickey");
115
buffer_put_char(&b, have_sig);
116
buffer_put_cstring(&b, pkalg);
118
buffer_put_string(&b, pkblob, blen);
122
/* test for correct signature */
124
if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
125
PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
126
buffer_len(&b))) == 1)
131
debug("test whether pkalg/pkblob are acceptable");
134
/* XXX fake reply and always send PK_OK ? */
136
* XXX this allows testing whether a user is allowed
137
* to login: if you happen to have a valid pubkey this
138
* message is sent. the message is NEVER sent at all
139
* if a user is not allowed to login. is this an
142
if (PRIVSEP(user_key_allowed(authctxt->pw, key))) {
143
packet_start(SSH2_MSG_USERAUTH_PK_OK);
144
packet_put_string(pkalg, alen);
145
packet_put_string(pkblob, blen);
148
authctxt->postponed = 1;
151
if (authenticated != 1)
152
auth_clear_options();
154
debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
160
if (check_nt_auth(0, authctxt->pw) == 0)
163
return authenticated;
166
/* return 1 if user allows given key */
168
user_key_allowed2(struct passwd *pw, Key *key, char *file)
178
/* Temporarily use the user's uid. */
179
temporarily_use_uid(pw);
181
debug("trying public key file %s", file);
183
/* Fail quietly if file does not exist */
184
if (stat(file, &st) < 0) {
185
/* Restore the privileged uid. */
189
/* Open the file containing the authorized keys. */
190
f = fopen(file, "r");
192
/* Restore the privileged uid. */
196
if (options.strict_modes &&
197
secure_filename(f, file, pw, line, sizeof(line)) != 0) {
199
logit("Authentication refused: %s", line);
205
found = key_new(key->type);
207
while (fgets(line, sizeof(line), f)) {
208
char *cp, *options = NULL;
210
/* Skip leading whitespace, empty and comment lines. */
211
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
213
if (!*cp || *cp == '\n' || *cp == '#')
216
if (key_read(found, &cp) != 1) {
217
/* no key? check if there are options for this key */
219
debug2("user_key_allowed: check options: '%s'", cp);
221
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
222
if (*cp == '\\' && cp[1] == '"')
223
cp++; /* Skip both */
227
/* Skip remaining whitespace. */
228
for (; *cp == ' ' || *cp == '\t'; cp++)
230
if (key_read(found, &cp) != 1) {
231
debug2("user_key_allowed: advance: '%s'", cp);
232
/* still no key? advance to next line*/
236
if (key_equal(found, key) &&
237
auth_parse_options(pw, options, file, linenum) == 1) {
239
debug("matching key found: file %s, line %lu",
241
fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
242
verbose("Found matching %s key: %s",
243
key_type(found), fp);
252
debug2("key not found");
256
/* check whether given key is in .ssh/authorized_keys* */
258
user_key_allowed(struct passwd *pw, Key *key)
263
file = authorized_keys_file(pw);
264
success = user_key_allowed2(pw, key, file);
269
/* try suffix "2" for backward compat, too */
270
file = authorized_keys_file2(pw);
271
success = user_key_allowed2(pw, key, file);
276
Authmethod method_pubkey = {
279
&options.pubkey_authentication