source: trunk/third/openssh/auth2.c @ 19372

Revision 19372, 10.0 KB checked in by zacheiss, 21 years ago (diff)
Log username and originating hostname for failed login attempts.
Line 
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"
26RCSID("$OpenBSD: auth2.c,v 1.95 2002/08/22 21:33:58 markus Exp $");
27
28#include "ssh2.h"
29#include "xmalloc.h"
30#include "packet.h"
31#include "log.h"
32#include "servconf.h"
33#include "compat.h"
34#include "auth.h"
35#include "dispatch.h"
36#include "pathnames.h"
37#include "monitor_wrap.h"
38
39#include <al.h>
40extern char *session_username;
41extern int is_local_acct;
42
43#ifdef GSSAPI
44#include "ssh-gss.h"
45#endif
46
47/* import */
48extern ServerOptions options;
49extern u_char *session_id2;
50extern int session_id2_len;
51extern int debug_flag;
52
53#ifdef WITH_AIXAUTHENTICATE
54extern char *aixloginmsg;
55#endif
56
57Authctxt *x_authctxt = NULL;
58
59/* methods */
60
61extern Authmethod method_none;
62extern Authmethod method_pubkey;
63extern Authmethod method_passwd;
64extern Authmethod method_kbdint;
65extern Authmethod method_hostbased;
66extern Authmethod method_external;
67extern Authmethod method_gssapi;
68
69Authmethod *authmethods[] = {
70        &method_none,
71#ifdef GSSAPI
72        &method_external,
73        &method_gssapi,
74#endif
75        &method_pubkey,
76        &method_passwd,
77        &method_kbdint,
78        &method_hostbased,
79        NULL
80};
81
82/* protocol */
83
84static void input_service_request(int, u_int32_t, void *);
85static void input_userauth_request(int, u_int32_t, void *);
86
87/* helper */
88static Authmethod *authmethod_lookup(const char *);
89static char *authmethods_get(void);
90int user_key_allowed(struct passwd *, Key *);
91int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
92
93/*
94 * loop until authctxt->success == TRUE
95 */
96
97Authctxt *
98do_authentication2(void)
99{
100        Authctxt *authctxt = authctxt_new();
101
102        x_authctxt = authctxt;          /*XXX*/
103
104        /* challenge-response is implemented via keyboard interactive */
105        if (options.challenge_response_authentication)
106                options.kbd_interactive_authentication = 1;
107        if (options.pam_authentication_via_kbd_int)
108                options.kbd_interactive_authentication = 1;
109        if (use_privsep)
110                options.pam_authentication_via_kbd_int = 0;
111
112        dispatch_init(&dispatch_protocol_error);
113        dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
114        dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
115
116        return (authctxt);
117}
118
119static void
120input_service_request(int type, u_int32_t seq, void *ctxt)
121{
122        Authctxt *authctxt = ctxt;
123        u_int len;
124        int acceptit = 0;
125        char *service = packet_get_string(&len);
126        packet_check_eom();
127
128        if (authctxt == NULL)
129                fatal("input_service_request: no authctxt");
130
131        if (strcmp(service, "ssh-userauth") == 0) {
132                if (!authctxt->success) {
133                        acceptit = 1;
134                        /* now we can handle user-auth requests */
135                        dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
136                }
137        }
138        /* XXX all other service requests are denied */
139
140        if (acceptit) {
141                packet_start(SSH2_MSG_SERVICE_ACCEPT);
142                packet_put_cstring(service);
143                packet_send();
144                packet_write_wait();
145        } else {
146                debug("bad service request %s", service);
147                packet_disconnect("bad service request %s", service);
148        }
149        xfree(service);
150}
151
152static void
153input_userauth_request(int type, u_int32_t seq, void *ctxt)
154{
155        Authctxt *authctxt = ctxt;
156        Authmethod *m = NULL;
157        char *user, *service, *method, *style = NULL;
158        int authenticated = 0, status;
159        char *filetext, *errmem;
160        const char *err;
161
162        if (authctxt == NULL)
163                fatal("input_userauth_request: no authctxt");
164
165        user = packet_get_string(NULL);
166        service = packet_get_string(NULL);
167        method = packet_get_string(NULL);
168        debug("userauth-request for user %s service %s method %s", user, service, method);
169        debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
170
171        if ((style = strchr(user, ':')) != NULL)
172                *style++ = 0;
173
174        if (authctxt->attempt++ == 0) {
175                /* setup auth context */
176                struct passwd *pw = NULL;
177
178                status = al_login_allowed(user, 1, &is_local_acct, &filetext);
179                if (status != AL_SUCCESS)
180                  {
181                    char *buf;
182
183                    err = al_strerror(status, &errmem);
184                    if (filetext && *filetext)
185                      {
186                        buf = xmalloc(40 + strlen(err) + strlen(filetext));
187                        sprintf(buf, "You are not allowed to log in here: "
188                                "%s\n%s", err, filetext);
189                      }
190                    else
191                      {
192                        buf = xmalloc(40 + strlen(err));
193                        sprintf(buf, "You are not allowed to log in here: "
194                                "%s\n", err);
195                      }
196                    packet_start(SSH2_MSG_DISCONNECT);
197                    packet_put_int(SSH2_DISCONNECT_ILLEGAL_USER_NAME);
198                    packet_put_cstring(buf);
199                    packet_put_cstring("");
200                    packet_send();
201                    packet_write_wait();
202
203                    fatal("Login denied: attempted login as %s from %s: %s",
204                          user, get_canonical_hostname(1), err);
205                  }
206                if (!is_local_acct)
207                  {
208                    status = al_acct_create(user, NULL, getpid(), 0, 0,
209                                            NULL);
210                    if (status != AL_SUCCESS && debug_flag)
211                      {
212                        err = al_strerror(status, &errmem);
213                        debug("al_acct_create failed for user %s: %s", user,
214                              err);
215                        al_free_errmem(errmem);
216                      }
217                    session_username = xstrdup(user);
218                    atexit(session_cleanup);
219                  }             
220               
221                authctxt->pw = PRIVSEP(getpwnamallow(user));
222                if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
223                        authctxt->valid = 1;
224                        debug2("input_userauth_request: setting up authctxt for %s", user);
225#ifdef USE_PAM
226                        PRIVSEP(start_pam(authctxt->pw->pw_name));
227#endif
228                } else {
229                        log("input_userauth_request: illegal user %s", user);
230#ifdef USE_PAM
231                        PRIVSEP(start_pam("NOUSER"));
232#endif
233                }
234                setproctitle("%s%s", authctxt->pw ? user : "unknown",
235                    use_privsep ? " [net]" : "");
236                authctxt->user = xstrdup(user);
237                authctxt->service = xstrdup(service);
238                authctxt->style = style ? xstrdup(style) : NULL;
239                if (use_privsep)
240                        mm_inform_authserv(service, style);
241        } else if (strcmp(user, authctxt->user) != 0 ||
242            strcmp(service, authctxt->service) != 0) {
243                packet_disconnect("Change of username or service not allowed: "
244                    "(%s,%s) -> (%s,%s)",
245                    authctxt->user, authctxt->service, user, service);
246        }
247        /* reset state */
248        auth2_challenge_stop(authctxt);
249
250#ifdef GSSAPI
251        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
252        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
253#endif
254
255        authctxt->postponed = 0;
256
257        /* try to authenticate user */
258        m = authmethod_lookup(method);
259        if (m != NULL) {
260                debug2("input_userauth_request: try method %s", method);
261                authenticated = m->userauth(authctxt);
262        }
263        userauth_finish(authctxt, authenticated, method);
264
265        xfree(service);
266        xfree(user);
267        xfree(method);
268}
269
270void
271userauth_finish(Authctxt *authctxt, int authenticated, char *method)
272{
273        char *methods;
274
275        if (!authctxt->valid && authenticated)
276                fatal("INTERNAL ERROR: authenticated invalid user %s",
277                    authctxt->user);
278
279        /* Special handling for root */
280        if (!use_privsep &&
281            authenticated && authctxt->pw->pw_uid == 0 &&
282            !auth_root_allowed(method))
283                authenticated = 0;
284
285#ifdef USE_PAM
286        if (!use_privsep && authenticated && authctxt->user &&
287            !do_pam_account(authctxt->user, NULL))
288                authenticated = 0;
289#endif /* USE_PAM */
290
291#ifdef _UNICOS
292        if (authenticated && cray_access_denied(authctxt->user)) {
293                authenticated = 0;
294                fatal("Access denied for user %s.",authctxt->user);
295        }
296#endif /* _UNICOS */
297
298        /* Log before sending the reply */
299        auth_log(authctxt, authenticated, method, " ssh2");
300
301        if (authctxt->postponed)
302                return;
303
304        /* XXX todo: check if multiple auth methods are needed */
305        if (authenticated == 1) {
306                /* turn off userauth */
307                dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
308                packet_start(SSH2_MSG_USERAUTH_SUCCESS);
309                packet_send();
310                packet_write_wait();
311                /* now we can break out */
312                authctxt->success = 1;
313        } else {
314                if (authctxt->failures++ > AUTH_FAIL_MAX) {
315                        packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
316                }
317#ifdef _UNICOS
318                if (strcmp(method, "password") == 0)
319                        cray_login_failure(authctxt->user, IA_UDBERR);
320#endif /* _UNICOS */
321                methods = authmethods_get();
322                packet_start(SSH2_MSG_USERAUTH_FAILURE);
323                packet_put_cstring(methods);
324                packet_put_char(0);     /* XXX partial success, unused */
325                packet_send();
326                packet_write_wait();
327                xfree(methods);
328        }
329}
330
331/* get current user */
332
333struct passwd*
334auth_get_user(void)
335{
336        return (x_authctxt != NULL && x_authctxt->valid) ? x_authctxt->pw : NULL;
337}
338
339#define DELIM   ","
340
341static char *
342authmethods_get(void)
343{
344        Buffer b;
345        char *list;
346        int i;
347
348        buffer_init(&b);
349        for (i = 0; authmethods[i] != NULL; i++) {
350                if (strcmp(authmethods[i]->name, "none") == 0)
351                        continue;
352                if (authmethods[i]->enabled != NULL &&
353                    *(authmethods[i]->enabled) != 0) {
354                        if (buffer_len(&b) > 0)
355                                buffer_append(&b, ",", 1);
356                        buffer_append(&b, authmethods[i]->name,
357                            strlen(authmethods[i]->name));
358                }
359        }
360        buffer_append(&b, "\0", 1);
361        list = xstrdup(buffer_ptr(&b));
362        buffer_free(&b);
363        return list;
364}
365
366static Authmethod *
367authmethod_lookup(const char *name)
368{
369        int i;
370
371        if (name != NULL)
372                for (i = 0; authmethods[i] != NULL; i++)
373                        if (authmethods[i]->enabled != NULL &&
374                            *(authmethods[i]->enabled) != 0 &&
375                            strcmp(name, authmethods[i]->name) == 0)
376                                return authmethods[i];
377        debug2("Unrecognized authentication method name: %s",
378            name ? name : "NULL");
379        return NULL;
380}
Note: See TracBrowser for help on using the repository browser.