]> andersk Git - openssh.git/blob - auth2.c
- Merge big update to OpenSSH-2.0 from OpenBSD CVS
[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  * 3. All advertising materials mentioning features or use of this software
13  *    must display the following acknowledgement:
14  *      This product includes software developed by Markus Friedl.
15  * 4. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 #include "includes.h"
30 RCSID("$OpenBSD: auth2.c,v 1.3 2000/04/27 15:23:02 markus Exp $");
31
32 #include <openssl/dsa.h>
33 #include <openssl/rsa.h>
34 #include <openssl/evp.h>
35
36 #include "xmalloc.h"
37 #include "rsa.h"
38 #include "ssh.h"
39 #include "pty.h"
40 #include "packet.h"
41 #include "buffer.h"
42 #include "cipher.h"
43 #include "servconf.h"
44 #include "compat.h"
45 #include "channels.h"
46 #include "bufaux.h"
47 #include "ssh2.h"
48 #include "auth.h"
49 #include "session.h"
50 #include "dispatch.h"
51 #include "auth.h"
52 #include "key.h"
53 #include "kex.h"
54
55 #include "dsa.h"
56 #include "uidswap.h"
57
58 /* import */
59 extern ServerOptions options;
60 extern unsigned char *session_id2;
61 extern int session_id2_len;
62
63 /* protocol */
64
65 void    input_service_request(int type, int plen);
66 void    input_userauth_request(int type, int plen);
67 void    protocol_error(int type, int plen);
68
69 /* auth */
70 int     ssh2_auth_none(struct passwd *pw);
71 int     ssh2_auth_password(struct passwd *pw);
72 int     ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen);
73
74 /* helper */
75 struct passwd*   auth_set_user(char *u, char *s);
76 int     user_dsa_key_allowed(struct passwd *pw, Key *key);
77
78 typedef struct Authctxt Authctxt;
79 struct Authctxt {
80         char *user;
81         char *service;
82         struct passwd pw;
83         int valid;
84 };
85 static Authctxt *authctxt = NULL;
86 static int userauth_success = 0;
87
88 /*
89  * loop until userauth_success == TRUE
90  */
91
92 void
93 do_authentication2()
94 {
95         dispatch_init(&protocol_error);
96         dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
97         dispatch_run(DISPATCH_BLOCK, &userauth_success);
98         do_authenticated2();
99 }
100
101 void
102 protocol_error(int type, int plen)
103 {
104         log("auth: protocol error: type %d plen %d", type, plen);
105         packet_start(SSH2_MSG_UNIMPLEMENTED);
106         packet_put_int(0);
107         packet_send();
108         packet_write_wait();
109 }
110
111 void
112 input_service_request(int type, int plen)
113 {
114         unsigned int len;
115         int accept = 0;
116         char *service = packet_get_string(&len);
117         packet_done();
118
119         if (strcmp(service, "ssh-userauth") == 0) {
120                 if (!userauth_success) {
121                         accept = 1;
122                         /* now we can handle user-auth requests */
123                         dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
124                 }
125         }
126         /* XXX all other service requests are denied */
127
128         if (accept) {
129                 packet_start(SSH2_MSG_SERVICE_ACCEPT);
130                 packet_put_cstring(service);
131                 packet_send();
132                 packet_write_wait();
133         } else {
134                 debug("bad service request %s", service);
135                 packet_disconnect("bad service request %s", service);
136         }
137         xfree(service);
138 }
139
140 void
141 input_userauth_request(int type, int plen)
142 {
143         static void (*authlog) (const char *fmt,...) = verbose;
144         static int attempt = 0;
145         unsigned int len, rlen;
146         int authenticated = 0;
147         char *raw, *user, *service, *method, *authmsg = NULL;
148         struct passwd *pw;
149
150         if (++attempt == AUTH_FAIL_MAX)
151                 packet_disconnect("too many failed userauth_requests");
152
153         raw = packet_get_raw(&rlen);
154         if (plen != rlen)
155                 fatal("plen != rlen");
156         user = packet_get_string(&len);
157         service = packet_get_string(&len);
158         method = packet_get_string(&len);
159         debug("userauth-request for user %s service %s method %s", user, service, method);
160
161         /* XXX we only allow the ssh-connection service */
162         pw = auth_set_user(user, service);
163         if (pw && strcmp(service, "ssh-connection")==0) {
164                 if (strcmp(method, "none") == 0) {
165                         authenticated = ssh2_auth_none(pw);
166                 } else if (strcmp(method, "password") == 0) {
167                         authenticated = ssh2_auth_password(pw);
168                 } else if (strcmp(method, "publickey") == 0) {
169                         authenticated = ssh2_auth_pubkey(pw, raw, rlen);
170                 }
171         }
172         if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
173                 authenticated = 0;
174                 log("ROOT LOGIN REFUSED FROM %.200s",
175                     get_canonical_hostname());
176         }
177
178 #ifdef USE_PAM
179                 if (authenticated && !do_pam_account(pw->pw_name, NULL))
180                         authenticated = 0;
181 #endif /* USE_PAM */
182
183         /* XXX todo: check if multiple auth methods are needed */
184         if (authenticated == 1) {
185                 authmsg = "Accepted";
186                 /* turn off userauth */
187                 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &protocol_error);
188                 packet_start(SSH2_MSG_USERAUTH_SUCCESS);
189                 packet_send();
190                 packet_write_wait();
191                 /* now we can break out */
192                 userauth_success = 1;
193         } else if (authenticated == 0) {
194                 authmsg = "Failed";
195                 packet_start(SSH2_MSG_USERAUTH_FAILURE);
196                 packet_put_cstring("publickey,password");       /* XXX dynamic */
197                 packet_put_char(0);                             /* XXX partial success, unused */
198                 packet_send();
199                 packet_write_wait();
200         } else {
201                 authmsg = "Postponed";
202         }
203         /* Raise logging level */
204         if (authenticated == 1||
205             attempt == AUTH_FAIL_LOG ||
206             strcmp(method, "password") == 0)
207                 authlog = log;
208
209         authlog("%s %s for %.200s from %.200s port %d ssh2",
210                 authmsg,
211                 method,
212                 pw && pw->pw_uid == 0 ? "ROOT" : user,
213                 get_remote_ipaddr(),
214                 get_remote_port());
215
216         xfree(service);
217         xfree(user);
218         xfree(method);
219 }
220
221 int
222 ssh2_auth_none(struct passwd *pw)
223 {
224         packet_done();
225 #ifdef USE_PAM
226         return auth_pam_password(pw, "");
227 #else /* USE_PAM */
228         return auth_password(pw, "");
229 #endif /* USE_PAM */
230 }
231 int
232 ssh2_auth_password(struct passwd *pw)
233 {
234         char *password;
235         int authenticated = 0;
236         int change;
237         unsigned int len;
238         change = packet_get_char();
239         if (change)
240                 log("password change not supported");
241         password = packet_get_string(&len);
242         packet_done();
243         if (options.password_authentication &&
244 #ifdef USE_PAM
245             auth_pam_password(pw, password) == 1)
246 #else /* USE_PAM */
247             auth_password(pw, password) == 1)
248 #endif /* USE_PAM */
249                 authenticated = 1;
250         memset(password, 0, len);
251         xfree(password);
252         return authenticated;
253 }
254 int
255 ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen)
256 {
257         Buffer b;
258         Key *key;
259         char *pkalg, *pkblob, *sig;
260         unsigned int alen, blen, slen;
261         int have_sig;
262         int authenticated = 0;
263
264         if (options.rsa_authentication == 0) {
265                 debug("pubkey auth disabled");
266                 return 0;
267         }
268         have_sig = packet_get_char();
269         pkalg = packet_get_string(&alen);
270         if (strcmp(pkalg, KEX_DSS) != 0) {
271                 xfree(pkalg);
272                 log("bad pkalg %s", pkalg);     /*XXX*/
273                 return 0;
274         }
275         pkblob = packet_get_string(&blen);
276         key = dsa_key_from_blob(pkblob, blen);
277         if (key != NULL) {
278                 if (have_sig) {
279                         sig = packet_get_string(&slen);
280                         packet_done();
281                         buffer_init(&b);
282                         buffer_append(&b, session_id2, session_id2_len);
283                         buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
284                         if (slen + 4 > rlen)
285                                 fatal("bad rlen/slen");
286                         buffer_append(&b, raw, rlen - slen - 4);
287 #ifdef DEBUG_DSS
288                         buffer_dump(&b);
289 #endif
290                         /* test for correct signature */
291                         if (user_dsa_key_allowed(pw, key) &&
292                             dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
293                                 authenticated = 1;
294                         buffer_clear(&b);
295                         xfree(sig);
296                 } else {
297                         packet_done();
298                         debug("test key...");
299                         /* test whether pkalg/pkblob are acceptable */
300                         /* XXX fake reply and always send PK_OK ? */
301                         if (user_dsa_key_allowed(pw, key)) {
302                                 packet_start(SSH2_MSG_USERAUTH_PK_OK);
303                                 packet_put_string(pkalg, alen);
304                                 packet_put_string(pkblob, blen);
305                                 packet_send();
306                                 packet_write_wait();
307                                 authenticated = -1;
308                         }
309                 }
310                 key_free(key);
311         }
312         xfree(pkalg);
313         xfree(pkblob);
314         return authenticated;
315 }
316
317 /* set and get current user */
318
319 struct passwd*
320 auth_get_user(void)
321 {
322         return (authctxt != NULL && authctxt->valid) ? &authctxt->pw : NULL;
323 }
324
325 struct passwd*
326 auth_set_user(char *u, char *s)
327 {
328         struct passwd *pw, *copy;
329
330         if (authctxt == NULL) {
331                 authctxt = xmalloc(sizeof(*authctxt));
332                 authctxt->valid = 0;
333                 authctxt->user = xstrdup(u);
334                 authctxt->service = xstrdup(s);
335                 setproctitle("%s", u);
336                 pw = getpwnam(u);
337                 if (!pw || !allowed_user(pw)) {
338                         log("auth_set_user: illegal user %s", u);
339                         return NULL;
340                 }
341 #ifdef USE_PAM
342                 start_pam(pw);
343 #endif
344                 copy = &authctxt->pw;
345                 memset(copy, 0, sizeof(*copy));
346                 copy->pw_name = xstrdup(pw->pw_name);
347                 copy->pw_passwd = xstrdup(pw->pw_passwd);
348                 copy->pw_uid = pw->pw_uid;
349                 copy->pw_gid = pw->pw_gid;
350                 copy->pw_dir = xstrdup(pw->pw_dir);
351                 copy->pw_shell = xstrdup(pw->pw_shell);
352                 authctxt->valid = 1;
353         } else {
354                 if (strcmp(u, authctxt->user) != 0 ||
355                     strcmp(s, authctxt->service) != 0) {
356                         log("auth_set_user: missmatch: (%s,%s)!=(%s,%s)",
357                             u, s, authctxt->user, authctxt->service);
358                         return NULL;
359                 }
360         }
361         return auth_get_user();
362 }
363
364 /* return 1 if user allows given key */
365 int
366 user_dsa_key_allowed(struct passwd *pw, Key *key)
367 {
368         char line[8192], file[1024];
369         int found_key = 0;
370         unsigned int bits = -1;
371         FILE *f;
372         unsigned long linenum = 0;
373         struct stat st;
374         Key *found;
375
376         /* Temporarily use the user's uid. */
377         temporarily_use_uid(pw->pw_uid);
378
379         /* The authorized keys. */
380         snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
381             SSH_USER_PERMITTED_KEYS2);
382
383         /* Fail quietly if file does not exist */
384         if (stat(file, &st) < 0) {
385                 /* Restore the privileged uid. */
386                 restore_uid();
387                 return 0;
388         }
389         /* Open the file containing the authorized keys. */
390         f = fopen(file, "r");
391         if (!f) {
392                 /* Restore the privileged uid. */
393                 restore_uid();
394                 return 0;
395         }
396         if (options.strict_modes) {
397                 int fail = 0;
398                 char buf[1024];
399                 /* Check open file in order to avoid open/stat races */
400                 if (fstat(fileno(f), &st) < 0 ||
401                     (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
402                     (st.st_mode & 022) != 0) {
403                         snprintf(buf, sizeof buf, "DSA authentication refused for %.100s: "
404                             "bad ownership or modes for '%s'.", pw->pw_name, file);
405                         fail = 1;
406                 } else {
407                         /* Check path to SSH_USER_PERMITTED_KEYS */
408                         int i;
409                         static const char *check[] = {
410                                 "", SSH_USER_DIR, NULL
411                         };
412                         for (i = 0; check[i]; i++) {
413                                 snprintf(line, sizeof line, "%.500s/%.100s",
414                                     pw->pw_dir, check[i]);
415                                 if (stat(line, &st) < 0 ||
416                                     (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
417                                     (st.st_mode & 022) != 0) {
418                                         snprintf(buf, sizeof buf,
419                                             "DSA authentication refused for %.100s: "
420                                             "bad ownership or modes for '%s'.",
421                                             pw->pw_name, line);
422                                         fail = 1;
423                                         break;
424                                 }
425                         }
426                 }
427                 if (fail) {
428                         log(buf);
429                         fclose(f);
430                         restore_uid();
431                         return 0;
432                 }
433         }
434         found_key = 0;
435         found = key_new(KEY_DSA);
436
437         while (fgets(line, sizeof(line), f)) {
438                 char *cp;
439                 linenum++;
440                 /* Skip leading whitespace, empty and comment lines. */
441                 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
442                         ;
443                 if (!*cp || *cp == '\n' || *cp == '#')
444                         continue;
445                 bits = key_read(found, &cp);
446                 if (bits == 0)
447                         continue;
448                 if (key_equal(found, key)) {
449                         found_key = 1;
450                         debug("matching key found: file %s, line %ld",
451                             file, linenum);
452                         break;
453                 }
454         }
455         restore_uid();
456         fclose(f);
457         key_free(found);
458         return found_key;
459 }
This page took 0.071109 seconds and 5 git commands to generate.