]> andersk Git - gssapi-openssh.git/blame - openssh/auth2.c
http://www.psc.edu/networking/projects/hpn-ssh/openssh-5.2p1-hpn13v6.diff.gz committe...
[gssapi-openssh.git] / openssh / auth2.c
CommitLineData
91d9cdd3 1/* $OpenBSD: auth2.c,v 1.120 2008/11/04 08:22:12 djm Exp $ */
3c0ef626 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "includes.h"
3c0ef626 27
9108f8d9 28#include <sys/types.h>
22616013 29#include <sys/stat.h>
30#include <sys/uio.h>
9108f8d9 31
22616013 32#include <fcntl.h>
9108f8d9 33#include <pwd.h>
34#include <stdarg.h>
35#include <string.h>
22616013 36#include <unistd.h>
9108f8d9 37
3c0ef626 38#include "xmalloc.h"
22616013 39#include "atomicio.h"
9108f8d9 40#include "ssh2.h"
3c0ef626 41#include "packet.h"
3c0ef626 42#include "log.h"
9108f8d9 43#include "buffer.h"
3c0ef626 44#include "servconf.h"
45#include "compat.h"
9108f8d9 46#include "key.h"
47#include "hostfile.h"
3c0ef626 48#include "auth.h"
3c0ef626 49#include "dispatch.h"
3c0ef626 50#include "pathnames.h"
996d5e62 51#include "buffer.h"
76d45d2f 52#include "canohost.h"
3c0ef626 53
0fff78ff 54#ifdef GSSAPI
55#include "ssh-gss.h"
56#endif
9108f8d9 57#include "monitor_wrap.h"
0fff78ff 58
3c0ef626 59/* import */
60extern ServerOptions options;
61extern u_char *session_id2;
0fff78ff 62extern u_int session_id2_len;
996d5e62 63extern Buffer loginmsg;
3c0ef626 64
f5799ae1 65/* methods */
66
67extern Authmethod method_none;
68extern Authmethod method_pubkey;
69extern Authmethod method_passwd;
70extern Authmethod method_kbdint;
71extern Authmethod method_hostbased;
0fff78ff 72#ifdef GSSAPI
f97edba6 73extern Authmethod method_gsskeyex;
0fff78ff 74extern Authmethod method_gssapi;
75#endif
91d9cdd3 76#ifdef JPAKE
77extern Authmethod method_jpake;
78#endif
f5799ae1 79
76d45d2f 80static int log_flag = 0;
81
82
f5799ae1 83Authmethod *authmethods[] = {
84 &method_none,
85 &method_pubkey,
0fff78ff 86#ifdef GSSAPI
f97edba6 87 &method_gsskeyex,
0fff78ff 88 &method_gssapi,
91d9cdd3 89#endif
90#ifdef JPAKE
91 &method_jpake,
0fff78ff 92#endif
f5799ae1 93 &method_passwd,
94 &method_kbdint,
95 &method_hostbased,
96 NULL
3c0ef626 97};
98
99/* protocol */
100
e9a17296 101static void input_service_request(int, u_int32_t, void *);
102static void input_userauth_request(int, u_int32_t, void *);
3c0ef626 103
104/* helper */
105static Authmethod *authmethod_lookup(const char *);
106static char *authmethods_get(void);
3c0ef626 107
22616013 108char *
109auth2_read_banner(void)
110{
111 struct stat st;
112 char *banner = NULL;
113 size_t len, n;
114 int fd;
115
116 if ((fd = open(options.banner, O_RDONLY)) == -1)
117 return (NULL);
118 if (fstat(fd, &st) == -1) {
119 close(fd);
120 return (NULL);
121 }
122 if (st.st_size > 1*1024*1024) {
123 close(fd);
124 return (NULL);
125 }
126
127 len = (size_t)st.st_size; /* truncate */
128 banner = xmalloc(len + 1);
129 n = atomicio(read, fd, banner, len);
130 close(fd);
131
132 if (n != len) {
133 xfree(banner);
134 return (NULL);
135 }
136 banner[n] = '\0';
137
138 return (banner);
139}
140
141void
142userauth_send_banner(const char *msg)
143{
144 if (datafellows & SSH_BUG_BANNER)
145 return;
146
147 packet_start(SSH2_MSG_USERAUTH_BANNER);
148 packet_put_cstring(msg);
149 packet_put_cstring(""); /* language, unused */
150 packet_send();
151 debug("%s: sent", __func__);
152}
153
154static void
155userauth_banner(void)
156{
157 char *banner = NULL;
158
159 if (options.banner == NULL ||
160 strcasecmp(options.banner, "none") == 0 ||
161 (datafellows & SSH_BUG_BANNER) != 0)
162 return;
163
164 if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
165 goto done;
166 userauth_send_banner(banner);
167
168done:
169 if (banner)
170 xfree(banner);
171}
172
3c0ef626 173/*
174 * loop until authctxt->success == TRUE
175 */
cdd66111 176void
177do_authentication2(Authctxt *authctxt)
3c0ef626 178{
e9a17296 179 dispatch_init(&dispatch_protocol_error);
3c0ef626 180 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
181 dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
3c0ef626 182}
183
9108f8d9 184/*ARGSUSED*/
3c0ef626 185static void
e9a17296 186input_service_request(int type, u_int32_t seq, void *ctxt)
3c0ef626 187{
188 Authctxt *authctxt = ctxt;
189 u_int len;
41b2f314 190 int acceptit = 0;
3c0ef626 191 char *service = packet_get_string(&len);
e9a17296 192 packet_check_eom();
3c0ef626 193
194 if (authctxt == NULL)
195 fatal("input_service_request: no authctxt");
196
197 if (strcmp(service, "ssh-userauth") == 0) {
198 if (!authctxt->success) {
41b2f314 199 acceptit = 1;
3c0ef626 200 /* now we can handle user-auth requests */
201 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
202 }
203 }
204 /* XXX all other service requests are denied */
205
41b2f314 206 if (acceptit) {
3c0ef626 207 packet_start(SSH2_MSG_SERVICE_ACCEPT);
208 packet_put_cstring(service);
209 packet_send();
210 packet_write_wait();
211 } else {
212 debug("bad service request %s", service);
213 packet_disconnect("bad service request %s", service);
214 }
215 xfree(service);
216}
217
9108f8d9 218/*ARGSUSED*/
3c0ef626 219static void
e9a17296 220input_userauth_request(int type, u_int32_t seq, void *ctxt)
3c0ef626 221{
222 Authctxt *authctxt = ctxt;
223 Authmethod *m = NULL;
224 char *user, *service, *method, *style = NULL;
225 int authenticated = 0;
226
227 if (authctxt == NULL)
228 fatal("input_userauth_request: no authctxt");
229
230 user = packet_get_string(NULL);
231 service = packet_get_string(NULL);
232 method = packet_get_string(NULL);
233 debug("userauth-request for user %s service %s method %s", user, service, method);
76d45d2f 234 if (!log_flag) {
235 logit("SSH: Server;Ltype: Authname;Remote: %s-%d;Name: %s",
236 get_remote_ipaddr(), get_remote_port(), user);
237 log_flag = 1;
238 }
3c0ef626 239 debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
240
241 if ((style = strchr(user, ':')) != NULL)
242 *style++ = 0;
243
244 if (authctxt->attempt++ == 0) {
245 /* setup auth context */
700318f3 246 authctxt->pw = PRIVSEP(getpwnamallow(user));
99be0775 247 authctxt->user = xstrdup(user);
700318f3 248 if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
3c0ef626 249 authctxt->valid = 1;
250 debug2("input_userauth_request: setting up authctxt for %s", user);
3c0ef626 251 } else {
c9f39d2c 252 logit("input_userauth_request: invalid user %s", user);
0fff78ff 253 authctxt->pw = fakepw();
996d5e62 254#ifdef SSH_AUDIT_EVENTS
255 PRIVSEP(audit_event(SSH_INVALID_USER));
3c0ef626 256#endif
257 }
2c06c99b 258#ifdef USE_PAM
259 if (options.use_pam)
260 PRIVSEP(start_pam(authctxt));
261#endif
c9f39d2c 262 setproctitle("%s%s", authctxt->valid ? user : "unknown",
700318f3 263 use_privsep ? " [net]" : "");
3c0ef626 264 authctxt->service = xstrdup(service);
265 authctxt->style = style ? xstrdup(style) : NULL;
700318f3 266 if (use_privsep)
267 mm_inform_authserv(service, style);
22616013 268 userauth_banner();
3c0ef626 269 } else if (strcmp(user, authctxt->user) != 0 ||
270 strcmp(service, authctxt->service) != 0) {
271 packet_disconnect("Change of username or service not allowed: "
272 "(%s,%s) -> (%s,%s)",
273 authctxt->user, authctxt->service, user, service);
274 }
275 /* reset state */
e9a17296 276 auth2_challenge_stop(authctxt);
91d9cdd3 277#ifdef JPAKE
278 auth2_jpake_stop(authctxt);
279#endif
0fff78ff 280
281#ifdef GSSAPI
91d9cdd3 282 /* XXX move to auth2_gssapi_stop() */
0fff78ff 283 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
284 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
285#endif
286
3c0ef626 287 authctxt->postponed = 0;
f97edba6 288 authctxt->server_caused_failure = 0;
3c0ef626 289
290 /* try to authenticate user */
291 m = authmethod_lookup(method);
22616013 292 if (m != NULL && authctxt->failures < options.max_authtries) {
3c0ef626 293 debug2("input_userauth_request: try method %s", method);
294 authenticated = m->userauth(authctxt);
295 }
296 userauth_finish(authctxt, authenticated, method);
297
298 xfree(service);
299 xfree(user);
300 xfree(method);
301}
302
303void
304userauth_finish(Authctxt *authctxt, int authenticated, char *method)
305{
306 char *methods;
307
308 if (!authctxt->valid && authenticated)
309 fatal("INTERNAL ERROR: authenticated invalid user %s",
310 authctxt->user);
311
312 /* Special handling for root */
6a9b3198 313 if (authenticated && authctxt->pw->pw_uid == 0 &&
996d5e62 314 !auth_root_allowed(method)) {
3c0ef626 315 authenticated = 0;
996d5e62 316#ifdef SSH_AUDIT_EVENTS
317 PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
318#endif
319 }
3c0ef626 320
321#ifdef USE_PAM
996d5e62 322 if (options.use_pam && authenticated) {
323 if (!PRIVSEP(do_pam_account())) {
324 /* if PAM returned a message, send it to the user */
325 if (buffer_len(&loginmsg) > 0) {
326 buffer_append(&loginmsg, "\0", 1);
327 userauth_send_banner(buffer_ptr(&loginmsg));
328 packet_write_wait();
329 }
330 fatal("Access denied for user %s by PAM account "
665a873d 331 "configuration", authctxt->user);
996d5e62 332 }
333 }
0fff78ff 334#endif
3c0ef626 335
41b2f314 336#ifdef _UNICOS
337 if (authenticated && cray_access_denied(authctxt->user)) {
338 authenticated = 0;
339 fatal("Access denied for user %s.",authctxt->user);
340 }
341#endif /* _UNICOS */
342
3c0ef626 343 /* Log before sending the reply */
344 auth_log(authctxt, authenticated, method, " ssh2");
345
346 if (authctxt->postponed)
347 return;
348
349 /* XXX todo: check if multiple auth methods are needed */
350 if (authenticated == 1) {
351 /* turn off userauth */
e9a17296 352 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
3c0ef626 353 packet_start(SSH2_MSG_USERAUTH_SUCCESS);
354 packet_send();
355 packet_write_wait();
356 /* now we can break out */
357 authctxt->success = 1;
358 } else {
22616013 359
360 /* Allow initial try of "none" auth without failure penalty */
f97edba6 361 if (!authctxt->server_caused_failure &&
362 (authctxt->attempt > 1 || strcmp(method, "none") != 0))
22616013 363 authctxt->failures++;
364 if (authctxt->failures >= options.max_authtries) {
996d5e62 365#ifdef SSH_AUDIT_EVENTS
366 PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
367#endif
3c0ef626 368 packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
996d5e62 369 }
3c0ef626 370 methods = authmethods_get();
371 packet_start(SSH2_MSG_USERAUTH_FAILURE);
372 packet_put_cstring(methods);
373 packet_put_char(0); /* XXX partial success, unused */
374 packet_send();
375 packet_write_wait();
376 xfree(methods);
377 }
378}
379
3c0ef626 380static char *
381authmethods_get(void)
382{
e9a17296 383 Buffer b;
3c0ef626 384 char *list;
f5799ae1 385 int i;
3c0ef626 386
e9a17296 387 buffer_init(&b);
f5799ae1 388 for (i = 0; authmethods[i] != NULL; i++) {
389 if (strcmp(authmethods[i]->name, "none") == 0)
3c0ef626 390 continue;
f5799ae1 391 if (authmethods[i]->enabled != NULL &&
392 *(authmethods[i]->enabled) != 0) {
e9a17296 393 if (buffer_len(&b) > 0)
394 buffer_append(&b, ",", 1);
f5799ae1 395 buffer_append(&b, authmethods[i]->name,
396 strlen(authmethods[i]->name));
3c0ef626 397 }
398 }
e9a17296 399 buffer_append(&b, "\0", 1);
400 list = xstrdup(buffer_ptr(&b));
401 buffer_free(&b);
3c0ef626 402 return list;
403}
404
405static Authmethod *
406authmethod_lookup(const char *name)
407{
f5799ae1 408 int i;
409
3c0ef626 410 if (name != NULL)
f5799ae1 411 for (i = 0; authmethods[i] != NULL; i++)
412 if (authmethods[i]->enabled != NULL &&
413 *(authmethods[i]->enabled) != 0 &&
414 strcmp(name, authmethods[i]->name) == 0)
415 return authmethods[i];
416 debug2("Unrecognized authentication method name: %s",
417 name ? name : "NULL");
3c0ef626 418 return NULL;
419}
22616013 420
This page took 0.118774 seconds and 5 git commands to generate.