]> andersk Git - gssapi-openssh.git/blame - openssh/auth2.c
o Bugfix makefile mod to use new mdoc2man.awk script
[gssapi-openssh.git] / openssh / auth2.c
CommitLineData
3c0ef626 1/*
2 * Copyright (c) 2000 Markus Friedl. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
23 */
24
25#include "includes.h"
70791e56 26RCSID("$OpenBSD: auth2.c,v 1.102 2003/08/26 09:58:43 markus Exp $");
3c0ef626 27
28#include "ssh2.h"
29#include "xmalloc.h"
3c0ef626 30#include "packet.h"
3c0ef626 31#include "log.h"
32#include "servconf.h"
3c0ef626 33#include "auth.h"
3c0ef626 34#include "dispatch.h"
3c0ef626 35#include "pathnames.h"
2980ea68 36#include "monitor_wrap.h"
3c0ef626 37
5598e598 38#ifdef GSSAPI
39#include "ssh-gss.h"
40#endif
41
3c0ef626 42/* import */
43extern ServerOptions options;
44extern u_char *session_id2;
70791e56 45extern u_int session_id2_len;
3c0ef626 46
2980ea68 47Authctxt *x_authctxt = NULL;
3c0ef626 48
ff2d7a98 49/* methods */
50
51extern Authmethod method_none;
ff2d7a98 52extern Authmethod method_pubkey;
53extern Authmethod method_passwd;
54extern Authmethod method_kbdint;
55extern Authmethod method_hostbased;
88928908 56#ifdef GSSAPI
57extern Authmethod method_external;
58extern Authmethod method_gssapi;
59#endif
ff2d7a98 60
61Authmethod *authmethods[] = {
62 &method_none,
63#ifdef GSSAPI
64 &method_external,
65 &method_gssapi,
66#endif
67 &method_pubkey,
70791e56 68#ifdef GSSAPI
69 &method_gssapi,
70#endif
ff2d7a98 71 &method_passwd,
72 &method_kbdint,
73 &method_hostbased,
74 NULL
3c0ef626 75};
76
77/* protocol */
78
1e608e42 79static void input_service_request(int, u_int32_t, void *);
80static void input_userauth_request(int, u_int32_t, void *);
3c0ef626 81
82/* helper */
83static Authmethod *authmethod_lookup(const char *);
84static char *authmethods_get(void);
2980ea68 85int user_key_allowed(struct passwd *, Key *);
86int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
3c0ef626 87
3c0ef626 88/*
89 * loop until authctxt->success == TRUE
90 */
91
2980ea68 92Authctxt *
1e608e42 93do_authentication2(void)
3c0ef626 94{
95 Authctxt *authctxt = authctxt_new();
96
97 x_authctxt = authctxt; /*XXX*/
98
99 /* challenge-response is implemented via keyboard interactive */
100 if (options.challenge_response_authentication)
101 options.kbd_interactive_authentication = 1;
3c0ef626 102
1e608e42 103 dispatch_init(&dispatch_protocol_error);
3c0ef626 104 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
105 dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
2980ea68 106
107 return (authctxt);
3c0ef626 108}
109
110static void
1e608e42 111input_service_request(int type, u_int32_t seq, void *ctxt)
3c0ef626 112{
113 Authctxt *authctxt = ctxt;
114 u_int len;
e54b3d7c 115 int acceptit = 0;
3c0ef626 116 char *service = packet_get_string(&len);
1e608e42 117 packet_check_eom();
3c0ef626 118
119 if (authctxt == NULL)
120 fatal("input_service_request: no authctxt");
121
122 if (strcmp(service, "ssh-userauth") == 0) {
123 if (!authctxt->success) {
e54b3d7c 124 acceptit = 1;
3c0ef626 125 /* now we can handle user-auth requests */
126 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
127 }
128 }
129 /* XXX all other service requests are denied */
130
e54b3d7c 131 if (acceptit) {
3c0ef626 132 packet_start(SSH2_MSG_SERVICE_ACCEPT);
133 packet_put_cstring(service);
134 packet_send();
135 packet_write_wait();
136 } else {
137 debug("bad service request %s", service);
138 packet_disconnect("bad service request %s", service);
139 }
140 xfree(service);
141}
142
143static void
1e608e42 144input_userauth_request(int type, u_int32_t seq, void *ctxt)
3c0ef626 145{
146 Authctxt *authctxt = ctxt;
147 Authmethod *m = NULL;
148 char *user, *service, *method, *style = NULL;
149 int authenticated = 0;
150
151 if (authctxt == NULL)
152 fatal("input_userauth_request: no authctxt");
153
154 user = packet_get_string(NULL);
155 service = packet_get_string(NULL);
156 method = packet_get_string(NULL);
2980ea68 157
158#ifdef GSSAPI
ff2d7a98 159 if (strcmp(user, "") == 0) {
c2397a66 160 debug("received empty username for %s", method);
161 if (strcmp(method, "external-keyx") == 0) {
162 char *lname = NULL;
163 PRIVSEP(ssh_gssapi_localname(&lname));
164 if (lname && lname[0] != '\0') {
165 xfree(user);
166 user = lname;
167 debug("set username to %s from gssapi context", user);
168 } else if (authctxt->valid) {
169 debug("failed to set username from gssapi context");
170 }
ff2d7a98 171 }
172 }
173#endif
2980ea68 174
c2397a66 175 debug("userauth-request for user %s service %s method %s",
176 (user && user[0]) ? user : "<implicit>", service, method);
3c0ef626 177 debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
178
179 if ((style = strchr(user, ':')) != NULL)
180 *style++ = 0;
181
c2397a66 182 authctxt->attempt++;
ff2d7a98 183 if (!authctxt->user ||
184 strcmp(user, authctxt->user) != 0) {
3c0ef626 185 /* setup auth context */
ff2d7a98 186 if (authctxt->user) {
187 xfree(authctxt->user);
188 authctxt->user = NULL;
189 }
190 if (authctxt->service) {
191 xfree(authctxt->service);
192 authctxt->service = NULL;
193 }
194 if (authctxt->style) {
195 xfree(authctxt->style);
196 authctxt->style = NULL;
197 }
c2397a66 198#ifdef GSSAPI
199 /* We'll verify the username after we set it from the
200 GSSAPI context. */
201 if ((strcmp(user, "") == 0) &&
202 ((strcmp(method, "gssapi") == 0) ||
203 (strcmp(method, "external-keyx") == 0))) {
204 authctxt->pw = NULL;
205 authctxt->valid = 1;
206 } else {
207#endif
2980ea68 208 authctxt->pw = PRIVSEP(getpwnamallow(user));
209 if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
3c0ef626 210 authctxt->valid = 1;
211 debug2("input_userauth_request: setting up authctxt for %s", user);
212#ifdef USE_PAM
70791e56 213 if (options.use_pam)
214 PRIVSEP(start_pam(authctxt->pw->pw_name));
3c0ef626 215#endif
216 } else {
70791e56 217 logit("input_userauth_request: illegal user %s", user);
218 authctxt->pw = fakepw();
3c0ef626 219#ifdef USE_PAM
70791e56 220 if (options.use_pam)
221 PRIVSEP(start_pam(user));
3c0ef626 222#endif
223 }
c2397a66 224#ifdef GSSAPI
225 }
226#endif
2980ea68 227 setproctitle("%s%s", authctxt->pw ? user : "unknown",
228 use_privsep ? " [net]" : "");
3c0ef626 229 authctxt->user = xstrdup(user);
230 authctxt->service = xstrdup(service);
231 authctxt->style = style ? xstrdup(style) : NULL;
c2397a66 232 if (use_privsep && (authctxt->attempt == 1))
2980ea68 233 mm_inform_authserv(service, style);
88928908 234 } else if (strcmp(service, authctxt->service) != 0) {
235 packet_disconnect("Change of service not allowed: "
236 "(%s,%s) -> (%s,%s)",
237 authctxt->user, authctxt->service, user, service);
3c0ef626 238 }
239 /* reset state */
1e608e42 240 auth2_challenge_stop(authctxt);
5598e598 241
242#ifdef GSSAPI
1e608e42 243 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
244 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
5598e598 245#endif
246
3c0ef626 247 authctxt->postponed = 0;
3c0ef626 248
249 /* try to authenticate user */
250 m = authmethod_lookup(method);
251 if (m != NULL) {
252 debug2("input_userauth_request: try method %s", method);
253 authenticated = m->userauth(authctxt);
254 }
255 userauth_finish(authctxt, authenticated, method);
256
257 xfree(service);
258 xfree(user);
259 xfree(method);
260}
261
262void
263userauth_finish(Authctxt *authctxt, int authenticated, char *method)
264{
265 char *methods;
266
267 if (!authctxt->valid && authenticated)
268 fatal("INTERNAL ERROR: authenticated invalid user %s",
269 authctxt->user);
270
271 /* Special handling for root */
1c14df9e 272 if (authenticated && authctxt->pw->pw_uid == 0 &&
3c0ef626 273 !auth_root_allowed(method))
274 authenticated = 0;
275
276#ifdef USE_PAM
70791e56 277 if (options.use_pam && authenticated && !PRIVSEP(do_pam_account()))
3c0ef626 278 authenticated = 0;
70791e56 279#endif
3c0ef626 280
e54b3d7c 281#ifdef _UNICOS
282 if (authenticated && cray_access_denied(authctxt->user)) {
283 authenticated = 0;
284 fatal("Access denied for user %s.",authctxt->user);
285 }
286#endif /* _UNICOS */
287
3c0ef626 288 /* Log before sending the reply */
289 auth_log(authctxt, authenticated, method, " ssh2");
290
291 if (authctxt->postponed)
292 return;
293
294 /* XXX todo: check if multiple auth methods are needed */
295 if (authenticated == 1) {
296 /* turn off userauth */
1e608e42 297 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
3c0ef626 298 packet_start(SSH2_MSG_USERAUTH_SUCCESS);
299 packet_send();
300 packet_write_wait();
301 /* now we can break out */
302 authctxt->success = 1;
303 } else {
70791e56 304 if (authctxt->failures++ > AUTH_FAIL_MAX)
3c0ef626 305 packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
3c0ef626 306 methods = authmethods_get();
307 packet_start(SSH2_MSG_USERAUTH_FAILURE);
308 packet_put_cstring(methods);
309 packet_put_char(0); /* XXX partial success, unused */
310 packet_send();
311 packet_write_wait();
312 xfree(methods);
313 }
314}
315
3c0ef626 316/* get current user */
317
318struct passwd*
319auth_get_user(void)
320{
321 return (x_authctxt != NULL && x_authctxt->valid) ? x_authctxt->pw : NULL;
322}
323
324#define DELIM ","
325
326static char *
327authmethods_get(void)
328{
1e608e42 329 Buffer b;
3c0ef626 330 char *list;
ff2d7a98 331 int i;
3c0ef626 332
1e608e42 333 buffer_init(&b);
ff2d7a98 334 for (i = 0; authmethods[i] != NULL; i++) {
335 if (strcmp(authmethods[i]->name, "none") == 0)
3c0ef626 336 continue;
ff2d7a98 337 if (authmethods[i]->enabled != NULL &&
338 *(authmethods[i]->enabled) != 0) {
1e608e42 339 if (buffer_len(&b) > 0)
340 buffer_append(&b, ",", 1);
ff2d7a98 341 buffer_append(&b, authmethods[i]->name,
342 strlen(authmethods[i]->name));
3c0ef626 343 }
344 }
1e608e42 345 buffer_append(&b, "\0", 1);
346 list = xstrdup(buffer_ptr(&b));
347 buffer_free(&b);
3c0ef626 348 return list;
349}
350
351static Authmethod *
352authmethod_lookup(const char *name)
353{
ff2d7a98 354 int i;
355
3c0ef626 356 if (name != NULL)
ff2d7a98 357 for (i = 0; authmethods[i] != NULL; i++)
358 if (authmethods[i]->enabled != NULL &&
359 *(authmethods[i]->enabled) != 0 &&
360 strcmp(name, authmethods[i]->name) == 0)
361 return authmethods[i];
362 debug2("Unrecognized authentication method name: %s",
363 name ? name : "NULL");
3c0ef626 364 return NULL;
365}
This page took 0.297264 seconds and 5 git commands to generate.