]> andersk Git - openssh.git/blob - auth2.c
- (bal) Refixed auth2.c. It was never fully commited while spliting out
[openssh.git] / auth2.c
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"
26 RCSID("$OpenBSD: auth2.c,v 1.93 2002/05/31 11:35:15 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 /* import */
40 extern ServerOptions options;
41 extern u_char *session_id2;
42 extern int session_id2_len;
43
44 Authctxt *x_authctxt = NULL;
45
46 /* methods */
47
48 extern Authmethod method_none;
49 extern Authmethod method_pubkey;
50 extern Authmethod method_passwd;
51 extern Authmethod method_kbdint;
52 extern Authmethod method_hostbased;
53
54 Authmethod *authmethods[] = {
55         &method_none,
56         &method_pubkey,
57         &method_passwd,
58         &method_kbdint,
59         &method_hostbased,
60         NULL
61 };
62
63 /* protocol */
64
65 static void input_service_request(int, u_int32_t, void *);
66 static void input_userauth_request(int, u_int32_t, void *);
67
68 /* helper */
69 static Authmethod *authmethod_lookup(const char *);
70 static char *authmethods_get(void);
71 int user_key_allowed(struct passwd *, Key *);
72 int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
73
74 /*
75  * loop until authctxt->success == TRUE
76  */
77
78 Authctxt *
79 do_authentication2(void)
80 {
81         Authctxt *authctxt = authctxt_new();
82
83         x_authctxt = authctxt;          /*XXX*/
84
85         /* challenge-response is implemented via keyboard interactive */
86         if (options.challenge_response_authentication)
87                 options.kbd_interactive_authentication = 1;
88         if (options.pam_authentication_via_kbd_int)
89                 options.kbd_interactive_authentication = 1;
90         if (use_privsep)
91                 options.pam_authentication_via_kbd_int = 0;
92
93         dispatch_init(&dispatch_protocol_error);
94         dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
95         dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
96
97         return (authctxt);
98 }
99
100 static void
101 input_service_request(int type, u_int32_t seq, void *ctxt)
102 {
103         Authctxt *authctxt = ctxt;
104         u_int len;
105         int accept = 0;
106         char *service = packet_get_string(&len);
107         packet_check_eom();
108
109         if (authctxt == NULL)
110                 fatal("input_service_request: no authctxt");
111
112         if (strcmp(service, "ssh-userauth") == 0) {
113                 if (!authctxt->success) {
114                         accept = 1;
115                         /* now we can handle user-auth requests */
116                         dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
117                 }
118         }
119         /* XXX all other service requests are denied */
120
121         if (accept) {
122                 packet_start(SSH2_MSG_SERVICE_ACCEPT);
123                 packet_put_cstring(service);
124                 packet_send();
125                 packet_write_wait();
126         } else {
127                 debug("bad service request %s", service);
128                 packet_disconnect("bad service request %s", service);
129         }
130         xfree(service);
131 }
132
133 static void
134 input_userauth_request(int type, u_int32_t seq, void *ctxt)
135 {
136         Authctxt *authctxt = ctxt;
137         Authmethod *m = NULL;
138         char *user, *service, *method, *style = NULL;
139         int authenticated = 0;
140
141         if (authctxt == NULL)
142                 fatal("input_userauth_request: no authctxt");
143
144         user = packet_get_string(NULL);
145         service = packet_get_string(NULL);
146         method = packet_get_string(NULL);
147         debug("userauth-request for user %s service %s method %s", user, service, method);
148         debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
149
150         if ((style = strchr(user, ':')) != NULL)
151                 *style++ = 0;
152
153         if (authctxt->attempt++ == 0) {
154                 /* setup auth context */
155                 authctxt->pw = PRIVSEP(getpwnamallow(user));
156                 if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
157                         authctxt->valid = 1;
158                         debug2("input_userauth_request: setting up authctxt for %s", user);
159 #ifdef USE_PAM
160                         PRIVSEP(start_pam(authctxt->pw->pw_name));
161 #endif
162                 } else {
163                         log("input_userauth_request: illegal user %s", user);
164 #ifdef USE_PAM
165                         PRIVSEP(start_pam("NOUSER"));
166 #endif
167                 }
168                 setproctitle("%s%s", authctxt->pw ? user : "unknown",
169                     use_privsep ? " [net]" : "");
170                 authctxt->user = xstrdup(user);
171                 authctxt->service = xstrdup(service);
172                 authctxt->style = style ? xstrdup(style) : NULL;
173                 if (use_privsep)
174                         mm_inform_authserv(service, style);
175         } else if (strcmp(user, authctxt->user) != 0 ||
176             strcmp(service, authctxt->service) != 0) {
177                 packet_disconnect("Change of username or service not allowed: "
178                     "(%s,%s) -> (%s,%s)",
179                     authctxt->user, authctxt->service, user, service);
180         }
181         /* reset state */
182         auth2_challenge_stop(authctxt);
183         authctxt->postponed = 0;
184
185         /* try to authenticate user */
186         m = authmethod_lookup(method);
187         if (m != NULL) {
188                 debug2("input_userauth_request: try method %s", method);
189                 authenticated = m->userauth(authctxt);
190         }
191         userauth_finish(authctxt, authenticated, method);
192
193         xfree(service);
194         xfree(user);
195         xfree(method);
196 }
197
198 void
199 userauth_finish(Authctxt *authctxt, int authenticated, char *method)
200 {
201         char *methods;
202
203         if (!authctxt->valid && authenticated)
204                 fatal("INTERNAL ERROR: authenticated invalid user %s",
205                     authctxt->user);
206
207         /* Special handling for root */
208         if (authenticated && authctxt->pw->pw_uid == 0 &&
209             !auth_root_allowed(method))
210                 authenticated = 0;
211
212 #ifdef USE_PAM
213         if (!use_privsep && authenticated && authctxt->user && 
214             !do_pam_account(authctxt->user, NULL))
215                 authenticated = 0;
216 #endif /* USE_PAM */
217
218         /* Log before sending the reply */
219         auth_log(authctxt, authenticated, method, " ssh2");
220
221         if (authctxt->postponed)
222                 return;
223
224         /* XXX todo: check if multiple auth methods are needed */
225         if (authenticated == 1) {
226                 /* turn off userauth */
227                 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
228                 packet_start(SSH2_MSG_USERAUTH_SUCCESS);
229                 packet_send();
230                 packet_write_wait();
231                 /* now we can break out */
232                 authctxt->success = 1;
233         } else {
234                 if (authctxt->failures++ > AUTH_FAIL_MAX) {
235 #ifdef WITH_AIXAUTHENTICATE
236                         loginfailed(authctxt->user,
237                             get_canonical_hostname(options.verify_reverse_mapping),
238                             "ssh");
239 #endif /* WITH_AIXAUTHENTICATE */
240                         packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
241                 }
242                 methods = authmethods_get();
243                 packet_start(SSH2_MSG_USERAUTH_FAILURE);
244                 packet_put_cstring(methods);
245                 packet_put_char(0);     /* XXX partial success, unused */
246                 packet_send();
247                 packet_write_wait();
248                 xfree(methods);
249         }
250 }
251
252 /* get current user */
253
254 struct passwd*
255 auth_get_user(void)
256 {
257         return (x_authctxt != NULL && x_authctxt->valid) ? x_authctxt->pw : NULL;
258 }
259
260 #define DELIM   ","
261
262 static char *
263 authmethods_get(void)
264 {
265         Buffer b;
266         char *list;
267         int i;
268
269         buffer_init(&b);
270         for (i = 0; authmethods[i] != NULL; i++) {
271                 if (strcmp(authmethods[i]->name, "none") == 0)
272                         continue;
273                 if (authmethods[i]->enabled != NULL &&
274                     *(authmethods[i]->enabled) != 0) {
275                         if (buffer_len(&b) > 0)
276                                 buffer_append(&b, ",", 1);
277                         buffer_append(&b, authmethods[i]->name,
278                             strlen(authmethods[i]->name));
279                 }
280         }
281         buffer_append(&b, "\0", 1);
282         list = xstrdup(buffer_ptr(&b));
283         buffer_free(&b);
284         return list;
285 }
286
287 static Authmethod *
288 authmethod_lookup(const char *name)
289 {
290         int i;
291
292         if (name != NULL)
293                 for (i = 0; authmethods[i] != NULL; i++)
294                         if (authmethods[i]->enabled != NULL &&
295                             *(authmethods[i]->enabled) != 0 &&
296                             strcmp(name, authmethods[i]->name) == 0)
297                                 return authmethods[i];
298         debug2("Unrecognized authentication method name: %s",
299             name ? name : "NULL");
300         return NULL;
301 }
This page took 0.073942 seconds and 5 git commands to generate.