]> andersk Git - openssh.git/blame - auth1.c
[configure.ac] Comment some non obvious platforms in the target-specific
[openssh.git] / auth1.c
CommitLineData
a306f2dd 1/*
2 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3 * All rights reserved
bcbf86ec 4 *
5 * As far as I am concerned, the code I have written for this software
6 * can be used freely for any purpose. Any derived versions of this
7 * software must be clearly marked as such, and if the derived work is
8 * incompatible with the protocol description in the RFC file, it must be
9 * called by a name other than "ssh" or "Secure Shell".
a306f2dd 10 */
11
12#include "includes.h"
d77347cc 13RCSID("$OpenBSD: auth1.c,v 1.59 2004/07/28 09:40:29 markus Exp $");
94ec8c6b 14
a306f2dd 15#include "xmalloc.h"
16#include "rsa.h"
42f11eb2 17#include "ssh1.h"
a306f2dd 18#include "packet.h"
19#include "buffer.h"
42f11eb2 20#include "log.h"
a306f2dd 21#include "servconf.h"
22#include "compat.h"
23#include "auth.h"
7899c98f 24#include "channels.h"
a306f2dd 25#include "session.h"
ced49be2 26#include "uidswap.h"
1853d1ef 27#include "monitor_wrap.h"
9aab0af7 28#include "buffer.h"
a306f2dd 29
30/* import */
31extern ServerOptions options;
9aab0af7 32extern Buffer loginmsg;
94ec8c6b 33
a306f2dd 34/*
35 * convert ssh auth msg type into description
36 */
396c147e 37static char *
a306f2dd 38get_authname(int type)
39{
40 static char buf[1024];
41 switch (type) {
42 case SSH_CMSG_AUTH_PASSWORD:
43 return "password";
44 case SSH_CMSG_AUTH_RSA:
45 return "rsa";
46 case SSH_CMSG_AUTH_RHOSTS_RSA:
47 return "rhosts-rsa";
48 case SSH_CMSG_AUTH_RHOSTS:
49 return "rhosts";
59c97189 50 case SSH_CMSG_AUTH_TIS:
51 case SSH_CMSG_AUTH_TIS_RESPONSE:
52 return "challenge-response";
a306f2dd 53 }
54 snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
55 return buf;
56}
57
58/*
59c97189 59 * read packets, try to authenticate the user and
60 * return only if authentication is successful
a306f2dd 61 */
396c147e 62static void
59c97189 63do_authloop(Authctxt *authctxt)
a306f2dd 64{
94ec8c6b 65 int authenticated = 0;
1e3b8b07 66 u_int bits;
b775c6f2 67 Key *client_host_key;
a306f2dd 68 BIGNUM *n;
94ec8c6b 69 char *client_user, *password;
59c97189 70 char info[1024];
1e3b8b07 71 u_int dlen;
1e3b8b07 72 u_int ulen;
05114c74 73 int prev, type = 0;
59c97189 74
75 debug("Attempting authentication for %s%.100s.",
d77347cc 76 authctxt->valid ? "" : "invalid user ", authctxt->user);
59c97189 77
78 /* If the user has no password, accept authentication immediately. */
79 if (options.password_authentication &&
1c590258 80#ifdef KRB5
59c97189 81 (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
82#endif
1853d1ef 83 PRIVSEP(auth_password(authctxt, ""))) {
ece30983 84#ifdef USE_PAM
85 if (options.use_pam && (PRIVSEP(do_pam_account())))
86#endif
87 {
88 auth_log(authctxt, 1, "without authentication", "");
89 return;
90 }
59c97189 91 }
a306f2dd 92
93 /* Indicate that authentication is needed. */
94 packet_start(SSH_SMSG_FAILURE);
95 packet_send();
96 packet_write_wait();
97
94ec8c6b 98 client_user = NULL;
99
59c97189 100 for (;;) {
94ec8c6b 101 /* default to fail */
102 authenticated = 0;
103
59c97189 104 info[0] = '\0';
a306f2dd 105
106 /* Get a packet from the client. */
05114c74 107 prev = type;
54a5250f 108 type = packet_read();
a306f2dd 109
05114c74 110 /*
111 * If we started challenge-response authentication but the
112 * next packet is not a response to our challenge, release
113 * the resources allocated by get_challenge() (which would
114 * normally have been released by verify_response() had we
115 * received such a response)
116 */
117 if (prev == SSH_CMSG_AUTH_TIS &&
118 type != SSH_CMSG_AUTH_TIS_RESPONSE)
119 abandon_challenge_response(authctxt);
120
a306f2dd 121 /* Process the packet. */
122 switch (type) {
a306f2dd 123 case SSH_CMSG_AUTH_RHOSTS_RSA:
124 if (!options.rhosts_rsa_authentication) {
125 verbose("Rhosts with RSA authentication disabled.");
126 break;
127 }
128 /*
129 * Get client user name. Note that we just have to
130 * trust the client; root on the client machine can
131 * claim to be any user.
132 */
133 client_user = packet_get_string(&ulen);
134
135 /* Get the client host key. */
b775c6f2 136 client_host_key = key_new(KEY_RSA1);
a306f2dd 137 bits = packet_get_int();
20b279e6 138 packet_get_bignum(client_host_key->rsa->e);
139 packet_get_bignum(client_host_key->rsa->n);
a306f2dd 140
b775c6f2 141 if (bits != BN_num_bits(client_host_key->rsa->n))
94ec8c6b 142 verbose("Warning: keysize mismatch for client_host_key: "
b775c6f2 143 "actual %d, announced %d",
7203d6bb 144 BN_num_bits(client_host_key->rsa->n), bits);
95500969 145 packet_check_eom();
a306f2dd 146
fdaef11e 147 authenticated = auth_rhosts_rsa(authctxt, client_user,
dc421aa3 148 client_host_key);
b775c6f2 149 key_free(client_host_key);
a306f2dd 150
59c97189 151 snprintf(info, sizeof info, " ruser %.100s", client_user);
a306f2dd 152 break;
153
154 case SSH_CMSG_AUTH_RSA:
155 if (!options.rsa_authentication) {
156 verbose("RSA authentication disabled.");
157 break;
158 }
159 /* RSA authentication requested. */
b775c6f2 160 if ((n = BN_new()) == NULL)
161 fatal("do_authloop: BN_new failed");
20b279e6 162 packet_get_bignum(n);
95500969 163 packet_check_eom();
fdaef11e 164 authenticated = auth_rsa(authctxt, n);
a306f2dd 165 BN_clear_free(n);
166 break;
167
168 case SSH_CMSG_AUTH_PASSWORD:
169 if (!options.password_authentication) {
170 verbose("Password authentication disabled.");
171 break;
172 }
173 /*
174 * Read user password. It is in plain text, but was
175 * transmitted over the encrypted channel so it is
176 * not visible to an outside observer.
177 */
178 password = packet_get_string(&dlen);
95500969 179 packet_check_eom();
a306f2dd 180
b4b5d644 181 /* Try authentication with the password. */
1853d1ef 182 authenticated = PRIVSEP(auth_password(authctxt, password));
a306f2dd 183
184 memset(password, 0, strlen(password));
185 xfree(password);
186 break;
187
a306f2dd 188 case SSH_CMSG_AUTH_TIS:
189 debug("rcvd SSH_CMSG_AUTH_TIS");
5ba55ada 190 if (options.challenge_response_authentication == 1) {
191 char *challenge = get_challenge(authctxt);
59c97189 192 if (challenge != NULL) {
193 debug("sending challenge '%s'", challenge);
a306f2dd 194 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
59c97189 195 packet_put_cstring(challenge);
5ba55ada 196 xfree(challenge);
a306f2dd 197 packet_send();
198 packet_write_wait();
199 continue;
200 }
201 }
202 break;
203 case SSH_CMSG_AUTH_TIS_RESPONSE:
204 debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
5ba55ada 205 if (options.challenge_response_authentication == 1) {
a306f2dd 206 char *response = packet_get_string(&dlen);
95500969 207 packet_check_eom();
59c97189 208 authenticated = verify_response(authctxt, response);
209 memset(response, 'r', dlen);
a306f2dd 210 xfree(response);
211 }
212 break;
a306f2dd 213
214 default:
215 /*
216 * Any unknown messages will be ignored (and failure
217 * returned) during authentication.
218 */
bbe88b6d 219 logit("Unknown message during authentication: type %d", type);
a306f2dd 220 break;
221 }
af774732 222#ifdef BSD_AUTH
223 if (authctxt->as) {
224 auth_close(authctxt->as);
225 authctxt->as = NULL;
226 }
227#endif
59c97189 228 if (!authctxt->valid && authenticated)
229 fatal("INTERNAL ERROR: authenticated invalid user %s",
230 authctxt->user);
a306f2dd 231
ef51930f 232#ifdef _UNICOS
ef51930f 233 if (authenticated && cray_access_denied(authctxt->user)) {
234 authenticated = 0;
235 fatal("Access denied for user %s.",authctxt->user);
236 }
237#endif /* _UNICOS */
238
2b87da3b 239#ifdef HAVE_CYGWIN
240 if (authenticated &&
02a57950 241 !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD,
242 authctxt->pw)) {
3c62e7eb 243 packet_disconnect("Authentication rejected for uid %d.",
02a57950 244 authctxt->pw == NULL ? -1 : authctxt->pw->pw_uid);
3c62e7eb 245 authenticated = 0;
246 }
3c418020 247#else
59c97189 248 /* Special handling for root */
5d47f1d4 249 if (authenticated && authctxt->pw->pw_uid == 0 &&
15853e93 250 !auth_root_allowed(get_authname(type)))
59c97189 251 authenticated = 0;
3c418020 252#endif
a306f2dd 253
5b9e2464 254#ifdef USE_PAM
aff51935 255 if (options.use_pam && authenticated &&
9aab0af7 256 !PRIVSEP(do_pam_account())) {
257 char *msg;
258 size_t len;
259
260 error("Access denied for user %s by PAM account "
261 "configuration", authctxt->user);
262 len = buffer_len(&loginmsg);
263 buffer_append(&loginmsg, "\0", 1);
264 msg = buffer_ptr(&loginmsg);
265 /* strip trailing newlines */
266 if (len > 0)
267 while (len > 0 && msg[--len] == '\n')
268 msg[len] = '\0';
269 else
270 msg = "Access denied.";
271 packet_disconnect(msg);
272 }
5b9e2464 273#endif
274
59c97189 275 /* Log before sending the reply */
276 auth_log(authctxt, authenticated, get_authname(type), info);
277
a306f2dd 278 if (client_user != NULL) {
279 xfree(client_user);
280 client_user = NULL;
281 }
282
94ec8c6b 283 if (authenticated)
284 return;
285
af4bd935 286 if (authctxt->failures++ > options.max_authtries)
59c97189 287 packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
a306f2dd 288
a306f2dd 289 packet_start(SSH_SMSG_FAILURE);
290 packet_send();
291 packet_write_wait();
292 }
293}
294
295/*
296 * Performs authentication of an incoming connection. Session key has already
297 * been exchanged and encryption is enabled.
298 */
2362db19 299void
300do_authentication(Authctxt *authctxt)
a306f2dd 301{
1e3b8b07 302 u_int ulen;
f8d99a32 303 char *user, *style = NULL;
a306f2dd 304
305 /* Get the name of the user that we wish to log in as. */
54a5250f 306 packet_read_expect(SSH_CMSG_USER);
a306f2dd 307
308 /* Get the user name. */
309 user = packet_get_string(&ulen);
95500969 310 packet_check_eom();
a306f2dd 311
59c97189 312 if ((style = strchr(user, ':')) != NULL)
ced49be2 313 *style++ = '\0';
59c97189 314
59c97189 315 authctxt->user = user;
316 authctxt->style = style;
317
a306f2dd 318 /* Verify that the user is a valid user. */
5f1f36b5 319 if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
59c97189 320 authctxt->valid = 1;
96d0bf74 321 else {
d77347cc 322 debug("do_authentication: invalid user %s", user);
96d0bf74 323 authctxt->pw = fakepw();
324 }
a306f2dd 325
bd5c0694 326 setproctitle("%s%s", authctxt->valid ? user : "unknown",
1853d1ef 327 use_privsep ? " [net]" : "");
6172e290 328
a306f2dd 329#ifdef USE_PAM
7fceb20d 330 if (options.use_pam)
529d73ab 331 PRIVSEP(start_pam(authctxt));
a306f2dd 332#endif
333
334 /*
335 * If we are not running as root, the user must have the same uid as
94ec8c6b 336 * the server. (Unless you are running Windows)
a306f2dd 337 */
94ec8c6b 338#ifndef HAVE_CYGWIN
5f1f36b5 339 if (!use_privsep && getuid() != 0 && authctxt->pw &&
340 authctxt->pw->pw_uid != getuid())
a306f2dd 341 packet_disconnect("Cannot change user when server not running as root.");
3c62e7eb 342#endif
a306f2dd 343
59c97189 344 /*
b4b5d644 345 * Loop until the user has been authenticated or the connection is
346 * closed, do_authloop() returns only if authentication is successful
347 */
59c97189 348 do_authloop(authctxt);
a306f2dd 349
350 /* The user has been authenticated and accepted. */
94ec8c6b 351 packet_start(SSH_SMSG_SUCCESS);
352 packet_send();
353 packet_write_wait();
a306f2dd 354}
This page took 0.214993 seconds and 5 git commands to generate.