summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Makefile.in4
-rw-r--r--auth.h9
-rw-r--r--auth2-hostbased.c182
-rw-r--r--auth2-kbdint.c69
-rw-r--r--auth2-none.c111
-rw-r--r--auth2-passwd.c65
-rw-r--r--auth2-pubkey.c283
-rw-r--r--auth2.c186
9 files changed, 726 insertions, 189 deletions
diff --git a/ChangeLog b/ChangeLog
index f43d19219..38ea644ce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -31,6 +31,10 @@
31 - markus@cvs.openbsd.org 2002/05/25 08:50:39 31 - markus@cvs.openbsd.org 2002/05/25 08:50:39
32 [sshconnect2.c] 32 [sshconnect2.c]
33 execlp->execl; from stevesk 33 execlp->execl; from stevesk
34 - markus@cvs.openbsd.org 2002/05/25 18:51:07
35 [auth.h auth2.c auth2-hostbased.c auth2-kbdint.c auth2-none.c
36 auth2-passwd.c auth2-pubkey.c Makefile.in]
37 split auth2.c into one file per method; ok provos@/deraadt@
34 38
3520020604 3920020604
36 - (stevesk) [channels.c] bug #164 patch from YOSHIFUJI Hideaki (changed 40 - (stevesk) [channels.c] bug #164 patch from YOSHIFUJI Hideaki (changed
@@ -715,4 +719,4 @@
715 - (stevesk) entropy.c: typo in debug message 719 - (stevesk) entropy.c: typo in debug message
716 - (djm) ssh-keygen -i needs seeded RNG; report from markus@ 720 - (djm) ssh-keygen -i needs seeded RNG; report from markus@
717 721
718$Id: ChangeLog,v 1.2152 2002/06/06 20:05:57 mouring Exp $ 722$Id: ChangeLog,v 1.2153 2002/06/06 20:27:55 mouring Exp $
diff --git a/Makefile.in b/Makefile.in
index ec235f827..4001d68a8 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,4 +1,4 @@
1# $Id: Makefile.in,v 1.209 2002/06/06 19:57:33 mouring Exp $ 1# $Id: Makefile.in,v 1.210 2002/06/06 20:27:55 mouring Exp $
2 2
3# uncomment if you run a non bourne compatable shell. Ie. csh 3# uncomment if you run a non bourne compatable shell. Ie. csh
4#SHELL = @SH@ 4#SHELL = @SH@
@@ -61,7 +61,7 @@ LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels
61 61
62SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o sshtty.o readconf.o clientloop.o 62SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o sshtty.o readconf.o clientloop.o
63 63
64SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-chall.o auth2-chall.o auth-rhosts.o auth-options.o auth-krb4.o auth-krb5.o auth-pam.o auth2-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o auth-sia.o sshpty.o sshlogin.o loginrec.o servconf.o serverloop.o md5crypt.o session.o groupaccess.o auth-skey.o auth-bsdauth.o monitor_mm.o monitor.o 64SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth2-hostbased.o auth2-kbdint.o auth2-none.o auth2-passwd.o auth2-pubkey.o auth-chall.o auth2-chall.o auth-rhosts.o auth-options.o auth-krb4.o auth-krb5.o auth-pam.o auth2-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o auth-sia.o sshpty.o sshlogin.o loginrec.o servconf.o serverloop.o md5crypt.o session.o groupaccess.o auth-skey.o auth-bsdauth.o monitor_mm.o monitor.o
65 65
66MANPAGES = scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out 66MANPAGES = scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out
67MANPAGES_IN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 67MANPAGES_IN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8
diff --git a/auth.h b/auth.h
index 2211c5b2a..59646ebe4 100644
--- a/auth.h
+++ b/auth.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth.h,v 1.37 2002/05/13 20:44:58 markus Exp $ */ 1/* $OpenBSD: auth.h,v 1.38 2002/05/25 18:51:07 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -100,6 +100,13 @@ BIGNUM *auth_rsa_generate_challenge(Key *);
100int auth_rsa_verify_response(Key *, BIGNUM *, u_char[]); 100int auth_rsa_verify_response(Key *, BIGNUM *, u_char[]);
101int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **); 101int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
102 102
103/* ssh2 methods */
104int userauth_none(Authctxt *);
105int userauth_passwd(Authctxt *);
106int userauth_pubkey(Authctxt *);
107int userauth_hostbased(Authctxt *);
108int userauth_kbdint(Authctxt *);
109
103int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *); 110int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
104int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); 111int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
105int user_key_allowed(struct passwd *, Key *); 112int user_key_allowed(struct passwd *, Key *);
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
new file mode 100644
index 000000000..2bde7bb79
--- /dev/null
+++ b/auth2-hostbased.c
@@ -0,0 +1,182 @@
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-hostbased.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
27
28#include "ssh2.h"
29#include "xmalloc.h"
30#include "packet.h"
31#include "buffer.h"
32#include "log.h"
33#include "servconf.h"
34#include "compat.h"
35#include "bufaux.h"
36#include "auth.h"
37#include "key.h"
38#include "canohost.h"
39#include "monitor_wrap.h"
40#include "pathnames.h"
41
42/* import */
43extern ServerOptions options;
44extern u_char *session_id2;
45extern int session_id2_len;
46
47static int
48userauth_hostbased(Authctxt *authctxt)
49{
50 Buffer b;
51 Key *key = NULL;
52 char *pkalg, *cuser, *chost, *service;
53 u_char *pkblob, *sig;
54 u_int alen, blen, slen;
55 int pktype;
56 int authenticated = 0;
57
58 if (!authctxt->valid) {
59 debug2("userauth_hostbased: disabled because of invalid user");
60 return 0;
61 }
62 pkalg = packet_get_string(&alen);
63 pkblob = packet_get_string(&blen);
64 chost = packet_get_string(NULL);
65 cuser = packet_get_string(NULL);
66 sig = packet_get_string(&slen);
67
68 debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
69 cuser, chost, pkalg, slen);
70#ifdef DEBUG_PK
71 debug("signature:");
72 buffer_init(&b);
73 buffer_append(&b, sig, slen);
74 buffer_dump(&b);
75 buffer_free(&b);
76#endif
77 pktype = key_type_from_name(pkalg);
78 if (pktype == KEY_UNSPEC) {
79 /* this is perfectly legal */
80 log("userauth_hostbased: unsupported "
81 "public key algorithm: %s", pkalg);
82 goto done;
83 }
84 key = key_from_blob(pkblob, blen);
85 if (key == NULL) {
86 error("userauth_hostbased: cannot decode key: %s", pkalg);
87 goto done;
88 }
89 if (key->type != pktype) {
90 error("userauth_hostbased: type mismatch for decoded key "
91 "(received %d, expected %d)", key->type, pktype);
92 goto done;
93 }
94 service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
95 authctxt->service;
96 buffer_init(&b);
97 buffer_put_string(&b, session_id2, session_id2_len);
98 /* reconstruct packet */
99 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
100 buffer_put_cstring(&b, authctxt->user);
101 buffer_put_cstring(&b, service);
102 buffer_put_cstring(&b, "hostbased");
103 buffer_put_string(&b, pkalg, alen);
104 buffer_put_string(&b, pkblob, blen);
105 buffer_put_cstring(&b, chost);
106 buffer_put_cstring(&b, cuser);
107#ifdef DEBUG_PK
108 buffer_dump(&b);
109#endif
110 /* test for allowed key and correct signature */
111 authenticated = 0;
112 if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
113 PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
114 buffer_len(&b))) == 1)
115 authenticated = 1;
116
117 buffer_clear(&b);
118done:
119 debug2("userauth_hostbased: authenticated %d", authenticated);
120 if (key != NULL)
121 key_free(key);
122 xfree(pkalg);
123 xfree(pkblob);
124 xfree(cuser);
125 xfree(chost);
126 xfree(sig);
127 return authenticated;
128}
129
130/* return 1 if given hostkey is allowed */
131int
132hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
133 Key *key)
134{
135 const char *resolvedname, *ipaddr, *lookup;
136 HostStatus host_status;
137 int len;
138
139 resolvedname = get_canonical_hostname(options.verify_reverse_mapping);
140 ipaddr = get_remote_ipaddr();
141
142 debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
143 chost, resolvedname, ipaddr);
144
145 if (options.hostbased_uses_name_from_packet_only) {
146 if (auth_rhosts2(pw, cuser, chost, chost) == 0)
147 return 0;
148 lookup = chost;
149 } else {
150 if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
151 debug2("stripping trailing dot from chost %s", chost);
152 chost[len - 1] = '\0';
153 }
154 if (strcasecmp(resolvedname, chost) != 0)
155 log("userauth_hostbased mismatch: "
156 "client sends %s, but we resolve %s to %s",
157 chost, ipaddr, resolvedname);
158 if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
159 return 0;
160 lookup = resolvedname;
161 }
162 debug2("userauth_hostbased: access allowed by auth_rhosts2");
163
164 host_status = check_key_in_hostfiles(pw, key, lookup,
165 _PATH_SSH_SYSTEM_HOSTFILE,
166 options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
167
168 /* backward compat if no key has been found. */
169 if (host_status == HOST_NEW)
170 host_status = check_key_in_hostfiles(pw, key, lookup,
171 _PATH_SSH_SYSTEM_HOSTFILE2,
172 options.ignore_user_known_hosts ? NULL :
173 _PATH_SSH_USER_HOSTFILE2);
174
175 return (host_status == HOST_OK);
176}
177
178Authmethod method_hostbased = {
179 "hostbased",
180 userauth_hostbased,
181 &options.hostbased_authentication
182};
diff --git a/auth2-kbdint.c b/auth2-kbdint.c
new file mode 100644
index 000000000..e60992881
--- /dev/null
+++ b/auth2-kbdint.c
@@ -0,0 +1,69 @@
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-kbdint.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
27
28#include "packet.h"
29#include "auth.h"
30#include "log.h"
31#include "servconf.h"
32#include "xmalloc.h"
33
34/* import */
35extern ServerOptions options;
36
37static int
38userauth_kbdint(Authctxt *authctxt)
39{
40 int authenticated = 0;
41 char *lang, *devs;
42
43 lang = packet_get_string(NULL);
44 devs = packet_get_string(NULL);
45 packet_check_eom();
46
47 debug("keyboard-interactive devs %s", devs);
48
49 if (options.challenge_response_authentication)
50 authenticated = auth2_challenge(authctxt, devs);
51
52#ifdef USE_PAM
53 if (authenticated == 0 && options.pam_authentication_via_kbd_int)
54 authenticated = auth2_pam(authctxt);
55#endif
56 xfree(devs);
57 xfree(lang);
58#ifdef HAVE_CYGWIN
59 if (check_nt_auth(0, authctxt->pw) == 0)
60 return(0);
61#endif
62 return authenticated;
63}
64
65Authmethod method_kbdint = {
66 "keyboard-interactive",
67 userauth_kbdint,
68 &options.kbd_interactive_authentication
69};
diff --git a/auth2-none.c b/auth2-none.c
new file mode 100644
index 000000000..30337fd6d
--- /dev/null
+++ b/auth2-none.c
@@ -0,0 +1,111 @@
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-none.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
27
28#include "auth.h"
29#include "xmalloc.h"
30#include "packet.h"
31#include "log.h"
32#include "servconf.h"
33#include "atomicio.h"
34#include "compat.h"
35#include "ssh2.h"
36#include "monitor_wrap.h"
37
38/* import */
39extern ServerOptions options;
40
41/* "none" is allowed only one time */
42static int none_enabled = 1;
43
44char *
45auth2_read_banner(void)
46{
47 struct stat st;
48 char *banner = NULL;
49 off_t len, n;
50 int fd;
51
52 if ((fd = open(options.banner, O_RDONLY)) == -1)
53 return (NULL);
54 if (fstat(fd, &st) == -1) {
55 close(fd);
56 return (NULL);
57 }
58 len = st.st_size;
59 banner = xmalloc(len + 1);
60 n = atomicio(read, fd, banner, len);
61 close(fd);
62
63 if (n != len) {
64 free(banner);
65 return (NULL);
66 }
67 banner[n] = '\0';
68
69 return (banner);
70}
71
72static void
73userauth_banner(void)
74{
75 char *banner = NULL;
76
77 if (options.banner == NULL || (datafellows & SSH_BUG_BANNER))
78 return;
79
80 if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
81 goto done;
82
83 packet_start(SSH2_MSG_USERAUTH_BANNER);
84 packet_put_cstring(banner);
85 packet_put_cstring(""); /* language, unused */
86 packet_send();
87 debug("userauth_banner: sent");
88done:
89 if (banner)
90 xfree(banner);
91 return;
92}
93
94static int
95userauth_none(Authctxt *authctxt)
96{
97 none_enabled = 0;
98 packet_check_eom();
99 userauth_banner();
100#ifdef HAVE_CYGWIN
101 if (check_nt_auth(1, authctxt->pw) == 0)
102 return(0);
103#endif
104 return (authctxt->valid ? PRIVSEP(auth_password(authctxt, "")) : 0);
105}
106
107Authmethod method_none = {
108 "none",
109 userauth_none,
110 &none_enabled
111};
diff --git a/auth2-passwd.c b/auth2-passwd.c
new file mode 100644
index 000000000..ffa279594
--- /dev/null
+++ b/auth2-passwd.c
@@ -0,0 +1,65 @@
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-passwd.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
27
28#include "xmalloc.h"
29#include "packet.h"
30#include "log.h"
31#include "auth.h"
32#include "monitor_wrap.h"
33#include "servconf.h"
34
35/* import */
36extern ServerOptions options;
37
38static int
39userauth_passwd(Authctxt *authctxt)
40{
41 char *password;
42 int authenticated = 0;
43 int change;
44 u_int len;
45 change = packet_get_char();
46 if (change)
47 log("password change not supported");
48 password = packet_get_string(&len);
49 packet_check_eom();
50 if (authctxt->valid &&
51#ifdef HAVE_CYGWIN
52 check_nt_auth(1, authctxt->pw) &&
53#endif
54 PRIVSEP(auth_password(authctxt, password)) == 1)
55 authenticated = 1;
56 memset(password, 0, len);
57 xfree(password);
58 return authenticated;
59}
60
61Authmethod method_passwd = {
62 "password",
63 userauth_passwd,
64 &options.password_authentication
65};
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
new file mode 100644
index 000000000..947bfed0b
--- /dev/null
+++ b/auth2-pubkey.c
@@ -0,0 +1,283 @@
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-pubkey.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
27
28#include "ssh2.h"
29#include "xmalloc.h"
30#include "packet.h"
31#include "buffer.h"
32#include "log.h"
33#include "servconf.h"
34#include "compat.h"
35#include "bufaux.h"
36#include "auth.h"
37#include "key.h"
38#include "pathnames.h"
39#include "uidswap.h"
40#include "auth-options.h"
41#include "canohost.h"
42#include "monitor_wrap.h"
43
44/* import */
45extern ServerOptions options;
46extern u_char *session_id2;
47extern int session_id2_len;
48
49static int
50userauth_pubkey(Authctxt *authctxt)
51{
52 Buffer b;
53 Key *key = NULL;
54 char *pkalg;
55 u_char *pkblob, *sig;
56 u_int alen, blen, slen;
57 int have_sig, pktype;
58 int authenticated = 0;
59
60 if (!authctxt->valid) {
61 debug2("userauth_pubkey: disabled because of invalid user");
62 return 0;
63 }
64 have_sig = packet_get_char();
65 if (datafellows & SSH_BUG_PKAUTH) {
66 debug2("userauth_pubkey: SSH_BUG_PKAUTH");
67 /* no explicit pkalg given */
68 pkblob = packet_get_string(&blen);
69 buffer_init(&b);
70 buffer_append(&b, pkblob, blen);
71 /* so we have to extract the pkalg from the pkblob */
72 pkalg = buffer_get_string(&b, &alen);
73 buffer_free(&b);
74 } else {
75 pkalg = packet_get_string(&alen);
76 pkblob = packet_get_string(&blen);
77 }
78 pktype = key_type_from_name(pkalg);
79 if (pktype == KEY_UNSPEC) {
80 /* this is perfectly legal */
81 log("userauth_pubkey: unsupported public key algorithm: %s",
82 pkalg);
83 goto done;
84 }
85 key = key_from_blob(pkblob, blen);
86 if (key == NULL) {
87 error("userauth_pubkey: cannot decode key: %s", pkalg);
88 goto done;
89 }
90 if (key->type != pktype) {
91 error("userauth_pubkey: type mismatch for decoded key "
92 "(received %d, expected %d)", key->type, pktype);
93 goto done;
94 }
95 if (have_sig) {
96 sig = packet_get_string(&slen);
97 packet_check_eom();
98 buffer_init(&b);
99 if (datafellows & SSH_OLD_SESSIONID) {
100 buffer_append(&b, session_id2, session_id2_len);
101 } else {
102 buffer_put_string(&b, session_id2, session_id2_len);
103 }
104 /* reconstruct packet */
105 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
106 buffer_put_cstring(&b, authctxt->user);
107 buffer_put_cstring(&b,
108 datafellows & SSH_BUG_PKSERVICE ?
109 "ssh-userauth" :
110 authctxt->service);
111 if (datafellows & SSH_BUG_PKAUTH) {
112 buffer_put_char(&b, have_sig);
113 } else {
114 buffer_put_cstring(&b, "publickey");
115 buffer_put_char(&b, have_sig);
116 buffer_put_cstring(&b, pkalg);
117 }
118 buffer_put_string(&b, pkblob, blen);
119#ifdef DEBUG_PK
120 buffer_dump(&b);
121#endif
122 /* test for correct signature */
123 authenticated = 0;
124 if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
125 PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
126 buffer_len(&b))) == 1)
127 authenticated = 1;
128 buffer_clear(&b);
129 xfree(sig);
130 } else {
131 debug("test whether pkalg/pkblob are acceptable");
132 packet_check_eom();
133
134 /* XXX fake reply and always send PK_OK ? */
135 /*
136 * XXX this allows testing whether a user is allowed
137 * to login: if you happen to have a valid pubkey this
138 * message is sent. the message is NEVER sent at all
139 * if a user is not allowed to login. is this an
140 * issue? -markus
141 */
142 if (PRIVSEP(user_key_allowed(authctxt->pw, key))) {
143 packet_start(SSH2_MSG_USERAUTH_PK_OK);
144 packet_put_string(pkalg, alen);
145 packet_put_string(pkblob, blen);
146 packet_send();
147 packet_write_wait();
148 authctxt->postponed = 1;
149 }
150 }
151 if (authenticated != 1)
152 auth_clear_options();
153done:
154 debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
155 if (key != NULL)
156 key_free(key);
157 xfree(pkalg);
158 xfree(pkblob);
159#ifdef HAVE_CYGWIN
160 if (check_nt_auth(0, authctxt->pw) == 0)
161 return(0);
162#endif
163 return authenticated;
164}
165
166/* return 1 if user allows given key */
167static int
168user_key_allowed2(struct passwd *pw, Key *key, char *file)
169{
170 char line[8192];
171 int found_key = 0;
172 FILE *f;
173 u_long linenum = 0;
174 struct stat st;
175 Key *found;
176 char *fp;
177
178 if (pw == NULL)
179 return 0;
180
181 /* Temporarily use the user's uid. */
182 temporarily_use_uid(pw);
183
184 debug("trying public key file %s", file);
185
186 /* Fail quietly if file does not exist */
187 if (stat(file, &st) < 0) {
188 /* Restore the privileged uid. */
189 restore_uid();
190 return 0;
191 }
192 /* Open the file containing the authorized keys. */
193 f = fopen(file, "r");
194 if (!f) {
195 /* Restore the privileged uid. */
196 restore_uid();
197 return 0;
198 }
199 if (options.strict_modes &&
200 secure_filename(f, file, pw, line, sizeof(line)) != 0) {
201 fclose(f);
202 log("Authentication refused: %s", line);
203 restore_uid();
204 return 0;
205 }
206
207 found_key = 0;
208 found = key_new(key->type);
209
210 while (fgets(line, sizeof(line), f)) {
211 char *cp, *options = NULL;
212 linenum++;
213 /* Skip leading whitespace, empty and comment lines. */
214 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
215 ;
216 if (!*cp || *cp == '\n' || *cp == '#')
217 continue;
218
219 if (key_read(found, &cp) != 1) {
220 /* no key? check if there are options for this key */
221 int quoted = 0;
222 debug2("user_key_allowed: check options: '%s'", cp);
223 options = cp;
224 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
225 if (*cp == '\\' && cp[1] == '"')
226 cp++; /* Skip both */
227 else if (*cp == '"')
228 quoted = !quoted;
229 }
230 /* Skip remaining whitespace. */
231 for (; *cp == ' ' || *cp == '\t'; cp++)
232 ;
233 if (key_read(found, &cp) != 1) {
234 debug2("user_key_allowed: advance: '%s'", cp);
235 /* still no key? advance to next line*/
236 continue;
237 }
238 }
239 if (key_equal(found, key) &&
240 auth_parse_options(pw, options, file, linenum) == 1) {
241 found_key = 1;
242 debug("matching key found: file %s, line %lu",
243 file, linenum);
244 fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
245 verbose("Found matching %s key: %s",
246 key_type(found), fp);
247 xfree(fp);
248 break;
249 }
250 }
251 restore_uid();
252 fclose(f);
253 key_free(found);
254 if (!found_key)
255 debug2("key not found");
256 return found_key;
257}
258
259/* check whether given key is in .ssh/authorized_keys* */
260int
261user_key_allowed(struct passwd *pw, Key *key)
262{
263 int success;
264 char *file;
265
266 file = authorized_keys_file(pw);
267 success = user_key_allowed2(pw, key, file);
268 xfree(file);
269 if (success)
270 return success;
271
272 /* try suffix "2" for backward compat, too */
273 file = authorized_keys_file2(pw);
274 success = user_key_allowed2(pw, key, file);
275 xfree(file);
276 return success;
277}
278
279Authmethod method_pubkey = {
280 "publickey",
281 userauth_pubkey,
282 &options.pubkey_authentication
283};
diff --git a/auth2.c b/auth2.c
index 6bcc56527..ffd703282 100644
--- a/auth2.c
+++ b/auth2.c
@@ -23,35 +23,18 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: auth2.c,v 1.91 2002/05/13 02:37:39 itojun Exp $"); 26RCSID("$OpenBSD: auth2.c,v 1.92 2002/05/25 18:51:07 markus Exp $");
27
28#include <openssl/evp.h>
29 27
30#include "ssh2.h" 28#include "ssh2.h"
31#include "xmalloc.h" 29#include "xmalloc.h"
32#include "rsa.h"
33#include "sshpty.h"
34#include "packet.h" 30#include "packet.h"
35#include "buffer.h"
36#include "log.h" 31#include "log.h"
37#include "servconf.h" 32#include "servconf.h"
38#include "compat.h" 33#include "compat.h"
39#include "channels.h"
40#include "bufaux.h"
41#include "auth.h" 34#include "auth.h"
42#include "session.h"
43#include "dispatch.h" 35#include "dispatch.h"
44#include "key.h"
45#include "cipher.h"
46#include "kex.h"
47#include "pathnames.h" 36#include "pathnames.h"
48#include "uidswap.h"
49#include "auth-options.h"
50#include "hostfile.h"
51#include "canohost.h"
52#include "match.h"
53#include "monitor_wrap.h" 37#include "monitor_wrap.h"
54#include "atomicio.h"
55 38
56/* import */ 39/* import */
57extern ServerOptions options; 40extern ServerOptions options;
@@ -80,12 +63,6 @@ int user_key_allowed(struct passwd *, Key *);
80int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); 63int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
81 64
82/* auth */ 65/* auth */
83static void userauth_banner(void);
84static int userauth_none(Authctxt *);
85static int userauth_passwd(Authctxt *);
86static int userauth_pubkey(Authctxt *);
87static int userauth_hostbased(Authctxt *);
88static int userauth_kbdint(Authctxt *);
89 66
90Authmethod authmethods[] = { 67Authmethod authmethods[] = {
91 {"none", 68 {"none",
@@ -651,164 +628,3 @@ authmethod_lookup(const char *name)
651 debug2("Unrecognized authentication method name: %s", name ? name : "NULL"); 628 debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
652 return NULL; 629 return NULL;
653} 630}
654
655/* return 1 if user allows given key */
656static int
657user_key_allowed2(struct passwd *pw, Key *key, char *file)
658{
659 char line[8192];
660 int found_key = 0;
661 FILE *f;
662 u_long linenum = 0;
663 struct stat st;
664 Key *found;
665 char *fp;
666
667 if (pw == NULL)
668 return 0;
669
670 /* Temporarily use the user's uid. */
671 temporarily_use_uid(pw);
672
673 debug("trying public key file %s", file);
674
675 /* Fail quietly if file does not exist */
676 if (stat(file, &st) < 0) {
677 /* Restore the privileged uid. */
678 restore_uid();
679 return 0;
680 }
681 /* Open the file containing the authorized keys. */
682 f = fopen(file, "r");
683 if (!f) {
684 /* Restore the privileged uid. */
685 restore_uid();
686 return 0;
687 }
688 if (options.strict_modes &&
689 secure_filename(f, file, pw, line, sizeof(line)) != 0) {
690 fclose(f);
691 log("Authentication refused: %s", line);
692 restore_uid();
693 return 0;
694 }
695
696 found_key = 0;
697 found = key_new(key->type);
698
699 while (fgets(line, sizeof(line), f)) {
700 char *cp, *options = NULL;
701 linenum++;
702 /* Skip leading whitespace, empty and comment lines. */
703 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
704 ;
705 if (!*cp || *cp == '\n' || *cp == '#')
706 continue;
707
708 if (key_read(found, &cp) != 1) {
709 /* no key? check if there are options for this key */
710 int quoted = 0;
711 debug2("user_key_allowed: check options: '%s'", cp);
712 options = cp;
713 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
714 if (*cp == '\\' && cp[1] == '"')
715 cp++; /* Skip both */
716 else if (*cp == '"')
717 quoted = !quoted;
718 }
719 /* Skip remaining whitespace. */
720 for (; *cp == ' ' || *cp == '\t'; cp++)
721 ;
722 if (key_read(found, &cp) != 1) {
723 debug2("user_key_allowed: advance: '%s'", cp);
724 /* still no key? advance to next line*/
725 continue;
726 }
727 }
728 if (key_equal(found, key) &&
729 auth_parse_options(pw, options, file, linenum) == 1) {
730 found_key = 1;
731 debug("matching key found: file %s, line %lu",
732 file, linenum);
733 fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
734 verbose("Found matching %s key: %s",
735 key_type(found), fp);
736 xfree(fp);
737 break;
738 }
739 }
740 restore_uid();
741 fclose(f);
742 key_free(found);
743 if (!found_key)
744 debug2("key not found");
745 return found_key;
746}
747
748/* check whether given key is in .ssh/authorized_keys* */
749int
750user_key_allowed(struct passwd *pw, Key *key)
751{
752 int success;
753 char *file;
754
755 file = authorized_keys_file(pw);
756 success = user_key_allowed2(pw, key, file);
757 xfree(file);
758 if (success)
759 return success;
760
761 /* try suffix "2" for backward compat, too */
762 file = authorized_keys_file2(pw);
763 success = user_key_allowed2(pw, key, file);
764 xfree(file);
765 return success;
766}
767
768/* return 1 if given hostkey is allowed */
769int
770hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
771 Key *key)
772{
773 const char *resolvedname, *ipaddr, *lookup;
774 HostStatus host_status;
775 int len;
776
777 resolvedname = get_canonical_hostname(options.verify_reverse_mapping);
778 ipaddr = get_remote_ipaddr();
779
780 debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
781 chost, resolvedname, ipaddr);
782
783 if (options.hostbased_uses_name_from_packet_only) {
784 if (auth_rhosts2(pw, cuser, chost, chost) == 0)
785 return 0;
786 lookup = chost;
787 } else {
788 if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
789 debug2("stripping trailing dot from chost %s", chost);
790 chost[len - 1] = '\0';
791 }
792 if (strcasecmp(resolvedname, chost) != 0)
793 log("userauth_hostbased mismatch: "
794 "client sends %s, but we resolve %s to %s",
795 chost, ipaddr, resolvedname);
796 if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
797 return 0;
798 lookup = resolvedname;
799 }
800 debug2("userauth_hostbased: access allowed by auth_rhosts2");
801
802 host_status = check_key_in_hostfiles(pw, key, lookup,
803 _PATH_SSH_SYSTEM_HOSTFILE,
804 options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
805
806 /* backward compat if no key has been found. */
807 if (host_status == HOST_NEW)
808 host_status = check_key_in_hostfiles(pw, key, lookup,
809 _PATH_SSH_SYSTEM_HOSTFILE2,
810 options.ignore_user_known_hosts ? NULL :
811 _PATH_SSH_USER_HOSTFILE2);
812
813 return (host_status == HOST_OK);
814}