summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--Makefile.in6
-rw-r--r--auth-bsdauth.c15
-rw-r--r--auth-options.c80
-rw-r--r--auth-rh-rsa.c6
-rw-r--r--auth-rsa.c17
-rw-r--r--auth-skey.c17
-rw-r--r--auth.h5
-rw-r--r--auth1.c25
-rw-r--r--auth2-chall.c21
-rw-r--r--auth2.c43
-rw-r--r--kex.c8
-rw-r--r--kex.h3
-rw-r--r--kexdh.c5
-rw-r--r--kexgex.c9
-rw-r--r--monitor.c1440
-rw-r--r--monitor.h78
-rw-r--r--monitor_fdpass.c86
-rw-r--r--monitor_fdpass.h32
-rw-r--r--monitor_mm.c329
-rw-r--r--monitor_mm.h64
-rw-r--r--monitor_wrap.c894
-rw-r--r--monitor_wrap.h85
-rw-r--r--servconf.c42
-rw-r--r--servconf.h5
-rw-r--r--serverloop.c4
-rw-r--r--session.c117
-rw-r--r--session.h34
-rw-r--r--sshd.c209
29 files changed, 3549 insertions, 138 deletions
diff --git a/ChangeLog b/ChangeLog
index 8ee5bb9aa..9c8ddecc0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -59,6 +59,12 @@
59 - provos@cvs.openbsd.org 2002/03/18 17:31:54 59 - provos@cvs.openbsd.org 2002/03/18 17:31:54
60 [compress.c] 60 [compress.c]
61 export compression streams for ssh-privsep 61 export compression streams for ssh-privsep
62 - provos@cvs.openbsd.org 2002/03/18 17:50:31
63 [auth-bsdauth.c auth-options.c auth-rh-rsa.c auth-rsa.c auth-skey.c auth.h
64 auth1.c auth2-chall.c auth2.c kex.c kex.h kexdh.c kexgex.c servconf.c
65 session.h servconf.h serverloop.c session.c sshd.c]
66 integrate privilege separated openssh; its turned off by default for now.
67 work done by me and markus@
62 68
6320020317 6920020317
64 - (tim) [configure.ac] Assume path given with --with-pid-dir=PATH is wanted, 70 - (tim) [configure.ac] Assume path given with --with-pid-dir=PATH is wanted,
@@ -7905,4 +7911,4 @@
7905 - Wrote replacements for strlcpy and mkdtemp 7911 - Wrote replacements for strlcpy and mkdtemp
7906 - Released 1.0pre1 7912 - Released 1.0pre1
7907 7913
7908$Id: ChangeLog,v 1.1942 2002/03/22 01:51:24 mouring Exp $ 7914$Id: ChangeLog,v 1.1943 2002/03/22 02:30:41 mouring Exp $
diff --git a/Makefile.in b/Makefile.in
index 31aa8e583..cae801ef2 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,4 +1,4 @@
1# $Id: Makefile.in,v 1.199 2002/03/13 02:19:42 djm Exp $ 1# $Id: Makefile.in,v 1.200 2002/03/22 02:30:43 mouring Exp $
2 2
3prefix=@prefix@ 3prefix=@prefix@
4exec_prefix=@exec_prefix@ 4exec_prefix=@exec_prefix@
@@ -50,11 +50,11 @@ INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
50 50
51TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} $(SFTP_PROGS) 51TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} $(SFTP_PROGS)
52 52
53LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dh.o dispatch.o fatal.o mac.o hostfile.o key.o kex.o kexdh.o kexgex.o log.o match.o misc.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o scard.o ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o 53LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dh.o dispatch.o fatal.o mac.o hostfile.o key.o kex.o kexdh.o kexgex.o log.o match.o misc.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o scard.o ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o monitor_wrap.o monitor_fdpass.o
54 54
55SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o sshtty.o readconf.o clientloop.o 55SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o sshtty.o readconf.o clientloop.o
56 56
57SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-chall.o auth2-chall.o auth-rhosts.o auth-options.o auth-krb4.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 57SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-chall.o auth2-chall.o auth-rhosts.o auth-options.o auth-krb4.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
58 58
59MANPAGES = 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 59MANPAGES = 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
60MANPAGES_IN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 60MANPAGES_IN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1
diff --git a/auth-bsdauth.c b/auth-bsdauth.c
index b70d48f20..fa06732cc 100644
--- a/auth-bsdauth.c
+++ b/auth-bsdauth.c
@@ -22,12 +22,13 @@
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */ 23 */
24#include "includes.h" 24#include "includes.h"
25RCSID("$OpenBSD: auth-bsdauth.c,v 1.2 2001/12/19 07:18:56 deraadt Exp $"); 25RCSID("$OpenBSD: auth-bsdauth.c,v 1.3 2002/03/18 17:50:31 provos Exp $");
26 26
27#ifdef BSD_AUTH 27#ifdef BSD_AUTH
28#include "xmalloc.h" 28#include "xmalloc.h"
29#include "auth.h" 29#include "auth.h"
30#include "log.h" 30#include "log.h"
31#include "monitor_wrap.h"
31 32
32static void * 33static void *
33bsdauth_init_ctx(Authctxt *authctxt) 34bsdauth_init_ctx(Authctxt *authctxt)
@@ -35,7 +36,7 @@ bsdauth_init_ctx(Authctxt *authctxt)
35 return authctxt; 36 return authctxt;
36} 37}
37 38
38static int 39int
39bsdauth_query(void *ctx, char **name, char **infotxt, 40bsdauth_query(void *ctx, char **name, char **infotxt,
40 u_int *numprompts, char ***prompts, u_int **echo_on) 41 u_int *numprompts, char ***prompts, u_int **echo_on)
41{ 42{
@@ -76,7 +77,7 @@ bsdauth_query(void *ctx, char **name, char **infotxt,
76 return 0; 77 return 0;
77} 78}
78 79
79static int 80int
80bsdauth_respond(void *ctx, u_int numresponses, char **responses) 81bsdauth_respond(void *ctx, u_int numresponses, char **responses)
81{ 82{
82 Authctxt *authctxt = ctx; 83 Authctxt *authctxt = ctx;
@@ -113,4 +114,12 @@ KbdintDevice bsdauth_device = {
113 bsdauth_respond, 114 bsdauth_respond,
114 bsdauth_free_ctx 115 bsdauth_free_ctx
115}; 116};
117
118KbdintDevice mm_bsdauth_device = {
119 "bsdauth",
120 bsdauth_init_ctx,
121 mm_bsdauth_query,
122 mm_bsdauth_respond,
123 bsdauth_free_ctx
124};
116#endif 125#endif
diff --git a/auth-options.c b/auth-options.c
index 8df6a6dfc..48be6d8e0 100644
--- a/auth-options.c
+++ b/auth-options.c
@@ -10,7 +10,7 @@
10 */ 10 */
11 11
12#include "includes.h" 12#include "includes.h"
13RCSID("$OpenBSD: auth-options.c,v 1.21 2002/01/29 14:32:03 markus Exp $"); 13RCSID("$OpenBSD: auth-options.c,v 1.22 2002/03/18 17:50:31 provos Exp $");
14 14
15#include "packet.h" 15#include "packet.h"
16#include "xmalloc.h" 16#include "xmalloc.h"
@@ -20,7 +20,13 @@ RCSID("$OpenBSD: auth-options.c,v 1.21 2002/01/29 14:32:03 markus Exp $");
20#include "channels.h" 20#include "channels.h"
21#include "auth-options.h" 21#include "auth-options.h"
22#include "servconf.h" 22#include "servconf.h"
23#include "bufaux.h"
23#include "misc.h" 24#include "misc.h"
25#include "monitor_wrap.h"
26
27/* Debugging messages */
28Buffer auth_debug;
29int auth_debug_init;
24 30
25/* Flags set authorized_keys flags */ 31/* Flags set authorized_keys flags */
26int no_port_forwarding_flag = 0; 32int no_port_forwarding_flag = 0;
@@ -37,8 +43,27 @@ struct envstring *custom_environment = NULL;
37extern ServerOptions options; 43extern ServerOptions options;
38 44
39void 45void
46auth_send_debug(Buffer *m)
47{
48 char *msg;
49
50 while (buffer_len(m)) {
51 msg = buffer_get_string(m, NULL);
52 packet_send_debug("%s", msg);
53 xfree(msg);
54 }
55}
56
57void
40auth_clear_options(void) 58auth_clear_options(void)
41{ 59{
60 if (auth_debug_init)
61 buffer_clear(&auth_debug);
62 else {
63 buffer_init(&auth_debug);
64 auth_debug_init = 1;
65 }
66
42 no_agent_forwarding_flag = 0; 67 no_agent_forwarding_flag = 0;
43 no_port_forwarding_flag = 0; 68 no_port_forwarding_flag = 0;
44 no_pty_flag = 0; 69 no_pty_flag = 0;
@@ -63,6 +88,7 @@ auth_clear_options(void)
63int 88int
64auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) 89auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
65{ 90{
91 char tmp[1024];
66 const char *cp; 92 const char *cp;
67 int i; 93 int i;
68 94
@@ -75,28 +101,32 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
75 while (*opts && *opts != ' ' && *opts != '\t') { 101 while (*opts && *opts != ' ' && *opts != '\t') {
76 cp = "no-port-forwarding"; 102 cp = "no-port-forwarding";
77 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 103 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
78 packet_send_debug("Port forwarding disabled."); 104 snprintf(tmp, sizeof(tmp), "Port forwarding disabled.");
105 buffer_put_cstring(&auth_debug, tmp);
79 no_port_forwarding_flag = 1; 106 no_port_forwarding_flag = 1;
80 opts += strlen(cp); 107 opts += strlen(cp);
81 goto next_option; 108 goto next_option;
82 } 109 }
83 cp = "no-agent-forwarding"; 110 cp = "no-agent-forwarding";
84 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 111 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
85 packet_send_debug("Agent forwarding disabled."); 112 snprintf(tmp, sizeof(tmp), "Agent forwarding disabled.");
113 buffer_put_cstring(&auth_debug, tmp);
86 no_agent_forwarding_flag = 1; 114 no_agent_forwarding_flag = 1;
87 opts += strlen(cp); 115 opts += strlen(cp);
88 goto next_option; 116 goto next_option;
89 } 117 }
90 cp = "no-X11-forwarding"; 118 cp = "no-X11-forwarding";
91 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 119 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
92 packet_send_debug("X11 forwarding disabled."); 120 snprintf(tmp, sizeof(tmp), "X11 forwarding disabled.");
121 buffer_put_cstring(&auth_debug, tmp);
93 no_x11_forwarding_flag = 1; 122 no_x11_forwarding_flag = 1;
94 opts += strlen(cp); 123 opts += strlen(cp);
95 goto next_option; 124 goto next_option;
96 } 125 }
97 cp = "no-pty"; 126 cp = "no-pty";
98 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 127 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
99 packet_send_debug("Pty allocation disabled."); 128 snprintf(tmp, sizeof(tmp), "Pty allocation disabled.");
129 buffer_put_cstring(&auth_debug, tmp);
100 no_pty_flag = 1; 130 no_pty_flag = 1;
101 opts += strlen(cp); 131 opts += strlen(cp);
102 goto next_option; 132 goto next_option;
@@ -119,14 +149,16 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
119 if (!*opts) { 149 if (!*opts) {
120 debug("%.100s, line %lu: missing end quote", 150 debug("%.100s, line %lu: missing end quote",
121 file, linenum); 151 file, linenum);
122 packet_send_debug("%.100s, line %lu: missing end quote", 152 snprintf(tmp, sizeof(tmp), "%.100s, line %lu: missing end quote",
123 file, linenum); 153 file, linenum);
154 buffer_put_cstring(&auth_debug, tmp);
124 xfree(forced_command); 155 xfree(forced_command);
125 forced_command = NULL; 156 forced_command = NULL;
126 goto bad_option; 157 goto bad_option;
127 } 158 }
128 forced_command[i] = 0; 159 forced_command[i] = 0;
129 packet_send_debug("Forced command: %.900s", forced_command); 160 snprintf(tmp, sizeof(tmp), "Forced command: %.900s", forced_command);
161 buffer_put_cstring(&auth_debug, tmp);
130 opts++; 162 opts++;
131 goto next_option; 163 goto next_option;
132 } 164 }
@@ -151,13 +183,15 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
151 if (!*opts) { 183 if (!*opts) {
152 debug("%.100s, line %lu: missing end quote", 184 debug("%.100s, line %lu: missing end quote",
153 file, linenum); 185 file, linenum);
154 packet_send_debug("%.100s, line %lu: missing end quote", 186 snprintf(tmp, sizeof(tmp), "%.100s, line %lu: missing end quote",
155 file, linenum); 187 file, linenum);
188 buffer_put_cstring(&auth_debug, tmp);
156 xfree(s); 189 xfree(s);
157 goto bad_option; 190 goto bad_option;
158 } 191 }
159 s[i] = 0; 192 s[i] = 0;
160 packet_send_debug("Adding to environment: %.900s", s); 193 snprintf(tmp, sizeof(tmp), "Adding to environment: %.900s", s);
194 buffer_put_cstring(&auth_debug, tmp);
161 debug("Adding to environment: %.900s", s); 195 debug("Adding to environment: %.900s", s);
162 opts++; 196 opts++;
163 new_envstring = xmalloc(sizeof(struct envstring)); 197 new_envstring = xmalloc(sizeof(struct envstring));
@@ -188,8 +222,9 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
188 if (!*opts) { 222 if (!*opts) {
189 debug("%.100s, line %lu: missing end quote", 223 debug("%.100s, line %lu: missing end quote",
190 file, linenum); 224 file, linenum);
191 packet_send_debug("%.100s, line %lu: missing end quote", 225 snprintf(tmp, sizeof(tmp), "%.100s, line %lu: missing end quote",
192 file, linenum); 226 file, linenum);
227 buffer_put_cstring(&auth_debug, tmp);
193 xfree(patterns); 228 xfree(patterns);
194 goto bad_option; 229 goto bad_option;
195 } 230 }
@@ -202,9 +237,11 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
202 "correct key but not from a permitted " 237 "correct key but not from a permitted "
203 "host (host=%.200s, ip=%.200s).", 238 "host (host=%.200s, ip=%.200s).",
204 pw->pw_name, remote_host, remote_ip); 239 pw->pw_name, remote_host, remote_ip);
205 packet_send_debug("Your host '%.200s' is not " 240 snprintf(tmp, sizeof(tmp),
241 "Your host '%.200s' is not "
206 "permitted to use this key for login.", 242 "permitted to use this key for login.",
207 remote_host); 243 remote_host);
244 buffer_put_cstring(&auth_debug, tmp);
208 /* deny access */ 245 /* deny access */
209 return 0; 246 return 0;
210 } 247 }
@@ -233,8 +270,9 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
233 if (!*opts) { 270 if (!*opts) {
234 debug("%.100s, line %lu: missing end quote", 271 debug("%.100s, line %lu: missing end quote",
235 file, linenum); 272 file, linenum);
236 packet_send_debug("%.100s, line %lu: missing end quote", 273 snprintf(tmp, sizeof(tmp), "%.100s, line %lu: missing end quote",
237 file, linenum); 274 file, linenum);
275 buffer_put_cstring(&auth_debug, tmp);
238 xfree(patterns); 276 xfree(patterns);
239 goto bad_option; 277 goto bad_option;
240 } 278 }
@@ -244,16 +282,18 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
244 sscanf(patterns, "%255[^/]/%5[0-9]", host, sport) != 2) { 282 sscanf(patterns, "%255[^/]/%5[0-9]", host, sport) != 2) {
245 debug("%.100s, line %lu: Bad permitopen specification " 283 debug("%.100s, line %lu: Bad permitopen specification "
246 "<%.100s>", file, linenum, patterns); 284 "<%.100s>", file, linenum, patterns);
247 packet_send_debug("%.100s, line %lu: " 285 snprintf(tmp, sizeof(tmp), "%.100s, line %lu: "
248 "Bad permitopen specification", file, linenum); 286 "Bad permitopen specification", file, linenum);
287 buffer_put_cstring(&auth_debug, tmp);
249 xfree(patterns); 288 xfree(patterns);
250 goto bad_option; 289 goto bad_option;
251 } 290 }
252 if ((port = a2port(sport)) == 0) { 291 if ((port = a2port(sport)) == 0) {
253 debug("%.100s, line %lu: Bad permitopen port <%.100s>", 292 debug("%.100s, line %lu: Bad permitopen port <%.100s>",
254 file, linenum, sport); 293 file, linenum, sport);
255 packet_send_debug("%.100s, line %lu: " 294 snprintf(tmp, sizeof(tmp), "%.100s, line %lu: "
256 "Bad permitopen port", file, linenum); 295 "Bad permitopen port", file, linenum);
296 buffer_put_cstring(&auth_debug, tmp);
257 xfree(patterns); 297 xfree(patterns);
258 goto bad_option; 298 goto bad_option;
259 } 299 }
@@ -276,14 +316,24 @@ next_option:
276 opts++; 316 opts++;
277 /* Process the next option. */ 317 /* Process the next option. */
278 } 318 }
319
320 if (!use_privsep)
321 auth_send_debug(&auth_debug);
322
279 /* grant access */ 323 /* grant access */
280 return 1; 324 return 1;
281 325
282bad_option: 326bad_option:
283 log("Bad options in %.100s file, line %lu: %.50s", 327 log("Bad options in %.100s file, line %lu: %.50s",
284 file, linenum, opts); 328 file, linenum, opts);
285 packet_send_debug("Bad options in %.100s file, line %lu: %.50s", 329 snprintf(tmp, sizeof(tmp),
330 "Bad options in %.100s file, line %lu: %.50s",
286 file, linenum, opts); 331 file, linenum, opts);
332 buffer_put_cstring(&auth_debug, tmp);
333
334 if (!use_privsep)
335 auth_send_debug(&auth_debug);
336
287 /* deny access */ 337 /* deny access */
288 return 0; 338 return 0;
289} 339}
diff --git a/auth-rh-rsa.c b/auth-rh-rsa.c
index 2a88e18b3..c940ec581 100644
--- a/auth-rh-rsa.c
+++ b/auth-rh-rsa.c
@@ -13,7 +13,7 @@
13 */ 13 */
14 14
15#include "includes.h" 15#include "includes.h"
16RCSID("$OpenBSD: auth-rh-rsa.c,v 1.31 2002/03/16 17:22:09 markus Exp $"); 16RCSID("$OpenBSD: auth-rh-rsa.c,v 1.32 2002/03/18 17:50:31 provos Exp $");
17 17
18#include "packet.h" 18#include "packet.h"
19#include "uidswap.h" 19#include "uidswap.h"
@@ -25,6 +25,8 @@ RCSID("$OpenBSD: auth-rh-rsa.c,v 1.31 2002/03/16 17:22:09 markus Exp $");
25#include "auth.h" 25#include "auth.h"
26#include "canohost.h" 26#include "canohost.h"
27 27
28#include "monitor_wrap.h"
29
28/* import */ 30/* import */
29extern ServerOptions options; 31extern ServerOptions options;
30 32
@@ -69,7 +71,7 @@ auth_rhosts_rsa(struct passwd *pw, char *cuser, Key *client_host_key)
69 chost = (char *)get_canonical_hostname(options.verify_reverse_mapping); 71 chost = (char *)get_canonical_hostname(options.verify_reverse_mapping);
70 debug("Rhosts RSA authentication: canonical host %.900s", chost); 72 debug("Rhosts RSA authentication: canonical host %.900s", chost);
71 73
72 if (!auth_rhosts_rsa_key_allowed(pw, cuser, chost, client_host_key)) { 74 if (!PRIVSEP(auth_rhosts_rsa_key_allowed(pw, cuser, chost, client_host_key))) {
73 debug("Rhosts with RSA host authentication denied: unknown or invalid host key"); 75 debug("Rhosts with RSA host authentication denied: unknown or invalid host key");
74 packet_send_debug("Your host key cannot be verified: unknown or invalid host key."); 76 packet_send_debug("Your host key cannot be verified: unknown or invalid host key.");
75 return 0; 77 return 0;
diff --git a/auth-rsa.c b/auth-rsa.c
index ff9bf3b64..9c5d484b1 100644
--- a/auth-rsa.c
+++ b/auth-rsa.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$OpenBSD: auth-rsa.c,v 1.51 2002/03/14 16:56:33 markus Exp $"); 17RCSID("$OpenBSD: auth-rsa.c,v 1.52 2002/03/18 17:50:31 provos Exp $");
18 18
19#include <openssl/rsa.h> 19#include <openssl/rsa.h>
20#include <openssl/md5.h> 20#include <openssl/md5.h>
@@ -32,6 +32,7 @@ RCSID("$OpenBSD: auth-rsa.c,v 1.51 2002/03/14 16:56:33 markus Exp $");
32#include "servconf.h" 32#include "servconf.h"
33#include "auth.h" 33#include "auth.h"
34#include "hostfile.h" 34#include "hostfile.h"
35#include "monitor_wrap.h"
35 36
36/* import */ 37/* import */
37extern ServerOptions options; 38extern ServerOptions options;
@@ -52,7 +53,7 @@ extern u_char session_id[16];
52 * description of the options. 53 * description of the options.
53 */ 54 */
54 55
55static BIGNUM * 56BIGNUM *
56auth_rsa_generate_challenge(Key *key) 57auth_rsa_generate_challenge(Key *key)
57{ 58{
58 BIGNUM *challenge; 59 BIGNUM *challenge;
@@ -70,7 +71,7 @@ auth_rsa_generate_challenge(Key *key)
70 return challenge; 71 return challenge;
71} 72}
72 73
73static int 74int
74auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16]) 75auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
75{ 76{
76 u_char buf[32], mdbuf[16]; 77 u_char buf[32], mdbuf[16];
@@ -113,7 +114,7 @@ auth_rsa_challenge_dialog(Key *key)
113 if ((encrypted_challenge = BN_new()) == NULL) 114 if ((encrypted_challenge = BN_new()) == NULL)
114 fatal("auth_rsa_challenge_dialog: BN_new() failed"); 115 fatal("auth_rsa_challenge_dialog: BN_new() failed");
115 116
116 challenge = auth_rsa_generate_challenge(key); 117 challenge = PRIVSEP(auth_rsa_generate_challenge(key));
117 118
118 /* Encrypt the challenge with the public key. */ 119 /* Encrypt the challenge with the public key. */
119 rsa_public_encrypt(encrypted_challenge, challenge, key->rsa); 120 rsa_public_encrypt(encrypted_challenge, challenge, key->rsa);
@@ -131,7 +132,7 @@ auth_rsa_challenge_dialog(Key *key)
131 response[i] = packet_get_char(); 132 response[i] = packet_get_char();
132 packet_check_eom(); 133 packet_check_eom();
133 134
134 success = auth_rsa_verify_response(key, challenge, response); 135 success = PRIVSEP(auth_rsa_verify_response(key, challenge, response));
135 BN_clear_free(challenge); 136 BN_clear_free(challenge);
136 return (success); 137 return (success);
137} 138}
@@ -141,11 +142,11 @@ auth_rsa_challenge_dialog(Key *key)
141 * return key if login is allowed, NULL otherwise 142 * return key if login is allowed, NULL otherwise
142 */ 143 */
143 144
144static int 145int
145auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) 146auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
146{ 147{
147 char line[8192], *file; 148 char line[8192], *file;
148 int allowed; 149 int allowed = 0;
149 u_int bits; 150 u_int bits;
150 FILE *f; 151 FILE *f;
151 u_long linenum = 0; 152 u_long linenum = 0;
@@ -284,7 +285,7 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
284 if (pw == NULL) 285 if (pw == NULL)
285 return 0; 286 return 0;
286 287
287 if (auth_rsa_key_allowed(pw, client_n, &key) == 0) { 288 if (!PRIVSEP(auth_rsa_key_allowed(pw, client_n, &key))) {
288 auth_clear_options(); 289 auth_clear_options();
289 return (0); 290 return (0);
290 } 291 }
diff --git a/auth-skey.c b/auth-skey.c
index df19f7507..e897d1875 100644
--- a/auth-skey.c
+++ b/auth-skey.c
@@ -22,7 +22,7 @@
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */ 23 */
24#include "includes.h" 24#include "includes.h"
25RCSID("$OpenBSD: auth-skey.c,v 1.16 2002/01/12 13:10:29 markus Exp $"); 25RCSID("$OpenBSD: auth-skey.c,v 1.17 2002/03/18 17:50:31 provos Exp $");
26 26
27#ifdef SKEY 27#ifdef SKEY
28 28
@@ -30,6 +30,7 @@ RCSID("$OpenBSD: auth-skey.c,v 1.16 2002/01/12 13:10:29 markus Exp $");
30 30
31#include "xmalloc.h" 31#include "xmalloc.h"
32#include "auth.h" 32#include "auth.h"
33#include "monitor_wrap.h"
33 34
34static void * 35static void *
35skey_init_ctx(Authctxt *authctxt) 36skey_init_ctx(Authctxt *authctxt)
@@ -37,8 +38,6 @@ skey_init_ctx(Authctxt *authctxt)
37 return authctxt; 38 return authctxt;
38} 39}
39 40
40#define PROMPT "\nS/Key Password: "
41
42static int 41static int
43skey_query(void *ctx, char **name, char **infotxt, 42skey_query(void *ctx, char **name, char **infotxt,
44 u_int* numprompts, char ***prompts, u_int **echo_on) 43 u_int* numprompts, char ***prompts, u_int **echo_on)
@@ -58,10 +57,10 @@ skey_query(void *ctx, char **name, char **infotxt,
58 *echo_on = xmalloc(*numprompts * sizeof(u_int)); 57 *echo_on = xmalloc(*numprompts * sizeof(u_int));
59 (*echo_on)[0] = 0; 58 (*echo_on)[0] = 0;
60 59
61 len = strlen(challenge) + strlen(PROMPT) + 1; 60 len = strlen(challenge) + strlen(SKEY_PROMPT) + 1;
62 p = xmalloc(len); 61 p = xmalloc(len);
63 strlcpy(p, challenge, len); 62 strlcpy(p, challenge, len);
64 strlcat(p, PROMPT, len); 63 strlcat(p, SKEY_PROMPT, len);
65 (*prompts)[0] = p; 64 (*prompts)[0] = p;
66 65
67 return 0; 66 return 0;
@@ -93,4 +92,12 @@ KbdintDevice skey_device = {
93 skey_respond, 92 skey_respond,
94 skey_free_ctx 93 skey_free_ctx
95}; 94};
95
96KbdintDevice mm_skey_device = {
97 "skey",
98 skey_init_ctx,
99 mm_skey_query,
100 mm_skey_respond,
101 skey_free_ctx
102};
96#endif /* SKEY */ 103#endif /* SKEY */
diff --git a/auth.h b/auth.h
index bdfdf1c54..3e4a55010 100644
--- a/auth.h
+++ b/auth.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth.h,v 1.33 2002/03/18 01:12:14 provos Exp $ */ 1/* $OpenBSD: auth.h,v 1.34 2002/03/18 17:50:31 provos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -129,6 +129,8 @@ void auth_log(Authctxt *, int, char *, char *);
129void userauth_finish(Authctxt *, int, char *); 129void userauth_finish(Authctxt *, int, char *);
130int auth_root_allowed(char *); 130int auth_root_allowed(char *);
131 131
132void privsep_challenge_enable(void);
133
132int auth2_challenge(Authctxt *, char *); 134int auth2_challenge(Authctxt *, char *);
133void auth2_challenge_stop(Authctxt *); 135void auth2_challenge_stop(Authctxt *);
134 136
@@ -155,4 +157,5 @@ check_key_in_hostfiles(struct passwd *, Key *, const char *,
155#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2) 157#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
156#define AUTH_FAIL_MSG "Too many authentication failures for %.100s" 158#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
157 159
160#define SKEY_PROMPT "\nS/Key Password: "
158#endif 161#endif
diff --git a/auth1.c b/auth1.c
index 4c295215f..ca288958e 100644
--- a/auth1.c
+++ b/auth1.c
@@ -10,7 +10,7 @@
10 */ 10 */
11 11
12#include "includes.h" 12#include "includes.h"
13RCSID("$OpenBSD: auth1.c,v 1.37 2002/03/18 01:12:14 provos Exp $"); 13RCSID("$OpenBSD: auth1.c,v 1.38 2002/03/18 17:50:31 provos Exp $");
14 14
15#include "xmalloc.h" 15#include "xmalloc.h"
16#include "rsa.h" 16#include "rsa.h"
@@ -26,6 +26,7 @@ RCSID("$OpenBSD: auth1.c,v 1.37 2002/03/18 01:12:14 provos Exp $");
26#include "session.h" 26#include "session.h"
27#include "misc.h" 27#include "misc.h"
28#include "uidswap.h" 28#include "uidswap.h"
29#include "monitor_wrap.h"
29 30
30/* import */ 31/* import */
31extern ServerOptions options; 32extern ServerOptions options;
@@ -89,7 +90,7 @@ do_authloop(Authctxt *authctxt)
89#elif defined(HAVE_OSF_SIA) 90#elif defined(HAVE_OSF_SIA)
90 0) { 91 0) {
91#else 92#else
92 auth_password(authctxt, "")) { 93 PRIVSEP(auth_password(authctxt, ""))) {
93#endif 94#endif
94 auth_log(authctxt, 1, "without authentication", ""); 95 auth_log(authctxt, 1, "without authentication", "");
95 return; 96 return;
@@ -253,9 +254,8 @@ do_authloop(Authctxt *authctxt)
253 /* Do SIA auth with password */ 254 /* Do SIA auth with password */
254 authenticated = auth_sia_password(authctxt->user, 255 authenticated = auth_sia_password(authctxt->user,
255 password); 256 password);
256#else /* !USE_PAM && !HAVE_OSF_SIA */
257 /* Try authentication with the password. */ 257 /* Try authentication with the password. */
258 authenticated = auth_password(authctxt, password); 258 authenticated = PRIVSEP(auth_password(authctxt, password));
259#endif /* USE_PAM */ 259#endif /* USE_PAM */
260 260
261 memset(password, 0, strlen(password)); 261 memset(password, 0, strlen(password));
@@ -359,7 +359,7 @@ Authctxt *
359do_authentication(void) 359do_authentication(void)
360{ 360{
361 Authctxt *authctxt; 361 Authctxt *authctxt;
362 struct passwd *pw; 362 struct passwd *pw = NULL, *pwent;
363 u_int ulen; 363 u_int ulen;
364 char *p, *user, *style = NULL; 364 char *p, *user, *style = NULL;
365 365
@@ -382,17 +382,22 @@ do_authentication(void)
382 authctxt->style = style; 382 authctxt->style = style;
383 383
384 /* Verify that the user is a valid user. */ 384 /* Verify that the user is a valid user. */
385 pw = getpwnamallow(user); 385 pwent = PRIVSEP(getpwnamallow(user));
386 if (pw) { 386 if (pwent) {
387 authctxt->valid = 1; 387 authctxt->valid = 1;
388 pw = pwcopy(pw); 388 pw = pwcopy(pwent);
389 } else { 389 } else {
390 debug("do_authentication: illegal user %s", user); 390 debug("do_authentication: illegal user %s", user);
391 pw = NULL; 391 pw = NULL;
392 } 392 }
393 /* Free memory */
394 if (use_privsep && pwent != NULL)
395 pwfree(pwent);
396
393 authctxt->pw = pw; 397 authctxt->pw = pw;
394 398
395 setproctitle("%s", pw ? user : "unknown"); 399 setproctitle("%s%s", pw ? user : "unknown",
400 use_privsep ? " [net]" : "");
396 401
397#ifdef USE_PAM 402#ifdef USE_PAM
398 start_pam(pw == NULL ? "NOUSER" : user); 403 start_pam(pw == NULL ? "NOUSER" : user);
@@ -403,7 +408,7 @@ do_authentication(void)
403 * the server. (Unless you are running Windows) 408 * the server. (Unless you are running Windows)
404 */ 409 */
405#ifndef HAVE_CYGWIN 410#ifndef HAVE_CYGWIN
406 if (getuid() != 0 && pw && pw->pw_uid != getuid()) 411 if (!use_privsep && getuid() != 0 && pw && pw->pw_uid != getuid())
407 packet_disconnect("Cannot change user when server not running as root."); 412 packet_disconnect("Cannot change user when server not running as root.");
408#endif 413#endif
409 414
diff --git a/auth2-chall.c b/auth2-chall.c
index 9f1d93275..38f955a02 100644
--- a/auth2-chall.c
+++ b/auth2-chall.c
@@ -23,7 +23,7 @@
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */ 24 */
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: auth2-chall.c,v 1.16 2002/01/13 17:57:37 markus Exp $"); 26RCSID("$OpenBSD: auth2-chall.c,v 1.17 2002/03/18 17:50:31 provos Exp $");
27 27
28#include "ssh2.h" 28#include "ssh2.h"
29#include "auth.h" 29#include "auth.h"
@@ -310,3 +310,22 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
310 userauth_finish(authctxt, authenticated, method); 310 userauth_finish(authctxt, authenticated, method);
311 xfree(method); 311 xfree(method);
312} 312}
313
314void
315privsep_challenge_enable(void)
316{
317#ifdef BSD_AUTH
318 extern KbdintDevice mm_bsdauth_device;
319#endif
320#ifdef SKEY
321 extern KbdintDevice mm_skey_device;
322#endif
323 /* As long as SSHv1 has devices[0] hard coded this is fine */
324#ifdef BSD_AUTH
325 devices[0] = &mm_bsdauth_device;
326#else
327#ifdef SKEY
328 devices[0] = &mm_skey_device;
329#endif
330#endif
331}
diff --git a/auth2.c b/auth2.c
index b57fda216..9bfcde5c1 100644
--- a/auth2.c
+++ b/auth2.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: auth2.c,v 1.87 2002/03/18 01:12:14 provos Exp $"); 26RCSID("$OpenBSD: auth2.c,v 1.88 2002/03/18 17:50:31 provos Exp $");
27 27
28#include <openssl/evp.h> 28#include <openssl/evp.h>
29 29
@@ -51,13 +51,14 @@ RCSID("$OpenBSD: auth2.c,v 1.87 2002/03/18 01:12:14 provos Exp $");
51#include "hostfile.h" 51#include "hostfile.h"
52#include "canohost.h" 52#include "canohost.h"
53#include "match.h" 53#include "match.h"
54#include "monitor_wrap.h"
54 55
55/* import */ 56/* import */
56extern ServerOptions options; 57extern ServerOptions options;
57extern u_char *session_id2; 58extern u_char *session_id2;
58extern int session_id2_len; 59extern int session_id2_len;
59 60
60static Authctxt *x_authctxt = NULL; 61Authctxt *x_authctxt = NULL;
61static int one = 1; 62static int one = 1;
62 63
63typedef struct Authmethod Authmethod; 64typedef struct Authmethod Authmethod;
@@ -75,8 +76,8 @@ static void input_userauth_request(int, u_int32_t, void *);
75/* helper */ 76/* helper */
76static Authmethod *authmethod_lookup(const char *); 77static Authmethod *authmethod_lookup(const char *);
77static char *authmethods_get(void); 78static char *authmethods_get(void);
78static int user_key_allowed(struct passwd *, Key *); 79int user_key_allowed(struct passwd *, Key *);
79static int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); 80int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
80 81
81/* auth */ 82/* auth */
82static void userauth_banner(void); 83static void userauth_banner(void);
@@ -185,7 +186,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
185 if (authctxt->attempt++ == 0) { 186 if (authctxt->attempt++ == 0) {
186 /* setup auth context */ 187 /* setup auth context */
187 struct passwd *pw = NULL; 188 struct passwd *pw = NULL;
188 pw = getpwnamallow(user); 189 pw = PRIVSEP(getpwnamallow(user));
189 if (pw && strcmp(service, "ssh-connection")==0) { 190 if (pw && strcmp(service, "ssh-connection")==0) {
190 authctxt->pw = pwcopy(pw); 191 authctxt->pw = pwcopy(pw);
191 authctxt->valid = 1; 192 authctxt->valid = 1;
@@ -199,10 +200,18 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
199 start_pam("NOUSER"); 200 start_pam("NOUSER");
200#endif 201#endif
201 } 202 }
202 setproctitle("%s", pw ? user : "unknown"); 203 /* Free memory */
204 if (use_privsep && pw != NULL)
205 pwfree(pw);
206
207 setproctitle("%s%s", pw ? user : "unknown",
208 use_privsep ? " [net]" : "");
203 authctxt->user = xstrdup(user); 209 authctxt->user = xstrdup(user);
204 authctxt->service = xstrdup(service); 210 authctxt->service = xstrdup(service);
205 authctxt->style = style ? xstrdup(style) : NULL; 211 authctxt->style = style ? xstrdup(style) : NULL;
212
213 if (use_privsep)
214 mm_inform_authserv(service, style);
206 } else if (strcmp(user, authctxt->user) != 0 || 215 } else if (strcmp(user, authctxt->user) != 0 ||
207 strcmp(service, authctxt->service) != 0) { 216 strcmp(service, authctxt->service) != 0) {
208 packet_disconnect("Change of username or service not allowed: " 217 packet_disconnect("Change of username or service not allowed: "
@@ -333,7 +342,7 @@ userauth_none(Authctxt *authctxt)
333#elif defined(HAVE_OSF_SIA) 342#elif defined(HAVE_OSF_SIA)
334 return 0; 343 return 0;
335#else /* !HAVE_OSF_SIA && !USE_PAM */ 344#else /* !HAVE_OSF_SIA && !USE_PAM */
336 return auth_password(authctxt, ""); 345 return PRIVSEP(auth_password(authctxt, ""));
337#endif /* USE_PAM */ 346#endif /* USE_PAM */
338} 347}
339 348
@@ -358,7 +367,7 @@ userauth_passwd(Authctxt *authctxt)
358#elif defined(HAVE_OSF_SIA) 367#elif defined(HAVE_OSF_SIA)
359 auth_sia_password(authctxt->user, password) == 1) 368 auth_sia_password(authctxt->user, password) == 1)
360#else /* !USE_PAM && !HAVE_OSF_SIA */ 369#else /* !USE_PAM && !HAVE_OSF_SIA */
361 auth_password(authctxt, password) == 1) 370 PRIVSEP(auth_password(authctxt, password)) == 1)
362#endif /* USE_PAM */ 371#endif /* USE_PAM */
363 authenticated = 1; 372 authenticated = 1;
364 memset(password, 0, len); 373 memset(password, 0, len);
@@ -468,8 +477,10 @@ userauth_pubkey(Authctxt *authctxt)
468 buffer_dump(&b); 477 buffer_dump(&b);
469#endif 478#endif
470 /* test for correct signature */ 479 /* test for correct signature */
471 if (user_key_allowed(authctxt->pw, key) && 480 authenticated = 0;
472 key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) 481 if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
482 PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
483 buffer_len(&b))) == 1)
473 authenticated = 1; 484 authenticated = 1;
474 buffer_clear(&b); 485 buffer_clear(&b);
475 xfree(sig); 486 xfree(sig);
@@ -485,7 +496,7 @@ userauth_pubkey(Authctxt *authctxt)
485 * if a user is not allowed to login. is this an 496 * if a user is not allowed to login. is this an
486 * issue? -markus 497 * issue? -markus
487 */ 498 */
488 if (user_key_allowed(authctxt->pw, key)) { 499 if (PRIVSEP(user_key_allowed(authctxt->pw, key))) {
489 packet_start(SSH2_MSG_USERAUTH_PK_OK); 500 packet_start(SSH2_MSG_USERAUTH_PK_OK);
490 packet_put_string(pkalg, alen); 501 packet_put_string(pkalg, alen);
491 packet_put_string(pkblob, blen); 502 packet_put_string(pkblob, blen);
@@ -573,8 +584,10 @@ userauth_hostbased(Authctxt *authctxt)
573 buffer_dump(&b); 584 buffer_dump(&b);
574#endif 585#endif
575 /* test for allowed key and correct signature */ 586 /* test for allowed key and correct signature */
576 if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) && 587 authenticated = 0;
577 key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) 588 if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
589 PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
590 buffer_len(&b))) == 1)
578 authenticated = 1; 591 authenticated = 1;
579 592
580 buffer_clear(&b); 593 buffer_clear(&b);
@@ -731,7 +744,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
731} 744}
732 745
733/* check whether given key is in .ssh/authorized_keys* */ 746/* check whether given key is in .ssh/authorized_keys* */
734static int 747int
735user_key_allowed(struct passwd *pw, Key *key) 748user_key_allowed(struct passwd *pw, Key *key)
736{ 749{
737 int success; 750 int success;
@@ -751,7 +764,7 @@ user_key_allowed(struct passwd *pw, Key *key)
751} 764}
752 765
753/* return 1 if given hostkey is allowed */ 766/* return 1 if given hostkey is allowed */
754static int 767int
755hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, 768hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
756 Key *key) 769 Key *key)
757{ 770{
diff --git a/kex.c b/kex.c
index bf8fd95b4..8097ab0f2 100644
--- a/kex.c
+++ b/kex.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: kex.c,v 1.47 2002/02/28 15:46:33 markus Exp $"); 26RCSID("$OpenBSD: kex.c,v 1.48 2002/03/18 17:50:31 provos Exp $");
27 27
28#include <openssl/crypto.h> 28#include <openssl/crypto.h>
29 29
@@ -40,9 +40,15 @@ RCSID("$OpenBSD: kex.c,v 1.47 2002/02/28 15:46:33 markus Exp $");
40#include "mac.h" 40#include "mac.h"
41#include "match.h" 41#include "match.h"
42#include "dispatch.h" 42#include "dispatch.h"
43#include "monitor.h"
43 44
44#define KEX_COOKIE_LEN 16 45#define KEX_COOKIE_LEN 16
45 46
47/* Use privilege separation for sshd */
48int use_privsep;
49struct monitor *monitor;
50
51
46/* prototype */ 52/* prototype */
47static void kex_kexinit_finish(Kex *); 53static void kex_kexinit_finish(Kex *);
48static void kex_choose_conf(Kex *); 54static void kex_choose_conf(Kex *);
diff --git a/kex.h b/kex.h
index 755bf332a..2d3523a36 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.h,v 1.29 2002/02/14 23:41:01 markus Exp $ */ 1/* $OpenBSD: kex.h,v 1.30 2002/03/18 17:50:31 provos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -111,6 +111,7 @@ struct Kex {
111 char *server_version_string; 111 char *server_version_string;
112 int (*verify_host_key)(Key *); 112 int (*verify_host_key)(Key *);
113 Key *(*load_host_key)(int); 113 Key *(*load_host_key)(int);
114 int (*host_key_index)(Key *);
114}; 115};
115 116
116Kex *kex_setup(char *[PROPOSAL_MAX]); 117Kex *kex_setup(char *[PROPOSAL_MAX]);
diff --git a/kexdh.c b/kexdh.c
index eaf497ca7..1e91e2550 100644
--- a/kexdh.c
+++ b/kexdh.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: kexdh.c,v 1.17 2002/02/28 15:46:33 markus Exp $"); 26RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $");
27 27
28#include <openssl/crypto.h> 28#include <openssl/crypto.h>
29#include <openssl/bn.h> 29#include <openssl/bn.h>
@@ -37,6 +37,7 @@ RCSID("$OpenBSD: kexdh.c,v 1.17 2002/02/28 15:46:33 markus Exp $");
37#include "packet.h" 37#include "packet.h"
38#include "dh.h" 38#include "dh.h"
39#include "ssh2.h" 39#include "ssh2.h"
40#include "monitor_wrap.h"
40 41
41static u_char * 42static u_char *
42kex_dh_hash( 43kex_dh_hash(
@@ -275,7 +276,7 @@ kexdh_server(Kex *kex)
275 276
276 /* sign H */ 277 /* sign H */
277 /* XXX hashlen depends on KEX */ 278 /* XXX hashlen depends on KEX */
278 key_sign(server_host_key, &signature, &slen, hash, 20); 279 PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20));
279 280
280 /* destroy_sensitive_data(); */ 281 /* destroy_sensitive_data(); */
281 282
diff --git a/kexgex.c b/kexgex.c
index 61896e6ed..7379e8d10 100644
--- a/kexgex.c
+++ b/kexgex.c
@@ -24,7 +24,7 @@
24 */ 24 */
25 25
26#include "includes.h" 26#include "includes.h"
27RCSID("$OpenBSD: kexgex.c,v 1.20 2002/02/28 15:46:33 markus Exp $"); 27RCSID("$OpenBSD: kexgex.c,v 1.21 2002/03/18 17:50:31 provos Exp $");
28 28
29#include <openssl/bn.h> 29#include <openssl/bn.h>
30 30
@@ -38,6 +38,7 @@ RCSID("$OpenBSD: kexgex.c,v 1.20 2002/02/28 15:46:33 markus Exp $");
38#include "dh.h" 38#include "dh.h"
39#include "ssh2.h" 39#include "ssh2.h"
40#include "compat.h" 40#include "compat.h"
41#include "monitor_wrap.h"
41 42
42static u_char * 43static u_char *
43kexgex_hash( 44kexgex_hash(
@@ -296,7 +297,8 @@ kexgex_server(Kex *kex)
296 fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d", 297 fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d",
297 min, nbits, max); 298 min, nbits, max);
298 299
299 dh = choose_dh(min, nbits, max); 300 /* Contact privileged parent */
301 dh = PRIVSEP(choose_dh(min, nbits, max));
300 if (dh == NULL) 302 if (dh == NULL)
301 packet_disconnect("Protocol error: no matching DH grp found"); 303 packet_disconnect("Protocol error: no matching DH grp found");
302 304
@@ -379,7 +381,7 @@ kexgex_server(Kex *kex)
379 381
380 /* sign H */ 382 /* sign H */
381 /* XXX hashlen depends on KEX */ 383 /* XXX hashlen depends on KEX */
382 key_sign(server_host_key, &signature, &slen, hash, 20); 384 PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20));
383 385
384 /* destroy_sensitive_data(); */ 386 /* destroy_sensitive_data(); */
385 387
@@ -390,6 +392,7 @@ kexgex_server(Kex *kex)
390 packet_put_bignum2(dh->pub_key); /* f */ 392 packet_put_bignum2(dh->pub_key); /* f */
391 packet_put_string(signature, slen); 393 packet_put_string(signature, slen);
392 packet_send(); 394 packet_send();
395
393 xfree(signature); 396 xfree(signature);
394 xfree(server_host_key_blob); 397 xfree(server_host_key_blob);
395 /* have keys, free DH */ 398 /* have keys, free DH */
diff --git a/monitor.c b/monitor.c
new file mode 100644
index 000000000..921ad985a
--- /dev/null
+++ b/monitor.c
@@ -0,0 +1,1440 @@
1/*
2 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
3 * Copyright 2002 Markus Friedl <markus@openbsd.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "includes.h"
28RCSID("$OpenBSD: monitor.c,v 1.6 2002/03/21 18:38:33 stevesk Exp $");
29
30#include <openssl/dh.h>
31
32#ifdef SKEY
33#include <skey.h>
34#endif
35
36#include "ssh.h"
37#include "auth.h"
38#include "kex.h"
39#include "dh.h"
40#include "zlib.h"
41#include "packet.h"
42#include "auth-options.h"
43#include "sshpty.h"
44#include "channels.h"
45#include "session.h"
46#include "sshlogin.h"
47#include "canohost.h"
48#include "log.h"
49#include "servconf.h"
50#include "monitor.h"
51#include "monitor_mm.h"
52#include "monitor_wrap.h"
53#include "monitor_fdpass.h"
54#include "xmalloc.h"
55#include "misc.h"
56#include "buffer.h"
57#include "bufaux.h"
58#include "compat.h"
59#include "ssh2.h"
60#include "mpaux.h"
61
62/* Imports */
63extern ServerOptions options;
64extern u_int utmp_len;
65extern Newkeys *current_keys[];
66extern z_stream incoming_stream;
67extern z_stream outgoing_stream;
68extern u_char session_id[];
69extern Buffer input, output;
70extern Buffer auth_debug;
71extern int auth_debug_init;
72
73/* State exported from the child */
74
75struct {
76 z_stream incoming;
77 z_stream outgoing;
78 u_char *keyin;
79 u_int keyinlen;
80 u_char *keyout;
81 u_int keyoutlen;
82 u_char *ivin;
83 u_int ivinlen;
84 u_char *ivout;
85 u_int ivoutlen;
86 int ssh1cipher;
87 int ssh1protoflags;
88 u_char *input;
89 u_int ilen;
90 u_char *output;
91 u_int olen;
92} child_state;
93
94/* Functions on the montior that answer unprivileged requests */
95
96int mm_answer_moduli(int, Buffer *);
97int mm_answer_sign(int, Buffer *);
98int mm_answer_pwnamallow(int, Buffer *);
99int mm_answer_authserv(int, Buffer *);
100int mm_answer_authpassword(int, Buffer *);
101int mm_answer_bsdauthquery(int, Buffer *);
102int mm_answer_bsdauthrespond(int, Buffer *);
103int mm_answer_skeyquery(int, Buffer *);
104int mm_answer_skeyrespond(int, Buffer *);
105int mm_answer_keyallowed(int, Buffer *);
106int mm_answer_keyverify(int, Buffer *);
107int mm_answer_pty(int, Buffer *);
108int mm_answer_pty_cleanup(int, Buffer *);
109int mm_answer_term(int, Buffer *);
110int mm_answer_rsa_keyallowed(int, Buffer *);
111int mm_answer_rsa_challenge(int, Buffer *);
112int mm_answer_rsa_response(int, Buffer *);
113int mm_answer_sesskey(int, Buffer *);
114int mm_answer_sessid(int, Buffer *);
115
116static Authctxt *authctxt;
117static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */
118
119/* local state for key verify */
120static u_char *key_blob = NULL;
121static u_int key_bloblen = 0;
122static int key_blobtype = MM_NOKEY;
123static u_char *hostbased_cuser = NULL;
124static u_char *hostbased_chost = NULL;
125static char *auth_method = "unknown";
126
127struct mon_table {
128 enum monitor_reqtype type;
129 int flags;
130 int (*f)(int, Buffer *);
131};
132
133#define MON_ISAUTH 0x0004 /* Required for Authentication */
134#define MON_AUTHDECIDE 0x0008 /* Decides Authentication */
135#define MON_ONCE 0x0010 /* Disable after calling */
136
137#define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE)
138
139#define MON_PERMIT 0x1000 /* Request is permitted */
140
141struct mon_table mon_dispatch_proto20[] = {
142 {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
143 {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
144 {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
145 {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
146 {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
147#ifdef BSD_AUTH
148 {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
149 {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond},
150#endif
151#ifdef SKEY
152 {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
153 {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
154#endif
155 {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
156 {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
157 {0, 0, NULL}
158};
159
160struct mon_table mon_dispatch_postauth20[] = {
161 {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
162 {MONITOR_REQ_SIGN, 0, mm_answer_sign},
163 {MONITOR_REQ_PTY, 0, mm_answer_pty},
164 {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
165 {MONITOR_REQ_TERM, 0, mm_answer_term},
166 {0, 0, NULL}
167};
168
169struct mon_table mon_dispatch_proto15[] = {
170 {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
171 {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey},
172 {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid},
173 {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
174 {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH, mm_answer_rsa_keyallowed},
175 {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
176 {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge},
177 {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response},
178#ifdef BSD_AUTH
179 {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
180 {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond},
181#endif
182#ifdef SKEY
183 {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
184 {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
185#endif
186 {0, 0, NULL}
187};
188
189struct mon_table mon_dispatch_postauth15[] = {
190 {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
191 {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
192 {MONITOR_REQ_TERM, 0, mm_answer_term},
193 {0, 0, NULL}
194};
195
196struct mon_table *mon_dispatch;
197
198/* Specifies if a certain message is allowed at the moment */
199
200static void
201monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit)
202{
203 while (ent->f != NULL) {
204 if (ent->type == type) {
205 ent->flags &= ~MON_PERMIT;
206 ent->flags |= permit ? MON_PERMIT : 0;
207 return;
208 }
209 ent++;
210 }
211}
212
213static void
214monitor_permit_authentications(int permit)
215{
216 struct mon_table *ent = mon_dispatch;
217
218 while (ent->f != NULL) {
219 if (ent->flags & MON_AUTH) {
220 ent->flags &= ~MON_PERMIT;
221 ent->flags |= permit ? MON_PERMIT : 0;
222 }
223 ent++;
224 }
225}
226
227Authctxt *
228monitor_child_preauth(struct monitor *monitor)
229{
230 struct mon_table *ent;
231 int authenticated = 0;
232
233 debug3("preauth child monitor started");
234
235 if (compat20) {
236 mon_dispatch = mon_dispatch_proto20;
237
238 /* Permit requests for moduli and signatures */
239 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
240 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
241 } else {
242 mon_dispatch = mon_dispatch_proto15;
243
244 monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
245 }
246
247 authctxt = authctxt_new();
248
249 /* The first few requests do not require asynchronous access */
250 while (!authenticated) {
251 authenticated = monitor_read(monitor, mon_dispatch, &ent);
252 if (authenticated) {
253 if (!(ent->flags & MON_AUTHDECIDE))
254 fatal("%s: unexpected authentication from %d",
255 __FUNCTION__, ent->type);
256 if (authctxt->pw->pw_uid == 0 &&
257 !auth_root_allowed(auth_method))
258 authenticated = 0;
259 }
260
261 if (ent->flags & MON_AUTHDECIDE) {
262 auth_log(authctxt, authenticated, auth_method,
263 compat20 ? " ssh2" : "");
264 if (!authenticated)
265 authctxt->failures++;
266 }
267 }
268
269 if (!authctxt->valid)
270 fatal("%s: authenticated invalid user", __FUNCTION__);
271
272 debug("%s: %s has been authenticated by privileged process",
273 __FUNCTION__, authctxt->user);
274
275 mm_get_keystate(monitor);
276
277 return (authctxt);
278}
279
280void
281monitor_child_postauth(struct monitor *monitor)
282{
283 if (compat20) {
284 mon_dispatch = mon_dispatch_postauth20;
285
286 /* Permit requests for moduli and signatures */
287 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
288 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
289 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
290
291 } else {
292 mon_dispatch = mon_dispatch_postauth15;
293 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
294 }
295 if (!no_pty_flag) {
296 monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
297 monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
298 }
299
300 for (;;)
301 monitor_read(monitor, mon_dispatch, NULL);
302}
303
304void
305monitor_sync(struct monitor *monitor)
306{
307 /* The member allocation is not visible, so sync it */
308 mm_share_sync(&monitor->m_zlib, &monitor->m_zback);
309}
310
311int
312monitor_read(struct monitor *monitor, struct mon_table *ent,
313 struct mon_table **pent)
314{
315 Buffer m;
316 int ret;
317 u_char type;
318
319 buffer_init(&m);
320
321 mm_request_receive(monitor->m_sendfd, &m);
322 type = buffer_get_char(&m);
323
324 debug3("%s: checking request %d", __FUNCTION__, type);
325
326 while (ent->f != NULL) {
327 if (ent->type == type)
328 break;
329 ent++;
330 }
331
332 if (ent->f != NULL) {
333 if (!(ent->flags & MON_PERMIT))
334 fatal("%s: unpermitted request %d", __FUNCTION__,
335 type);
336 ret = (*ent->f)(monitor->m_sendfd, &m);
337 buffer_free(&m);
338
339 /* The child may use this request only once, disable it */
340 if (ent->flags & MON_ONCE) {
341 debug2("%s: %d used once, disabling now", __FUNCTION__,
342 type);
343 ent->flags &= ~MON_PERMIT;
344 }
345
346 if (pent != NULL)
347 *pent = ent;
348
349 return ret;
350 }
351
352 fatal("%s: unsupported request: %d\n", __FUNCTION__, type);
353
354 /* NOTREACHED */
355 return (-1);
356}
357
358/* allowed key state */
359static int
360monitor_allowed_key(u_char *blob, u_int bloblen)
361{
362 /* make sure key is allowed */
363 if (key_blob == NULL || key_bloblen != bloblen ||
364 memcmp(key_blob, blob, key_bloblen))
365 return (0);
366 return (1);
367}
368
369static void
370monitor_reset_key_state(void)
371{
372 /* reset state */
373 if (key_blob != NULL)
374 xfree(key_blob);
375 if (hostbased_cuser != NULL)
376 xfree(hostbased_cuser);
377 if (hostbased_chost != NULL)
378 xfree(hostbased_chost);
379 key_blob = NULL;
380 key_bloblen = 0;
381 key_blobtype = MM_NOKEY;
382 hostbased_cuser = NULL;
383 hostbased_chost = NULL;
384}
385
386int
387mm_answer_moduli(int socket, Buffer *m)
388{
389 DH *dh;
390 int min, want, max;
391
392 min = buffer_get_int(m);
393 want = buffer_get_int(m);
394 max = buffer_get_int(m);
395
396 debug3("%s: got parameters: %d %d %d",
397 __FUNCTION__, min, want, max);
398 /* We need to check here, too, in case the child got corrupted */
399 if (max < min || want < min || max < want)
400 fatal("%s: bad parameters: %d %d %d",
401 __FUNCTION__, min, want, max);
402
403 buffer_clear(m);
404
405 dh = choose_dh(min, want, max);
406 if (dh == NULL) {
407 buffer_put_char(m, 0);
408 return (0);
409 } else {
410 /* Send first bignum */
411 buffer_put_char(m, 1);
412 buffer_put_bignum2(m, dh->p);
413 buffer_put_bignum2(m, dh->g);
414
415 DH_free(dh);
416 }
417 mm_request_send(socket, MONITOR_ANS_MODULI, m);
418 return (0);
419}
420
421int
422mm_answer_sign(int socket, Buffer *m)
423{
424 Key *key;
425 u_char *p;
426 u_char *signature;
427 u_int siglen, datlen;
428 int keyid;
429
430 debug3("%s", __FUNCTION__);
431
432 keyid = buffer_get_int(m);
433 p = buffer_get_string(m, &datlen);
434
435 if (datlen != 20)
436 fatal("%s: data length incorrect: %d", __FUNCTION__, datlen);
437
438 if ((key = get_hostkey_by_index(keyid)) == NULL)
439 fatal("%s: no hostkey from index %d", __FUNCTION__, keyid);
440 if (key_sign(key, &signature, &siglen, p, datlen) < 0)
441 fatal("%s: key_sign failed", __FUNCTION__);
442
443 debug3("%s: signature %p(%d)", __FUNCTION__, signature, siglen);
444
445 buffer_clear(m);
446 buffer_put_string(m, signature, siglen);
447
448 xfree(p);
449 xfree(signature);
450
451 mm_request_send(socket, MONITOR_ANS_SIGN, m);
452
453 /* Turn on permissions for getpwnam */
454 monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
455
456 return (0);
457}
458
459/* Retrieves the password entry and also checks if the user is permitted */
460
461int
462mm_answer_pwnamallow(int socket, Buffer *m)
463{
464 char *login;
465 struct passwd *pwent;
466 int allowed = 0;
467
468 debug3("%s", __FUNCTION__);
469
470 if (authctxt->attempt++ != 0)
471 fatal("%s: multiple attempts for getpwnam", __FUNCTION__);
472
473 login = buffer_get_string(m, NULL);
474
475 pwent = getpwnamallow(login);
476
477 authctxt->user = xstrdup(login);
478 setproctitle("%s [priv]", pwent ? login : "unknown");
479 xfree(login);
480
481 buffer_clear(m);
482
483 if (pwent == NULL) {
484 buffer_put_char(m, 0);
485 goto out;
486 }
487
488 allowed = 1;
489 authctxt->pw = pwent;
490 authctxt->valid = 1;
491
492 buffer_put_char(m, 1);
493 buffer_put_string(m, pwent, sizeof(struct passwd));
494 buffer_put_cstring(m, pwent->pw_name);
495 buffer_put_cstring(m, "*");
496 buffer_put_cstring(m, pwent->pw_gecos);
497 buffer_put_cstring(m, pwent->pw_class);
498 buffer_put_cstring(m, pwent->pw_dir);
499 buffer_put_cstring(m, pwent->pw_shell);
500
501 out:
502 debug3("%s: sending MONITOR_ANS_PWNAM: %d", __FUNCTION__, allowed);
503 mm_request_send(socket, MONITOR_ANS_PWNAM, m);
504
505 /* For SSHv1 allow authentication now */
506 if (!compat20)
507 monitor_permit_authentications(1);
508 else
509 /* Allow service/style information on the auth context */
510 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
511
512
513 return (0);
514}
515
516int
517mm_answer_authserv(int socket, Buffer *m)
518{
519 monitor_permit_authentications(1);
520
521 authctxt->service = buffer_get_string(m, NULL);
522 authctxt->style = buffer_get_string(m, NULL);
523 debug3("%s: service=%s, style=%s",
524 __FUNCTION__, authctxt->service, authctxt->style);
525
526 if (strlen(authctxt->style) == 0) {
527 xfree(authctxt->style);
528 authctxt->style = NULL;
529 }
530
531 return (0);
532}
533
534int
535mm_answer_authpassword(int socket, Buffer *m)
536{
537 static int call_count;
538 char *passwd;
539 int authenticated, plen;
540
541 passwd = buffer_get_string(m, &plen);
542 /* Only authenticate if the context is valid */
543 authenticated = authctxt->valid && auth_password(authctxt, passwd);
544 memset(passwd, 0, strlen(passwd));
545 xfree(passwd);
546
547 buffer_clear(m);
548 buffer_put_int(m, authenticated);
549
550 debug3("%s: sending result %d", __FUNCTION__, authenticated);
551 mm_request_send(socket, MONITOR_ANS_AUTHPASSWORD, m);
552
553 call_count++;
554 if (plen == 0 && call_count == 1)
555 auth_method = "none";
556 else
557 auth_method = "password";
558
559 /* Causes monitor loop to terminate if authenticated */
560 return (authenticated);
561}
562
563#ifdef BSD_AUTH
564int
565mm_answer_bsdauthquery(int socket, Buffer *m)
566{
567 char *name, *infotxt;
568 u_int numprompts;
569 u_int *echo_on;
570 char **prompts;
571 int res;
572
573 res = bsdauth_query(authctxt, &name, &infotxt, &numprompts,
574 &prompts, &echo_on);
575
576 buffer_clear(m);
577 buffer_put_int(m, res);
578 if (res != -1)
579 buffer_put_cstring(m, prompts[0]);
580
581 debug3("%s: sending challenge res: %d", __FUNCTION__, res);
582 mm_request_send(socket, MONITOR_ANS_BSDAUTHQUERY, m);
583
584 if (res != -1) {
585 xfree(name);
586 xfree(infotxt);
587 xfree(prompts);
588 xfree(echo_on);
589 }
590
591 return (0);
592}
593
594int
595mm_answer_bsdauthrespond(int socket, Buffer *m)
596{
597 char *response;
598 int authok;
599
600 if (authctxt->as == 0)
601 fatal("%s: no bsd auth session", __FUNCTION__);
602
603 response = buffer_get_string(m, NULL);
604 authok = auth_userresponse(authctxt->as, response, 0);
605 authctxt->as = NULL;
606 debug3("%s: <%s> = <%d>", __FUNCTION__, response, authok);
607 xfree(response);
608
609 buffer_clear(m);
610 buffer_put_int(m, authok);
611
612 debug3("%s: sending authenticated: %d", __FUNCTION__, authok);
613 mm_request_send(socket, MONITOR_ANS_BSDAUTHRESPOND, m);
614
615 auth_method = "bsdauth";
616
617 return (authok != 0);
618}
619#endif
620
621#ifdef SKEY
622int
623mm_answer_skeyquery(int socket, Buffer *m)
624{
625 struct skey skey;
626 char challenge[1024];
627 int res;
628
629 res = skeychallenge(&skey, authctxt->user, challenge);
630
631 buffer_clear(m);
632 buffer_put_int(m, res);
633 if (res != -1)
634 buffer_put_cstring(m, challenge);
635
636 debug3("%s: sending challenge res: %d", __FUNCTION__, res);
637 mm_request_send(socket, MONITOR_ANS_SKEYQUERY, m);
638
639 return (0);
640}
641
642int
643mm_answer_skeyrespond(int socket, Buffer *m)
644{
645 char *response;
646 int authok;
647
648 response = buffer_get_string(m, NULL);
649
650 authok = (authctxt->valid &&
651 skey_haskey(authctxt->pw->pw_name) == 0 &&
652 skey_passcheck(authctxt->pw->pw_name, response) != -1);
653
654 xfree(response);
655
656 buffer_clear(m);
657 buffer_put_int(m, authok);
658
659 debug3("%s: sending authenticated: %d", __FUNCTION__, authok);
660 mm_request_send(socket, MONITOR_ANS_SKEYRESPOND, m);
661
662 auth_method = "skey";
663
664 return (authok != 0);
665}
666#endif
667
668static void
669mm_append_debug(Buffer *m)
670{
671 if (auth_debug_init && buffer_len(&auth_debug)) {
672 debug3("%s: Appending debug messages for child", __FUNCTION__);
673 buffer_append(m, buffer_ptr(&auth_debug),
674 buffer_len(&auth_debug));
675 buffer_clear(&auth_debug);
676 }
677}
678
679int
680mm_answer_keyallowed(int socket, Buffer *m)
681{
682 Key *key;
683 u_char *cuser, *chost, *blob;
684 u_int bloblen;
685 enum mm_keytype type = 0;
686 int allowed = 0;
687
688 debug3("%s entering", __FUNCTION__);
689
690 type = buffer_get_int(m);
691 cuser = buffer_get_string(m, NULL);
692 chost = buffer_get_string(m, NULL);
693 blob = buffer_get_string(m, &bloblen);
694
695 key = key_from_blob(blob, bloblen);
696
697 if ((compat20 && type == MM_RSAHOSTKEY) ||
698 (!compat20 && type != MM_RSAHOSTKEY))
699 fatal("%s: key type and protocol mismatch", __FUNCTION__);
700
701 debug3("%s: key_from_blob: %p", __FUNCTION__, key);
702
703 if (key != NULL && authctxt->pw != NULL) {
704 switch(type) {
705 case MM_USERKEY:
706 allowed = user_key_allowed(authctxt->pw, key);
707 break;
708 case MM_HOSTKEY:
709 allowed = hostbased_key_allowed(authctxt->pw,
710 cuser, chost, key);
711 break;
712 case MM_RSAHOSTKEY:
713 key->type = KEY_RSA1; /* XXX */
714 allowed = auth_rhosts_rsa_key_allowed(authctxt->pw,
715 cuser, chost, key);
716 break;
717 default:
718 fatal("%s: unknown key type %d", __FUNCTION__, type);
719 break;
720 }
721 key_free(key);
722 }
723
724 /* clear temporarily storage (used by verify) */
725 monitor_reset_key_state();
726
727 if (allowed) {
728 /* Save temporarily for comparison in verify */
729 key_blob = blob;
730 key_bloblen = bloblen;
731 key_blobtype = type;
732 hostbased_cuser = cuser;
733 hostbased_chost = chost;
734 }
735
736 debug3("%s: key %p is %s",
737 __FUNCTION__, key, allowed ? "allowed" : "disallowed");
738
739 buffer_clear(m);
740 buffer_put_int(m, allowed);
741
742 mm_append_debug(m);
743
744 mm_request_send(socket, MONITOR_ANS_KEYALLOWED, m);
745
746 if (type == MM_RSAHOSTKEY)
747 monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
748
749 return (0);
750}
751
752static int
753monitor_valid_userblob(u_char *data, u_int datalen)
754{
755 Buffer b;
756 u_char *p;
757 u_int len;
758 int fail = 0;
759 int session_id2_len = 20 /*XXX should get from [net] */;
760
761 buffer_init(&b);
762 buffer_append(&b, data, datalen);
763
764 if (datafellows & SSH_OLD_SESSIONID) {
765 buffer_consume(&b, session_id2_len);
766 } else {
767 xfree(buffer_get_string(&b, &len));
768 if (len != session_id2_len)
769 fail++;
770 }
771 if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
772 fail++;
773 p = buffer_get_string(&b, NULL);
774 if (strcmp(authctxt->user, p) != 0) {
775 log("wrong user name passed to monitor: expected %s != %.100s",
776 authctxt->user, p);
777 fail++;
778 }
779 xfree(p);
780 buffer_skip_string(&b);
781 if (datafellows & SSH_BUG_PKAUTH) {
782 if (!buffer_get_char(&b))
783 fail++;
784 } else {
785 p = buffer_get_string(&b, NULL);
786 if (strcmp("publickey", p) != 0)
787 fail++;
788 xfree(p);
789 if (!buffer_get_char(&b))
790 fail++;
791 buffer_skip_string(&b);
792 }
793 buffer_skip_string(&b);
794 if (buffer_len(&b) != 0)
795 fail++;
796 buffer_free(&b);
797 return (fail == 0);
798}
799
800static int
801monitor_valid_hostbasedblob(u_char *data, u_int datalen, u_char *cuser,
802 u_char *chost)
803{
804 Buffer b;
805 u_char *p;
806 u_int len;
807 int fail = 0;
808 int session_id2_len = 20 /*XXX should get from [net] */;
809
810 buffer_init(&b);
811 buffer_append(&b, data, datalen);
812
813 xfree(buffer_get_string(&b, &len));
814 if (len != session_id2_len)
815 fail++;
816 if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
817 fail++;
818 p = buffer_get_string(&b, NULL);
819 if (strcmp(authctxt->user, p) != 0) {
820 log("wrong user name passed to monitor: expected %s != %.100s",
821 authctxt->user, p);
822 fail++;
823 }
824 xfree(p);
825 buffer_skip_string(&b); /* service */
826 p = buffer_get_string(&b, NULL);
827 if (strcmp(p, "hostbased") != 0)
828 fail++;
829 xfree(p);
830 buffer_skip_string(&b); /* pkalg */
831 buffer_skip_string(&b); /* pkblob */
832
833 /* verify client host, strip trailing dot if necessary */
834 p = buffer_get_string(&b, NULL);
835 if (((len = strlen(p)) > 0) && p[len - 1] == '.')
836 p[len - 1] = '\0';
837 if (strcmp(p, chost) != 0)
838 fail++;
839 xfree(p);
840
841 /* verify client user */
842 p = buffer_get_string(&b, NULL);
843 if (strcmp(p, cuser) != 0)
844 fail++;
845 xfree(p);
846
847 if (buffer_len(&b) != 0)
848 fail++;
849 buffer_free(&b);
850 return (fail == 0);
851}
852
853int
854mm_answer_keyverify(int socket, Buffer *m)
855{
856 Key *key;
857 u_char *signature, *data, *blob;
858 u_int signaturelen, datalen, bloblen;
859 int verified = 0;
860 int valid_data = 0;
861
862 blob = buffer_get_string(m, &bloblen);
863 signature = buffer_get_string(m, &signaturelen);
864 data = buffer_get_string(m, &datalen);
865
866 if (hostbased_cuser == NULL || hostbased_chost == NULL ||
867 monitor_allowed_key(blob, bloblen) == NULL)
868 fatal("%s: bad key, not previously allowed", __FUNCTION__);
869
870 key = key_from_blob(blob, bloblen);
871 if (key == NULL)
872 fatal("%s: bad public key blob", __FUNCTION__);
873
874 switch (key_blobtype) {
875 case MM_USERKEY:
876 valid_data = monitor_valid_userblob(data, datalen);
877 break;
878 case MM_HOSTKEY:
879 valid_data = monitor_valid_hostbasedblob(data, datalen,
880 hostbased_cuser, hostbased_chost);
881 break;
882 default:
883 valid_data = 0;
884 break;
885 }
886 if (!valid_data)
887 fatal("%s: bad signature data blob", __FUNCTION__);
888
889 verified = key_verify(key, signature, signaturelen, data, datalen);
890 debug3("%s: key %p signature %s",
891 __FUNCTION__, key, verified ? "verified" : "unverified");
892
893 key_free(key);
894 xfree(blob);
895 xfree(signature);
896 xfree(data);
897
898 monitor_reset_key_state();
899
900 buffer_clear(m);
901 buffer_put_int(m, verified);
902 mm_request_send(socket, MONITOR_ANS_KEYVERIFY, m);
903
904 auth_method = "publickey";
905
906 return (verified);
907}
908
909static void
910mm_record_login(Session *s, struct passwd *pw)
911{
912 socklen_t fromlen;
913 struct sockaddr_storage from;
914
915 /*
916 * Get IP address of client. If the connection is not a socket, let
917 * the address be 0.0.0.0.
918 */
919 memset(&from, 0, sizeof(from));
920 if (packet_connection_is_on_socket()) {
921 fromlen = sizeof(from);
922 if (getpeername(packet_get_connection_in(),
923 (struct sockaddr *) & from, &fromlen) < 0) {
924 debug("getpeername: %.100s", strerror(errno));
925 fatal_cleanup();
926 }
927 }
928 /* Record that there was a login on that tty from the remote host. */
929 record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid,
930 get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping),
931 (struct sockaddr *)&from);
932}
933
934static void
935mm_session_close(Session *s)
936{
937 debug3("%s: session %d pid %d", __FUNCTION__, s->self, s->pid);
938 if (s->ttyfd != -1) {
939 debug3("%s: tty %s ptyfd %d", __FUNCTION__, s->tty, s->ptyfd);
940 fatal_remove_cleanup(session_pty_cleanup2, (void *)s);
941 session_pty_cleanup2(s);
942 }
943 s->used = 0;
944}
945
946int
947mm_answer_pty(int socket, Buffer *m)
948{
949 extern struct monitor *monitor;
950 Session *s;
951 int res, fd0;
952
953 debug3("%s entering", __FUNCTION__);
954
955 buffer_clear(m);
956 s = session_new();
957 if (s == NULL)
958 goto error;
959 s->authctxt = authctxt;
960 s->pw = authctxt->pw;
961 s->pid = monitor->m_pid;
962 res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
963 if (res == 0)
964 goto error;
965 fatal_add_cleanup(session_pty_cleanup2, (void *)s);
966 pty_setowner(authctxt->pw, s->tty);
967
968 buffer_put_int(m, 1);
969 buffer_put_cstring(m, s->tty);
970 mm_request_send(socket, MONITOR_ANS_PTY, m);
971
972 mm_send_fd(socket, s->ptyfd);
973 mm_send_fd(socket, s->ttyfd);
974
975 /* We need to trick ttyslot */
976 if (dup2(s->ttyfd, 0) == -1)
977 fatal("%s: dup2", __FUNCTION__);
978
979 mm_record_login(s, authctxt->pw);
980
981 /* Now we can close the file descriptor again */
982 close(0);
983
984 /* make sure nothing uses fd 0 */
985 if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0)
986 fatal("%s: open(/dev/null): %s", __FUNCTION__, strerror(errno));
987 if (fd0 != 0)
988 error("%s: fd0 %d != 0", __FUNCTION__, fd0);
989
990 /* slave is not needed */
991 close(s->ttyfd);
992 s->ttyfd = s->ptyfd;
993 /* no need to dup() because nobody closes ptyfd */
994 s->ptymaster = s->ptyfd;
995
996 debug3("%s: tty %s ptyfd %d", __FUNCTION__, s->tty, s->ttyfd);
997
998 return (0);
999
1000 error:
1001 if (s != NULL)
1002 mm_session_close(s);
1003 buffer_put_int(m, 0);
1004 mm_request_send(socket, MONITOR_ANS_PTY, m);
1005 return (0);
1006}
1007
1008int
1009mm_answer_pty_cleanup(int socket, Buffer *m)
1010{
1011 Session *s;
1012 char *tty;
1013
1014 debug3("%s entering", __FUNCTION__);
1015
1016 tty = buffer_get_string(m, NULL);
1017 if ((s = session_by_tty(tty)) != NULL)
1018 mm_session_close(s);
1019 buffer_clear(m);
1020 xfree(tty);
1021 return (0);
1022}
1023
1024int
1025mm_answer_sesskey(int socket, Buffer *m)
1026{
1027 BIGNUM *p;
1028 int rsafail;
1029
1030 /* Turn off permissions */
1031 monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
1032
1033 if ((p = BN_new()) == NULL)
1034 fatal("%s: BN_new", __FUNCTION__);
1035
1036 buffer_get_bignum2(m, p);
1037
1038 rsafail = ssh1_session_key(p);
1039
1040 buffer_clear(m);
1041 buffer_put_int(m, rsafail);
1042 buffer_put_bignum2(m, p);
1043
1044 BN_clear_free(p);
1045
1046 mm_request_send(socket, MONITOR_ANS_SESSKEY, m);
1047
1048 /* Turn on permissions for sessid passing */
1049 monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1);
1050
1051 return (0);
1052}
1053
1054int
1055mm_answer_sessid(int socket, Buffer *m)
1056{
1057 int i;
1058
1059 debug3("%s entering", __FUNCTION__);
1060
1061 if (buffer_len(m) != 16)
1062 fatal("%s: bad ssh1 session id", __FUNCTION__);
1063 for (i = 0; i < 16; i++)
1064 session_id[i] = buffer_get_char(m);
1065
1066 /* Turn on permissions for getpwnam */
1067 monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
1068
1069 return (0);
1070}
1071
1072int
1073mm_answer_rsa_keyallowed(int socket, Buffer *m)
1074{
1075 BIGNUM *client_n;
1076 Key *key = NULL;
1077 u_char *blob = NULL;
1078 u_int blen = 0;
1079 int allowed = 0;
1080
1081 debug3("%s entering", __FUNCTION__);
1082
1083 if (authctxt->valid) {
1084 if ((client_n = BN_new()) == NULL)
1085 fatal("%s: BN_new", __FUNCTION__);
1086 buffer_get_bignum2(m, client_n);
1087 allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key);
1088 BN_clear_free(client_n);
1089 }
1090 buffer_clear(m);
1091 buffer_put_int(m, allowed);
1092
1093 /* clear temporarily storage (used by generate challenge) */
1094 monitor_reset_key_state();
1095
1096 if (allowed && key != NULL) {
1097 key->type = KEY_RSA; /* cheat for key_to_blob */
1098 if (key_to_blob(key, &blob, &blen) == 0)
1099 fatal("%s: key_to_blob failed", __FUNCTION__);
1100 buffer_put_string(m, blob, blen);
1101
1102 /* Save temporarily for comparison in verify */
1103 key_blob = blob;
1104 key_bloblen = blen;
1105 key_blobtype = MM_RSAUSERKEY;
1106 key_free(key);
1107 }
1108
1109 mm_append_debug(m);
1110
1111 mm_request_send(socket, MONITOR_ANS_RSAKEYALLOWED, m);
1112
1113 monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
1114 monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0);
1115 return (0);
1116}
1117
1118int
1119mm_answer_rsa_challenge(int socket, Buffer *m)
1120{
1121 Key *key = NULL;
1122 u_char *blob;
1123 u_int blen;
1124
1125 debug3("%s entering", __FUNCTION__);
1126
1127 if (!authctxt->valid)
1128 fatal("%s: authctxt not valid", __FUNCTION__);
1129 blob = buffer_get_string(m, &blen);
1130 if (!monitor_allowed_key(blob, blen))
1131 fatal("%s: bad key, not previously allowed", __FUNCTION__);
1132 if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
1133 fatal("%s: key type mismatch", __FUNCTION__);
1134 if ((key = key_from_blob(blob, blen)) == NULL)
1135 fatal("%s: received bad key", __FUNCTION__);
1136
1137 if (ssh1_challenge)
1138 BN_clear_free(ssh1_challenge);
1139 ssh1_challenge = auth_rsa_generate_challenge(key);
1140
1141 buffer_clear(m);
1142 buffer_put_bignum2(m, ssh1_challenge);
1143
1144 debug3("%s sending reply", __FUNCTION__);
1145 mm_request_send(socket, MONITOR_ANS_RSACHALLENGE, m);
1146
1147 monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1);
1148 return (0);
1149}
1150
1151int
1152mm_answer_rsa_response(int socket, Buffer *m)
1153{
1154 Key *key = NULL;
1155 u_char *blob, *response;
1156 u_int blen, len;
1157 int success;
1158
1159 debug3("%s entering", __FUNCTION__);
1160
1161 if (!authctxt->valid)
1162 fatal("%s: authctxt not valid", __FUNCTION__);
1163 if (ssh1_challenge == NULL)
1164 fatal("%s: no ssh1_challenge", __FUNCTION__);
1165
1166 blob = buffer_get_string(m, &blen);
1167 if (!monitor_allowed_key(blob, blen))
1168 fatal("%s: bad key, not previously allowed", __FUNCTION__);
1169 if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
1170 fatal("%s: key type mismatch: %d", __FUNCTION__, key_blobtype);
1171 if ((key = key_from_blob(blob, blen)) == NULL)
1172 fatal("%s: received bad key", __FUNCTION__);
1173 response = buffer_get_string(m, &len);
1174 if (len != 16)
1175 fatal("%s: received bad response to challenge", __FUNCTION__);
1176 success = auth_rsa_verify_response(key, ssh1_challenge, response);
1177
1178 key_free(key);
1179 xfree(response);
1180
1181 auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa";
1182
1183 /* reset state */
1184 BN_clear_free(ssh1_challenge);
1185 ssh1_challenge = NULL;
1186 monitor_reset_key_state();
1187
1188 buffer_clear(m);
1189 buffer_put_int(m, success);
1190 mm_request_send(socket, MONITOR_ANS_RSARESPONSE, m);
1191
1192 return (success);
1193}
1194
1195int
1196mm_answer_term(int socket, Buffer *req)
1197{
1198 extern struct monitor *monitor;
1199 int res, status;
1200
1201 debug3("%s: tearing down sessions", __FUNCTION__);
1202
1203 /* The child is terminating */
1204 session_destroy_all(&mm_session_close);
1205
1206 if (waitpid(monitor->m_pid, &status, 0) == -1)
1207 exit(1);
1208
1209 res = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
1210
1211 /* Terminate process */
1212 exit (res);
1213}
1214
1215void
1216monitor_apply_keystate(struct monitor *monitor)
1217{
1218 if (compat20) {
1219 set_newkeys(MODE_IN);
1220 set_newkeys(MODE_OUT);
1221 } else {
1222 u_char key[SSH_SESSION_KEY_LENGTH];
1223
1224 memset(key, 'a', sizeof(key));
1225 packet_set_protocol_flags(child_state.ssh1protoflags);
1226 packet_set_encryption_key(key, SSH_SESSION_KEY_LENGTH,
1227 child_state.ssh1cipher);
1228 }
1229
1230 packet_set_keycontext(MODE_OUT, child_state.keyout);
1231 xfree(child_state.keyout);
1232 packet_set_keycontext(MODE_IN, child_state.keyin);
1233 xfree(child_state.keyin);
1234
1235 if (!compat20) {
1236 packet_set_iv(MODE_OUT, child_state.ivout);
1237 xfree(child_state.ivout);
1238 packet_set_iv(MODE_IN, child_state.ivin);
1239 xfree(child_state.ivin);
1240 }
1241
1242 memcpy(&incoming_stream, &child_state.incoming,
1243 sizeof(incoming_stream));
1244 memcpy(&outgoing_stream, &child_state.outgoing,
1245 sizeof(outgoing_stream));
1246
1247 /* Update with new address */
1248 mm_init_compression(monitor->m_zlib);
1249
1250 /* Network I/O buffers */
1251 /* XXX inefficient for large buffers, need: buffer_init_from_string */
1252 buffer_clear(&input);
1253 buffer_append(&input, child_state.input, child_state.ilen);
1254 memset(child_state.input, 0, child_state.ilen);
1255 xfree(child_state.input);
1256
1257 buffer_clear(&output);
1258 buffer_append(&output, child_state.output, child_state.olen);
1259 memset(child_state.output, 0, child_state.olen);
1260 xfree(child_state.output);
1261}
1262
1263static Kex *
1264mm_get_kex(Buffer *m)
1265{
1266 Kex *kex;
1267 void *blob;
1268 u_int bloblen;
1269
1270 kex = xmalloc(sizeof(*kex));
1271 memset(kex, 0, sizeof(*kex));
1272 kex->session_id = buffer_get_string(m, &kex->session_id_len);
1273 kex->we_need = buffer_get_int(m);
1274 kex->server = 1;
1275 kex->hostkey_type = buffer_get_int(m);
1276 kex->kex_type = buffer_get_int(m);
1277 blob = buffer_get_string(m, &bloblen);
1278 buffer_init(&kex->my);
1279 buffer_append(&kex->my, blob, bloblen);
1280 xfree(blob);
1281 blob = buffer_get_string(m, &bloblen);
1282 buffer_init(&kex->peer);
1283 buffer_append(&kex->peer, blob, bloblen);
1284 xfree(blob);
1285 kex->done = 1;
1286 kex->flags = buffer_get_int(m);
1287 kex->client_version_string = buffer_get_string(m, NULL);
1288 kex->server_version_string = buffer_get_string(m, NULL);
1289 kex->load_host_key=&get_hostkey_by_type;
1290 kex->host_key_index=&get_hostkey_index;
1291
1292 return (kex);
1293}
1294
1295/* This function requries careful sanity checking */
1296
1297void
1298mm_get_keystate(struct monitor *monitor)
1299{
1300 Buffer m;
1301 u_char *blob, *p;
1302 u_int bloblen, plen;
1303
1304 debug3("%s: Waiting for new keys", __FUNCTION__);
1305
1306 buffer_init(&m);
1307 mm_request_receive_expect(monitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m);
1308 if (!compat20) {
1309 child_state.ssh1protoflags = buffer_get_int(&m);
1310 child_state.ssh1cipher = buffer_get_int(&m);
1311 child_state.ivout = buffer_get_string(&m,
1312 &child_state.ivoutlen);
1313 child_state.ivin = buffer_get_string(&m, &child_state.ivinlen);
1314 goto skip;
1315 } else {
1316 /* Get the Kex for rekeying */
1317 *monitor->m_pkex = mm_get_kex(&m);
1318 }
1319
1320 blob = buffer_get_string(&m, &bloblen);
1321 current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);
1322 xfree(blob);
1323
1324 debug3("%s: Waiting for second key", __FUNCTION__);
1325 blob = buffer_get_string(&m, &bloblen);
1326 current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen);
1327 xfree(blob);
1328
1329 /* Now get sequence numbers for the packets */
1330 packet_set_seqnr(MODE_OUT, buffer_get_int(&m));
1331 packet_set_seqnr(MODE_IN, buffer_get_int(&m));
1332
1333 skip:
1334 /* Get the key context */
1335 child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen);
1336 child_state.keyin = buffer_get_string(&m, &child_state.keyinlen);
1337
1338 debug3("%s: Getting compression state", __FUNCTION__);
1339 /* Get compression state */
1340 p = buffer_get_string(&m, &plen);
1341 if (plen != sizeof(child_state.outgoing))
1342 fatal("%s: bad request size", __FUNCTION__);
1343 memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing));
1344 xfree(p);
1345
1346 p = buffer_get_string(&m, &plen);
1347 if (plen != sizeof(child_state.incoming))
1348 fatal("%s: bad request size", __FUNCTION__);
1349 memcpy(&child_state.incoming, p, sizeof(child_state.incoming));
1350 xfree(p);
1351
1352 /* Network I/O buffers */
1353 debug3("%s: Getting Network I/O buffers", __FUNCTION__);
1354 child_state.input = buffer_get_string(&m, &child_state.ilen);
1355 child_state.output = buffer_get_string(&m, &child_state.olen);
1356
1357 buffer_free(&m);
1358}
1359
1360
1361/* Allocation functions for zlib */
1362void *
1363mm_zalloc(struct mm_master *mm, u_int ncount, u_int size)
1364{
1365 void *address;
1366
1367 address = mm_malloc(mm, size * ncount);
1368
1369 return (address);
1370}
1371
1372void
1373mm_zfree(struct mm_master *mm, void *address)
1374{
1375 mm_free(mm, address);
1376}
1377
1378void
1379mm_init_compression(struct mm_master *mm)
1380{
1381 outgoing_stream.zalloc = (alloc_func)mm_zalloc;
1382 outgoing_stream.zfree = (free_func)mm_zfree;
1383 outgoing_stream.opaque = mm;
1384
1385 incoming_stream.zalloc = (alloc_func)mm_zalloc;
1386 incoming_stream.zfree = (free_func)mm_zfree;
1387 incoming_stream.opaque = mm;
1388}
1389
1390/* XXX */
1391
1392#define FD_CLOSEONEXEC(x) do { \
1393 if (fcntl(x, F_SETFD, 1) == -1) \
1394 fatal("fcntl(%d, F_SETFD)", x); \
1395} while (0)
1396
1397static void
1398monitor_socketpair(int *pair)
1399{
1400 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
1401 fatal("%s: socketpair", __FUNCTION__);
1402 FD_CLOSEONEXEC(pair[0]);
1403 FD_CLOSEONEXEC(pair[1]);
1404}
1405
1406#define MM_MEMSIZE 65536
1407
1408struct monitor *
1409monitor_init(void)
1410{
1411 struct monitor *mon;
1412 int pair[2];
1413
1414 mon = xmalloc(sizeof(*mon));
1415
1416 monitor_socketpair(pair);
1417
1418 mon->m_recvfd = pair[0];
1419 mon->m_sendfd = pair[1];
1420
1421 /* Used to share zlib space across processes */
1422 mon->m_zback = mm_create(NULL, MM_MEMSIZE);
1423 mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE);
1424
1425 /* Compression needs to share state across borders */
1426 mm_init_compression(mon->m_zlib);
1427
1428 return mon;
1429}
1430
1431void
1432monitor_reinit(struct monitor *mon)
1433{
1434 int pair[2];
1435
1436 monitor_socketpair(pair);
1437
1438 mon->m_recvfd = pair[0];
1439 mon->m_sendfd = pair[1];
1440}
diff --git a/monitor.h b/monitor.h
new file mode 100644
index 000000000..da7f780b2
--- /dev/null
+++ b/monitor.h
@@ -0,0 +1,78 @@
1/*
2 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef _MONITOR_H_
27#define _MONITOR_H_
28
29enum monitor_reqtype {
30 MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
31 MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
32 MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
33 MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
34 MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD,
35 MONITOR_REQ_BSDAUTHQUERY, MONITOR_ANS_BSDAUTHQUERY,
36 MONITOR_REQ_BSDAUTHRESPOND, MONITOR_ANS_BSDAUTHRESPOND,
37 MONITOR_REQ_SKEYQUERY, MONITOR_ANS_SKEYQUERY,
38 MONITOR_REQ_SKEYRESPOND, MONITOR_ANS_SKEYRESPOND,
39 MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED,
40 MONITOR_REQ_KEYVERIFY, MONITOR_ANS_KEYVERIFY,
41 MONITOR_REQ_KEYEXPORT,
42 MONITOR_REQ_PTY, MONITOR_ANS_PTY,
43 MONITOR_REQ_PTYCLEANUP,
44 MONITOR_REQ_SESSKEY, MONITOR_ANS_SESSKEY,
45 MONITOR_REQ_SESSID,
46 MONITOR_REQ_RSAKEYALLOWED, MONITOR_ANS_RSAKEYALLOWED,
47 MONITOR_REQ_RSACHALLENGE, MONITOR_ANS_RSACHALLENGE,
48 MONITOR_REQ_RSARESPONSE, MONITOR_ANS_RSARESPONSE,
49 MONITOR_REQ_TERM,
50};
51
52struct mm_master;
53struct monitor {
54 int m_recvfd;
55 int m_sendfd;
56 struct mm_master *m_zback;
57 struct mm_master *m_zlib;
58 struct Kex **m_pkex;
59 int m_pid;
60};
61
62struct monitor *monitor_init(void);
63void monitor_reinit(struct monitor *);
64void monitor_sync(struct monitor *);
65
66struct Authctxt;
67struct Authctxt *monitor_child_preauth(struct monitor *);
68void monitor_child_postauth(struct monitor *);
69
70struct mon_table;
71int monitor_read(struct monitor*, struct mon_table *, struct mon_table **);
72
73/* Prototypes for request sending and receiving */
74void mm_request_send(int, enum monitor_reqtype, Buffer *);
75void mm_request_receive(int, Buffer *);
76void mm_request_receive_expect(int, enum monitor_reqtype, Buffer *);
77
78#endif /* _MONITOR_H_ */
diff --git a/monitor_fdpass.c b/monitor_fdpass.c
new file mode 100644
index 000000000..7785535bb
--- /dev/null
+++ b/monitor_fdpass.c
@@ -0,0 +1,86 @@
1/*
2 * Copyright 2001 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "includes.h"
27RCSID("$OpenBSD: monitor_fdpass.c,v 1.1 2002/03/18 17:27:22 provos Exp $");
28
29#include <sys/uio.h>
30
31#include "log.h"
32#include "monitor_fdpass.h"
33
34void
35mm_send_fd(int socket, int fd)
36{
37 struct msghdr msg;
38 char tmp[CMSG_SPACE(sizeof(int))];
39 struct cmsghdr *cmsg;
40 struct iovec vec;
41 char ch;
42
43 memset(&msg, 0, sizeof(msg));
44 msg.msg_control = (caddr_t)tmp;
45 msg.msg_controllen = CMSG_LEN(sizeof(int));
46 cmsg = CMSG_FIRSTHDR(&msg);
47 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
48 cmsg->cmsg_level = SOL_SOCKET;
49 cmsg->cmsg_type = SCM_RIGHTS;
50 *(int *)CMSG_DATA(cmsg) = fd;
51
52 vec.iov_base = &ch;
53 vec.iov_len = 1;
54 msg.msg_iov = &vec;
55 msg.msg_iovlen = 1;
56
57 if (sendmsg(socket, &msg, 0) == -1)
58 fatal("%s: sendmsg(%d)", __FUNCTION__, fd);
59}
60
61int
62mm_receive_fd(int socket)
63{
64 struct msghdr msg;
65 char tmp[CMSG_SPACE(sizeof(int))];
66 struct cmsghdr *cmsg;
67 struct iovec vec;
68 char ch;
69
70 memset(&msg, 0, sizeof(msg));
71 vec.iov_base = &ch;
72 vec.iov_len = 1;
73 msg.msg_iov = &vec;
74 msg.msg_iovlen = 1;
75 msg.msg_control = tmp;
76 msg.msg_controllen = sizeof(tmp);
77
78 if (recvmsg(socket, &msg, 0) == -1)
79 fatal("%s: recvmsg", __FUNCTION__);
80
81 cmsg = CMSG_FIRSTHDR(&msg);
82 if (cmsg->cmsg_type != SCM_RIGHTS)
83 fatal("%s: expected type %d got %d", __FUNCTION__,
84 SCM_RIGHTS, cmsg->cmsg_type);
85 return (*(int *)CMSG_DATA(cmsg));
86}
diff --git a/monitor_fdpass.h b/monitor_fdpass.h
new file mode 100644
index 000000000..cb6b71c93
--- /dev/null
+++ b/monitor_fdpass.h
@@ -0,0 +1,32 @@
1/*
2 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef _MM_FDPASS_H_
27#define _MM_FDPASS_H_
28
29void mm_send_fd(int, int);
30int mm_receive_fd(int);
31
32#endif /* _MM_FDPASS_H_ */
diff --git a/monitor_mm.c b/monitor_mm.c
new file mode 100644
index 000000000..bce98c93c
--- /dev/null
+++ b/monitor_mm.c
@@ -0,0 +1,329 @@
1/*
2 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "includes.h"
27RCSID("$OpenBSD: monitor_mm.c,v 1.3 2002/03/19 10:41:32 markus Exp $");
28
29#include <sys/mman.h>
30
31#include "ssh.h"
32#include "xmalloc.h"
33#include "log.h"
34#include "monitor_mm.h"
35
36static int
37mm_compare(struct mm_share *a, struct mm_share *b)
38{
39 return ((char *)a->address - (char *)b->address);
40}
41
42RB_GENERATE(mmtree, mm_share, next, mm_compare)
43
44static struct mm_share *
45mm_make_entry(struct mm_master *mm, struct mmtree *head,
46 void *address, size_t size)
47{
48 struct mm_share *tmp, *tmp2;
49
50 if (mm->mmalloc == NULL)
51 tmp = xmalloc(sizeof(struct mm_share));
52 else
53 tmp = mm_xmalloc(mm->mmalloc, sizeof(struct mm_share));
54 tmp->address = address;
55 tmp->size = size;
56
57 tmp2 = RB_INSERT(mmtree, head, tmp);
58 if (tmp2 != NULL)
59 fatal("mm_make_entry(%p): double address %p->%p(%d)",
60 mm, tmp2, address, size);
61
62 return (tmp);
63}
64
65/* Creates a shared memory area of a certain size */
66
67struct mm_master *
68mm_create(struct mm_master *mmalloc, size_t size)
69{
70 void *address;
71 struct mm_master *mm;
72
73 if (mmalloc == NULL)
74 mm = xmalloc(sizeof(struct mm_master));
75 else
76 mm = mm_xmalloc(mmalloc, sizeof(struct mm_master));
77
78 /*
79 * If the memory map has a mm_master it can be completely
80 * shared including authentication between the child
81 * and the client.
82 */
83 mm->mmalloc = mmalloc;
84
85 address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_ANON|MAP_SHARED,
86 -1, 0);
87 if (address == MAP_FAILED)
88 fatal("mmap(%d)", size);
89
90 mm->address = address;
91 mm->size = size;
92
93 RB_INIT(&mm->rb_free);
94 RB_INIT(&mm->rb_allocated);
95
96 mm_make_entry(mm, &mm->rb_free, address, size);
97
98 return (mm);
99}
100
101/* Frees either the allocated or the free list */
102
103static void
104mm_freelist(struct mm_master *mmalloc, struct mmtree *head)
105{
106 struct mm_share *mms, *next;
107
108 for (mms = RB_ROOT(head); mms; mms = next) {
109 next = RB_NEXT(mmtree, head, mms);
110 RB_REMOVE(mmtree, head, mms);
111 if (mmalloc == NULL)
112 xfree(mms);
113 else
114 mm_free(mmalloc, mms);
115 }
116}
117
118/* Destroys a memory mapped area */
119
120void
121mm_destroy(struct mm_master *mm)
122{
123 mm_freelist(mm->mmalloc, &mm->rb_free);
124 mm_freelist(mm->mmalloc, &mm->rb_allocated);
125
126 if (munmap(mm->address, mm->size) == -1)
127 fatal("munmap(%p, %d)", mm->address, mm->size);
128 if (mm->mmalloc == NULL)
129 xfree(mm);
130 else
131 mm_free(mm->mmalloc, mm);
132}
133
134void *
135mm_xmalloc(struct mm_master *mm, size_t size)
136{
137 void *address;
138
139 address = mm_malloc(mm, size);
140 if (address == NULL)
141 fatal("%s: mm_malloc(%d)", __FUNCTION__, size);
142 return (address);
143}
144
145
146/* Allocates data from a memory mapped area */
147
148void *
149mm_malloc(struct mm_master *mm, size_t size)
150{
151 struct mm_share *mms, *tmp;
152
153 if (size == 0)
154 fatal("mm_malloc: try to allocate 0 space");
155
156 size = ((size + MM_MINSIZE - 1) / MM_MINSIZE) * MM_MINSIZE;
157
158 RB_FOREACH(mms, mmtree, &mm->rb_free) {
159 if (mms->size >= size)
160 break;
161 }
162
163 if (mms == NULL)
164 return (NULL);
165
166 /* Debug */
167 memset(mms->address, 0xd0, size);
168
169 tmp = mm_make_entry(mm, &mm->rb_allocated, mms->address, size);
170
171 /* Does not change order in RB tree */
172 mms->size -= size;
173 mms->address = (u_char *)mms->address + size;
174
175 if (mms->size == 0) {
176 RB_REMOVE(mmtree, &mm->rb_free, mms);
177 if (mm->mmalloc == NULL)
178 xfree(mms);
179 else
180 mm_free(mm->mmalloc, mms);
181 }
182
183 return (tmp->address);
184}
185
186/* Frees memory in a memory mapped area */
187
188void
189mm_free(struct mm_master *mm, void *address)
190{
191 struct mm_share *mms, *prev, tmp;
192
193 tmp.address = address;
194 mms = RB_FIND(mmtree, &mm->rb_allocated, &tmp);
195 if (mms == NULL)
196 fatal("mm_free(%p): can not find %p", mm, address);
197
198 /* Debug */
199 memset(mms->address, 0xd0, mms->size);
200
201 /* Remove from allocated list and insert in free list */
202 RB_REMOVE(mmtree, &mm->rb_allocated, mms);
203 if (RB_INSERT(mmtree, &mm->rb_free, mms) != NULL)
204 fatal("mm_free(%p): double address %p", mm, address);
205
206 /* Find previous entry */
207 prev = mms;
208 if (RB_LEFT(prev, next)) {
209 prev = RB_LEFT(prev, next);
210 while (RB_RIGHT(prev, next))
211 prev = RB_RIGHT(prev, next);
212 } else {
213 if (RB_PARENT(prev, next) &&
214 (prev == RB_RIGHT(RB_PARENT(prev, next), next)))
215 prev = RB_PARENT(prev, next);
216 else {
217 while (RB_PARENT(prev, next) &&
218 (prev == RB_LEFT(RB_PARENT(prev, next), next)))
219 prev = RB_PARENT(prev, next);
220 prev = RB_PARENT(prev, next);
221 }
222 }
223
224 /* Check if range does not overlap */
225 if (prev != NULL && MM_ADDRESS_END(prev) > address)
226 fatal("mm_free: memory corruption: %p(%d) > %p",
227 prev->address, prev->size, address);
228
229 /* See if we can merge backwards */
230 if (prev != NULL && MM_ADDRESS_END(prev) == address) {
231 prev->size += mms->size;
232 RB_REMOVE(mmtree, &mm->rb_free, mms);
233 if (mm->mmalloc == NULL)
234 xfree(mms);
235 else
236 mm_free(mm->mmalloc, mms);
237 } else
238 prev = mms;
239
240 if (prev == NULL)
241 return;
242
243 /* Check if we can merge forwards */
244 mms = RB_NEXT(mmtree, &mm->rb_free, prev);
245 if (mms == NULL)
246 return;
247
248 if (MM_ADDRESS_END(prev) > mms->address)
249 fatal("mm_free: memory corruption: %p < %p(%d)",
250 mms->address, prev->address, prev->size);
251 if (MM_ADDRESS_END(prev) != mms->address)
252 return;
253
254 prev->size += mms->size;
255 RB_REMOVE(mmtree, &mm->rb_free, mms);
256
257 if (mm->mmalloc == NULL)
258 xfree(mms);
259 else
260 mm_free(mm->mmalloc, mms);
261}
262
263static void
264mm_sync_list(struct mmtree *oldtree, struct mmtree *newtree,
265 struct mm_master *mm, struct mm_master *mmold)
266{
267 struct mm_master *mmalloc = mm->mmalloc;
268 struct mm_share *mms, *new;
269
270 /* Sync free list */
271 RB_FOREACH(mms, mmtree, oldtree) {
272 /* Check the values */
273 mm_memvalid(mmold, mms, sizeof(struct mm_share));
274 mm_memvalid(mm, mms->address, mms->size);
275
276 new = mm_xmalloc(mmalloc, sizeof(struct mm_share));
277 memcpy(new, mms, sizeof(struct mm_share));
278 RB_INSERT(mmtree, newtree, new);
279 }
280}
281
282void
283mm_share_sync(struct mm_master **pmm, struct mm_master **pmmalloc)
284{
285 struct mm_master *mm;
286 struct mm_master *mmalloc;
287 struct mm_master *mmold;
288 struct mmtree rb_free, rb_allocated;
289
290 debug3("%s: Share sync", __FUNCTION__);
291
292 mm = *pmm;
293 mmold = mm->mmalloc;
294 mm_memvalid(mmold, mm, sizeof(*mm));
295
296 mmalloc = mm_create(NULL, mm->size);
297 mm = mm_xmalloc(mmalloc, sizeof(struct mm_master));
298 memcpy(mm, *pmm, sizeof(struct mm_master));
299 mm->mmalloc = mmalloc;
300
301 rb_free = mm->rb_free;
302 rb_allocated = mm->rb_allocated;
303
304 RB_INIT(&mm->rb_free);
305 RB_INIT(&mm->rb_allocated);
306
307 mm_sync_list(&rb_free, &mm->rb_free, mm, mmold);
308 mm_sync_list(&rb_allocated, &mm->rb_allocated, mm, mmold);
309
310 mm_destroy(mmold);
311
312 *pmm = mm;
313 *pmmalloc = mmalloc;
314
315 debug3("%s: Share sync end", __FUNCTION__);
316}
317
318void
319mm_memvalid(struct mm_master *mm, void *address, size_t size)
320{
321 void *end = (u_char *)address + size;
322
323 if (address < mm->address)
324 fatal("mm_memvalid: address too small: %p", address);
325 if (end < address)
326 fatal("mm_memvalid: end < address: %p < %p", end, address);
327 if (end > (void *)((u_char *)mm->address + mm->size))
328 fatal("mm_memvalid: address too large: %p", address);
329}
diff --git a/monitor_mm.h b/monitor_mm.h
new file mode 100644
index 000000000..43442609c
--- /dev/null
+++ b/monitor_mm.h
@@ -0,0 +1,64 @@
1/*
2 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef _MM_H_
27#define _MM_H_
28#include <sys/tree.h>
29
30struct mm_share {
31 RB_ENTRY(mm_share) next;
32 void *address;
33 size_t size;
34};
35
36struct mm_master {
37 RB_HEAD(mmtree, mm_share) rb_free;
38 struct mmtree rb_allocated;
39 void *address;
40 size_t size;
41
42 struct mm_master *mmalloc; /* Used to completely share */
43
44 int write; /* used to writing to other party */
45 int read; /* used for reading from other party */
46};
47
48RB_PROTOTYPE(mmtree, mm_share, next, mm_compare)
49
50#define MM_MINSIZE 128
51
52#define MM_ADDRESS_END(x) (void *)((u_char *)(x)->address + (x)->size)
53
54struct mm_master *mm_create(struct mm_master *, size_t);
55void mm_destroy(struct mm_master *);
56
57void mm_share_sync(struct mm_master **, struct mm_master **);
58
59void *mm_malloc(struct mm_master *, size_t);
60void *mm_xmalloc(struct mm_master *, size_t);
61void mm_free(struct mm_master *, void *);
62
63void mm_memvalid(struct mm_master *, void *, size_t);
64#endif /* _MM_H_ */
diff --git a/monitor_wrap.c b/monitor_wrap.c
new file mode 100644
index 000000000..e477cff25
--- /dev/null
+++ b/monitor_wrap.c
@@ -0,0 +1,894 @@
1/*
2 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
3 * Copyright 2002 Markus Friedl <markus@openbsd.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "includes.h"
28RCSID("$OpenBSD: monitor_wrap.c,v 1.4 2002/03/19 14:27:39 markus Exp $");
29
30#include <openssl/bn.h>
31#include <openssl/dh.h>
32
33#include "ssh.h"
34#include "dh.h"
35#include "kex.h"
36#include "auth.h"
37#include "buffer.h"
38#include "bufaux.h"
39#include "packet.h"
40#include "mac.h"
41#include "log.h"
42#include "zlib.h"
43#include "monitor.h"
44#include "monitor_wrap.h"
45#include "xmalloc.h"
46#include "atomicio.h"
47#include "monitor_fdpass.h"
48#include "getput.h"
49
50#include "auth.h"
51#include "channels.h"
52#include "session.h"
53
54/* Imports */
55extern int compat20;
56extern Newkeys *newkeys[];
57extern z_stream incoming_stream;
58extern z_stream outgoing_stream;
59extern struct monitor *monitor;
60extern Buffer input, output;
61
62void
63mm_request_send(int socket, enum monitor_reqtype type, Buffer *m)
64{
65 u_char buf[5];
66 u_int mlen = buffer_len(m);
67
68 debug3("%s entering: type %d", __FUNCTION__, type);
69
70 PUT_32BIT(buf, mlen + 1);
71 buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */
72 if (atomicio(write, socket, buf, sizeof(buf)) != sizeof(buf))
73 fatal("%s: write", __FUNCTION__);
74 if (atomicio(write, socket, buffer_ptr(m), mlen) != mlen)
75 fatal("%s: write", __FUNCTION__);
76}
77
78void
79mm_request_receive(int socket, Buffer *m)
80{
81 u_char buf[4];
82 ssize_t res;
83 u_int msg_len;
84
85 debug3("%s entering", __FUNCTION__);
86
87 res = atomicio(read, socket, buf, sizeof(buf));
88 if (res != sizeof(buf)) {
89 if (res == 0)
90 fatal_cleanup();
91 fatal("%s: read: %d", __FUNCTION__, res);
92 }
93 msg_len = GET_32BIT(buf);
94 if (msg_len > 256 * 1024)
95 fatal("%s: read: bad msg_len %d", __FUNCTION__, msg_len);
96 buffer_clear(m);
97 buffer_append_space(m, msg_len);
98 res = atomicio(read, socket, buffer_ptr(m), msg_len);
99 if (res != msg_len)
100 fatal("%s: read: %d != msg_len", __FUNCTION__, res);
101}
102
103void
104mm_request_receive_expect(int socket, enum monitor_reqtype type, Buffer *m)
105{
106 u_char rtype;
107
108 debug3("%s entering: type %d", __FUNCTION__, type);
109
110 mm_request_receive(socket, m);
111 rtype = buffer_get_char(m);
112 if (rtype != type)
113 fatal("%s: read: rtype %d != type %d", __FUNCTION__,
114 rtype, type);
115}
116
117DH *
118mm_choose_dh(int min, int nbits, int max)
119{
120 BIGNUM *p, *g;
121 int success = 0;
122 Buffer m;
123
124 buffer_init(&m);
125 buffer_put_int(&m, min);
126 buffer_put_int(&m, nbits);
127 buffer_put_int(&m, max);
128
129 mm_request_send(monitor->m_recvfd, MONITOR_REQ_MODULI, &m);
130
131 debug3("%s: waiting for MONITOR_ANS_MODULI", __FUNCTION__);
132 mm_request_receive_expect(monitor->m_recvfd, MONITOR_ANS_MODULI, &m);
133
134 success = buffer_get_char(&m);
135 if (success == 0)
136 fatal("%s: MONITOR_ANS_MODULI failed", __FUNCTION__);
137
138 if ((p = BN_new()) == NULL)
139 fatal("%s: BN_new failed", __FUNCTION__);
140 if ((g = BN_new()) == NULL)
141 fatal("%s: BN_new failed", __FUNCTION__);
142 buffer_get_bignum2(&m, p);
143 buffer_get_bignum2(&m, g);
144
145 debug3("%s: remaining %d", __FUNCTION__, buffer_len(&m));
146 buffer_free(&m);
147
148 return (dh_new_group(g, p));
149}
150
151int
152mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen)
153{
154 Kex *kex = *monitor->m_pkex;
155 Buffer m;
156
157 debug3("%s entering", __FUNCTION__);
158
159 buffer_init(&m);
160 buffer_put_int(&m, kex->host_key_index(key));
161 buffer_put_string(&m, data, datalen);
162
163 mm_request_send(monitor->m_recvfd, MONITOR_REQ_SIGN, &m);
164
165 debug3("%s: waiting for MONITOR_ANS_SIGN", __FUNCTION__);
166 mm_request_receive_expect(monitor->m_recvfd, MONITOR_ANS_SIGN, &m);
167 *sigp = buffer_get_string(&m, lenp);
168 buffer_free(&m);
169
170 return (0);
171}
172
173struct passwd *
174mm_getpwnamallow(const char *login)
175{
176 Buffer m;
177 struct passwd *pw;
178 u_int pwlen;
179
180 debug3("%s entering", __FUNCTION__);
181
182 buffer_init(&m);
183 buffer_put_cstring(&m, login);
184
185 mm_request_send(monitor->m_recvfd, MONITOR_REQ_PWNAM, &m);
186
187 debug3("%s: waiting for MONITOR_ANS_PWNAM", __FUNCTION__);
188 mm_request_receive_expect(monitor->m_recvfd, MONITOR_ANS_PWNAM, &m);
189
190 if (buffer_get_char(&m) == 0) {
191 buffer_free(&m);
192 return (NULL);
193 }
194 pw = buffer_get_string(&m, &pwlen);
195 if (pwlen != sizeof(struct passwd))
196 fatal("%s: struct passwd size mismatch", __FUNCTION__);
197 pw->pw_name = buffer_get_string(&m, NULL);
198 pw->pw_passwd = buffer_get_string(&m, NULL);
199 pw->pw_gecos = buffer_get_string(&m, NULL);
200 pw->pw_class = buffer_get_string(&m, NULL);
201 pw->pw_dir = buffer_get_string(&m, NULL);
202 pw->pw_shell = buffer_get_string(&m, NULL);
203 buffer_free(&m);
204
205 return (pw);
206}
207
208/* Inform the privileged process about service and style */
209
210void
211mm_inform_authserv(char *service, char *style)
212{
213 Buffer m;
214
215 debug3("%s entering", __FUNCTION__);
216
217 buffer_init(&m);
218 buffer_put_cstring(&m, service);
219 buffer_put_cstring(&m, style ? style : "");
220
221 mm_request_send(monitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
222
223 buffer_free(&m);
224}
225
226/* Do the password authentication */
227int
228mm_auth_password(Authctxt *authctxt, char *password)
229{
230 Buffer m;
231 int authenticated = 0;
232
233 debug3("%s entering", __FUNCTION__);
234
235 buffer_init(&m);
236 buffer_put_cstring(&m, password);
237 mm_request_send(monitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
238
239 debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __FUNCTION__);
240 mm_request_receive_expect(monitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
241
242 authenticated = buffer_get_int(&m);
243
244 buffer_free(&m);
245
246 debug3("%s: user %sauthenticated",
247 __FUNCTION__, authenticated ? "" : "not ");
248 return (authenticated);
249}
250
251int
252mm_user_key_allowed(struct passwd *pw, Key *key)
253{
254 return (mm_key_allowed(MM_USERKEY, NULL, NULL, key));
255}
256
257int
258mm_hostbased_key_allowed(struct passwd *pw, char *user, char *host,
259 Key *key)
260{
261 return (mm_key_allowed(MM_HOSTKEY, user, host, key));
262}
263
264int
265mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
266 char *host, Key *key)
267{
268 int ret;
269
270 key->type = KEY_RSA; /* XXX hack for key_to_blob */
271 ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key);
272 key->type = KEY_RSA1;
273 return (ret);
274}
275
276static void
277mm_send_debug(Buffer *m)
278{
279 char *msg;
280
281 while (buffer_len(m)) {
282 msg = buffer_get_string(m, NULL);
283 debug3("%s: Sending debug: %s", __FUNCTION__, msg);
284 packet_send_debug("%s", msg);
285 xfree(msg);
286 }
287}
288
289int
290mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
291{
292 Buffer m;
293 u_char *blob;
294 u_int len;
295 int allowed = 0;
296
297 debug3("%s entering", __FUNCTION__);
298
299 /* Convert the key to a blob and the pass it over */
300 if (!key_to_blob(key, &blob, &len))
301 return (0);
302
303 buffer_init(&m);
304 buffer_put_int(&m, type);
305 buffer_put_cstring(&m, user ? user : "");
306 buffer_put_cstring(&m, host ? host : "");
307 buffer_put_string(&m, blob, len);
308 xfree(blob);
309
310 mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
311
312 debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __FUNCTION__);
313 mm_request_receive_expect(monitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
314
315 allowed = buffer_get_int(&m);
316
317 /* Send potential debug messages */
318 mm_send_debug(&m);
319
320 buffer_free(&m);
321
322 return (allowed);
323}
324
325/*
326 * This key verify needs to send the key type along, because the
327 * privileged parent makes the decision if the key is allowed
328 * for authentication.
329 */
330
331int
332mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
333{
334 Buffer m;
335 u_char *blob;
336 u_int len;
337 int verified = 0;
338
339 debug3("%s entering", __FUNCTION__);
340
341 /* Convert the key to a blob and the pass it over */
342 if (!key_to_blob(key, &blob, &len))
343 return (0);
344
345 buffer_init(&m);
346 buffer_put_string(&m, blob, len);
347 buffer_put_string(&m, sig, siglen);
348 buffer_put_string(&m, data, datalen);
349 xfree(blob);
350
351 mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
352
353 debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __FUNCTION__);
354 mm_request_receive_expect(monitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
355
356 verified = buffer_get_int(&m);
357
358 buffer_free(&m);
359
360 return (verified);
361}
362
363/* Export key state after authentication */
364Newkeys *
365mm_newkeys_from_blob(u_char *blob, int blen)
366{
367 Buffer b;
368 u_int len;
369 Newkeys *newkey = NULL;
370 Enc *enc;
371 Mac *mac;
372 Comp *comp;
373
374 debug3("%s: %p(%d)", __FUNCTION__, blob, blen);
375#ifdef DEBUG_PK
376 dump_base64(stderr, blob, blen);
377#endif
378 buffer_init(&b);
379 buffer_append(&b, blob, blen);
380
381 newkey = xmalloc(sizeof(*newkey));
382 enc = &newkey->enc;
383 mac = &newkey->mac;
384 comp = &newkey->comp;
385
386 /* Enc structure */
387 enc->name = buffer_get_string(&b, NULL);
388 buffer_get(&b, &enc->cipher, sizeof(enc->cipher));
389 enc->enabled = buffer_get_int(&b);
390 enc->block_size = buffer_get_int(&b);
391 enc->key = buffer_get_string(&b, &enc->key_len);
392 enc->iv = buffer_get_string(&b, &len);
393 if (len != enc->block_size)
394 fatal("%s: bad ivlen: expected %d != %d", __FUNCTION__,
395 enc->block_size, len);
396
397 if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher)
398 fatal("%s: bad cipher name %s or pointer %p", __FUNCTION__,
399 enc->name, enc->cipher);
400
401 /* Mac structure */
402 mac->name = buffer_get_string(&b, NULL);
403 if (mac->name == NULL || mac_init(mac, mac->name) == -1)
404 fatal("%s: can not init mac %s", __FUNCTION__, mac->name);
405 mac->enabled = buffer_get_int(&b);
406 mac->key = buffer_get_string(&b, &len);
407 if (len > mac->key_len)
408 fatal("%s: bad mac key lenght: %d > %d", __FUNCTION__, len,
409 mac->key_len);
410 mac->key_len = len;
411
412 /* Comp structure */
413 comp->type = buffer_get_int(&b);
414 comp->enabled = buffer_get_int(&b);
415 comp->name = buffer_get_string(&b, NULL);
416
417 len = buffer_len(&b);
418 if (len != 0)
419 error("newkeys_from_blob: remaining bytes in blob %d", len);
420 buffer_free(&b);
421 return (newkey);
422}
423
424int
425mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
426{
427 Buffer b;
428 int len;
429 u_char *buf;
430 Enc *enc;
431 Mac *mac;
432 Comp *comp;
433 Newkeys *newkey = newkeys[mode];
434
435 debug3("%s: converting %p", __FUNCTION__, newkey);
436
437 if (newkey == NULL) {
438 error("%s: newkey == NULL", __FUNCTION__);
439 return 0;
440 }
441 enc = &newkey->enc;
442 mac = &newkey->mac;
443 comp = &newkey->comp;
444
445 buffer_init(&b);
446 /* Enc structure */
447 buffer_put_cstring(&b, enc->name);
448 /* The cipher struct is constant and shared, you export pointer */
449 buffer_append(&b, &enc->cipher, sizeof(enc->cipher));
450 buffer_put_int(&b, enc->enabled);
451 buffer_put_int(&b, enc->block_size);
452 buffer_put_string(&b, enc->key, enc->key_len);
453 packet_get_keyiv(mode, enc->iv, enc->block_size);
454 buffer_put_string(&b, enc->iv, enc->block_size);
455
456 /* Mac structure */
457 buffer_put_cstring(&b, mac->name);
458 buffer_put_int(&b, mac->enabled);
459 buffer_put_string(&b, mac->key, mac->key_len);
460
461 /* Comp structure */
462 buffer_put_int(&b, comp->type);
463 buffer_put_int(&b, comp->enabled);
464 buffer_put_cstring(&b, comp->name);
465
466 len = buffer_len(&b);
467 buf = xmalloc(len);
468 memcpy(buf, buffer_ptr(&b), len);
469 memset(buffer_ptr(&b), 0, len);
470 buffer_free(&b);
471 if (lenp != NULL)
472 *lenp = len;
473 if (blobp != NULL)
474 *blobp = buf;
475 return len;
476}
477
478static void
479mm_send_kex(Buffer *m, Kex *kex)
480{
481 buffer_put_string(m, kex->session_id, kex->session_id_len);
482 buffer_put_int(m, kex->we_need);
483 buffer_put_int(m, kex->hostkey_type);
484 buffer_put_int(m, kex->kex_type);
485 buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my));
486 buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer));
487 buffer_put_int(m, kex->flags);
488 buffer_put_cstring(m, kex->client_version_string);
489 buffer_put_cstring(m, kex->server_version_string);
490}
491
492void
493mm_send_keystate(struct monitor *monitor)
494{
495 Buffer m;
496 u_char *blob, *p;
497 u_int bloblen, plen;
498
499 buffer_init(&m);
500
501 if (!compat20) {
502 u_char iv[24];
503 int ivlen;
504
505 buffer_put_int(&m, packet_get_protocol_flags());
506
507 buffer_put_int(&m, packet_get_ssh1_cipher());
508
509 debug3("%s: Sending ssh1 IV", __FUNCTION__);
510 ivlen = packet_get_keyiv_len(MODE_OUT);
511 packet_get_keyiv(MODE_OUT, iv, ivlen);
512 buffer_put_string(&m, iv, ivlen);
513 ivlen = packet_get_keyiv_len(MODE_OUT);
514 packet_get_keyiv(MODE_IN, iv, ivlen);
515 buffer_put_string(&m, iv, ivlen);
516 goto skip;
517 } else {
518 /* Kex for rekeying */
519 mm_send_kex(&m, *monitor->m_pkex);
520 }
521
522 debug3("%s: Sending new keys: %p %p",
523 __FUNCTION__, newkeys[MODE_OUT], newkeys[MODE_IN]);
524
525 /* Keys from Kex */
526 if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen))
527 fatal("%s: conversion of newkeys failed", __FUNCTION__);
528
529 buffer_put_string(&m, blob, bloblen);
530 xfree(blob);
531
532 if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen))
533 fatal("%s: conversion of newkeys failed", __FUNCTION__);
534
535 buffer_put_string(&m, blob, bloblen);
536 xfree(blob);
537
538 buffer_put_int(&m, packet_get_seqnr(MODE_OUT));
539 buffer_put_int(&m, packet_get_seqnr(MODE_IN));
540
541 debug3("%s: New keys have been sent", __FUNCTION__);
542 skip:
543 /* More key context */
544 plen = packet_get_keycontext(MODE_OUT, NULL);
545 p = xmalloc(plen+1);
546 packet_get_keycontext(MODE_OUT, p);
547 buffer_put_string(&m, p, plen);
548 xfree(p);
549
550 plen = packet_get_keycontext(MODE_IN, NULL);
551 p = xmalloc(plen+1);
552 packet_get_keycontext(MODE_IN, p);
553 buffer_put_string(&m, p, plen);
554 xfree(p);
555
556 /* Compression state */
557 debug3("%s: Sending compression state", __FUNCTION__);
558 buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream));
559 buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream));
560
561 /* Network I/O buffers */
562 buffer_put_string(&m, buffer_ptr(&input), buffer_len(&input));
563 buffer_put_string(&m, buffer_ptr(&output), buffer_len(&output));
564
565 mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m);
566 debug3("%s: Finished sending state", __FUNCTION__);
567
568 buffer_free(&m);
569}
570
571int
572mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
573{
574 Buffer m;
575 u_char *p;
576 int success = 0;
577
578 buffer_init(&m);
579 mm_request_send(monitor->m_recvfd, MONITOR_REQ_PTY, &m);
580
581 debug3("%s: waiting for MONITOR_ANS_PTY", __FUNCTION__);
582 mm_request_receive_expect(monitor->m_recvfd, MONITOR_ANS_PTY, &m);
583
584 success = buffer_get_int(&m);
585 if (success == 0) {
586 debug3("%s: pty alloc failed", __FUNCTION__);
587 buffer_free(&m);
588 return (0);
589 }
590 p = buffer_get_string(&m, NULL);
591 buffer_free(&m);
592
593 strlcpy(namebuf, p, namebuflen); /* Possible truncation */
594 xfree(p);
595
596 *ptyfd = mm_receive_fd(monitor->m_recvfd);
597 *ttyfd = mm_receive_fd(monitor->m_recvfd);
598
599 /* Success */
600 return (1);
601}
602
603void
604mm_session_pty_cleanup2(void *session)
605{
606 Session *s = session;
607 Buffer m;
608
609 if (s->ttyfd == -1)
610 return;
611 buffer_init(&m);
612 buffer_put_cstring(&m, s->tty);
613 mm_request_send(monitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
614 buffer_free(&m);
615
616 /* closed dup'ed master */
617 if (close(s->ptymaster) < 0)
618 error("close(s->ptymaster): %s", strerror(errno));
619
620 /* unlink pty from session */
621 s->ttyfd = -1;
622}
623
624/* Request process termination */
625
626void
627mm_terminate(void)
628{
629 Buffer m;
630
631 buffer_init(&m);
632 mm_request_send(monitor->m_recvfd, MONITOR_REQ_TERM, &m);
633 buffer_free(&m);
634}
635
636int
637mm_ssh1_session_key(BIGNUM *num)
638{
639 int rsafail;
640 Buffer m;
641
642 buffer_init(&m);
643 buffer_put_bignum2(&m, num);
644 mm_request_send(monitor->m_recvfd, MONITOR_REQ_SESSKEY, &m);
645
646 mm_request_receive_expect(monitor->m_recvfd, MONITOR_ANS_SESSKEY, &m);
647
648 rsafail = buffer_get_int(&m);
649 buffer_get_bignum2(&m, num);
650
651 buffer_free(&m);
652
653 return (rsafail);
654}
655
656static void
657mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
658 char ***prompts, u_int **echo_on)
659{
660 *name = xstrdup("");
661 *infotxt = xstrdup("");
662 *numprompts = 1;
663 *prompts = xmalloc(*numprompts * sizeof(char*));
664 *echo_on = xmalloc(*numprompts * sizeof(u_int));
665 (*echo_on)[0] = 0;
666}
667
668int
669mm_bsdauth_query(void *ctx, char **name, char **infotxt,
670 u_int *numprompts, char ***prompts, u_int **echo_on)
671{
672 Buffer m;
673 int res;
674 char *challenge;
675
676 debug3("%s: entering", __FUNCTION__);
677
678 buffer_init(&m);
679 mm_request_send(monitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m);
680
681 mm_request_receive_expect(monitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY,
682 &m);
683 res = buffer_get_int(&m);
684 if (res == -1) {
685 debug3("%s: no challenge", __FUNCTION__);
686 buffer_free(&m);
687 return (-1);
688 }
689
690 /* Get the challenge, and format the response */
691 challenge = buffer_get_string(&m, NULL);
692 buffer_free(&m);
693
694 mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
695 (*prompts)[0] = challenge;
696
697 debug3("%s: received challenge: %s", __FUNCTION__, challenge);
698
699 return (0);
700}
701
702int
703mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
704{
705 Buffer m;
706 int authok;
707
708 debug3("%s: entering", __FUNCTION__);
709 if (numresponses != 1)
710 return (-1);
711
712 buffer_init(&m);
713 buffer_put_cstring(&m, responses[0]);
714 mm_request_send(monitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m);
715
716 mm_request_receive_expect(monitor->m_recvfd,
717 MONITOR_ANS_BSDAUTHRESPOND, &m);
718
719 authok = buffer_get_int(&m);
720 buffer_free(&m);
721
722 return ((authok == 0) ? -1 : 0);
723}
724
725int
726mm_skey_query(void *ctx, char **name, char **infotxt,
727 u_int *numprompts, char ***prompts, u_int **echo_on)
728{
729 Buffer m;
730 int len, res;
731 char *p, *challenge;
732
733 debug3("%s: entering", __FUNCTION__);
734
735 buffer_init(&m);
736 mm_request_send(monitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m);
737
738 mm_request_receive_expect(monitor->m_recvfd, MONITOR_ANS_SKEYQUERY,
739 &m);
740 res = buffer_get_int(&m);
741 if (res == -1) {
742 debug3("%s: no challenge", __FUNCTION__);
743 buffer_free(&m);
744 return (-1);
745 }
746
747 /* Get the challenge, and format the response */
748 challenge = buffer_get_string(&m, NULL);
749 buffer_free(&m);
750
751 debug3("%s: received challenge: %s", __FUNCTION__, challenge);
752
753 mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
754
755 len = strlen(challenge) + strlen(SKEY_PROMPT) + 1;
756 p = xmalloc(len);
757 strlcpy(p, challenge, len);
758 strlcat(p, SKEY_PROMPT, len);
759 (*prompts)[0] = p;
760 xfree(challenge);
761
762 return (0);
763}
764
765int
766mm_skey_respond(void *ctx, u_int numresponses, char **responses)
767{
768 Buffer m;
769 int authok;
770
771 debug3("%s: entering", __FUNCTION__);
772 if (numresponses != 1)
773 return (-1);
774
775 buffer_init(&m);
776 buffer_put_cstring(&m, responses[0]);
777 mm_request_send(monitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m);
778
779 mm_request_receive_expect(monitor->m_recvfd,
780 MONITOR_ANS_SKEYRESPOND, &m);
781
782 authok = buffer_get_int(&m);
783 buffer_free(&m);
784
785 return ((authok == 0) ? -1 : 0);
786}
787
788void
789mm_ssh1_session_id(u_char session_id[16])
790{
791 Buffer m;
792 int i;
793
794 debug3("%s entering", __FUNCTION__);
795
796 buffer_init(&m);
797 for (i = 0; i < 16; i++)
798 buffer_put_char(&m, session_id[i]);
799
800 mm_request_send(monitor->m_recvfd, MONITOR_REQ_SESSID, &m);
801 buffer_free(&m);
802}
803
804int
805mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
806{
807 Buffer m;
808 Key *key;
809 u_char *blob;
810 u_int blen;
811 int allowed = 0;
812
813 debug3("%s entering", __FUNCTION__);
814
815 buffer_init(&m);
816 buffer_put_bignum2(&m, client_n);
817
818 mm_request_send(monitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m);
819 mm_request_receive_expect(monitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);
820
821 allowed = buffer_get_int(&m);
822
823 if (allowed && rkey != NULL) {
824 blob = buffer_get_string(&m, &blen);
825 if ((key = key_from_blob(blob, blen)) == NULL)
826 fatal("%s: key_from_blob failed", __FUNCTION__);
827 *rkey = key;
828 xfree(blob);
829 }
830 mm_send_debug(&m);
831 buffer_free(&m);
832
833 return (allowed);
834}
835
836BIGNUM *
837mm_auth_rsa_generate_challenge(Key *key)
838{
839 Buffer m;
840 BIGNUM *challenge;
841 u_char *blob;
842 u_int blen;
843
844 debug3("%s entering", __FUNCTION__);
845
846 if ((challenge = BN_new()) == NULL)
847 fatal("%s: BN_new failed", __FUNCTION__);
848
849 key->type = KEY_RSA; /* XXX cheat for key_to_blob */
850 if (key_to_blob(key, &blob, &blen) == 0)
851 fatal("%s: key_to_blob failed", __FUNCTION__);
852 key->type = KEY_RSA1;
853
854 buffer_init(&m);
855 buffer_put_string(&m, blob, blen);
856 xfree(blob);
857
858 mm_request_send(monitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m);
859 mm_request_receive_expect(monitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m);
860
861 buffer_get_bignum2(&m, challenge);
862 buffer_free(&m);
863
864 return (challenge);
865}
866
867int
868mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
869{
870 Buffer m;
871 u_char *blob;
872 u_int blen;
873 int success = 0;
874
875 debug3("%s entering", __FUNCTION__);
876
877 key->type = KEY_RSA; /* XXX cheat for key_to_blob */
878 if (key_to_blob(key, &blob, &blen) == 0)
879 fatal("%s: key_to_blob failed", __FUNCTION__);
880 key->type = KEY_RSA1;
881
882 buffer_init(&m);
883 buffer_put_string(&m, blob, blen);
884 buffer_put_string(&m, response, 16);
885 xfree(blob);
886
887 mm_request_send(monitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m);
888 mm_request_receive_expect(monitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m);
889
890 success = buffer_get_int(&m);
891 buffer_free(&m);
892
893 return (success);
894}
diff --git a/monitor_wrap.h b/monitor_wrap.h
new file mode 100644
index 000000000..a75b90502
--- /dev/null
+++ b/monitor_wrap.h
@@ -0,0 +1,85 @@
1/*
2 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef _MM_WRAP_H_
27#define _MM_WRAP_H_
28#include "key.h"
29#include "buffer.h"
30
31extern int use_privsep;
32#define PRIVSEP(x) (use_privsep ? mm_##x : x)
33
34enum mm_keytype {MM_NOKEY, MM_HOSTKEY, MM_USERKEY, MM_RSAHOSTKEY, MM_RSAUSERKEY};
35
36struct monitor;
37struct mm_master;
38struct passwd;
39struct Authctxt;
40
41DH *mm_choose_dh(int, int, int);
42int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int);
43void mm_inform_authserv(char *, char *);
44struct passwd *mm_getpwnamallow(const char *);
45int mm_auth_password(struct Authctxt *, char *);
46int mm_key_allowed(enum mm_keytype, char *, char *, Key *);
47int mm_user_key_allowed(struct passwd *, Key *);
48int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *);
49int mm_auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
50int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int);
51int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
52int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *);
53BIGNUM *mm_auth_rsa_generate_challenge(Key *);
54
55void mm_terminate(void);
56int mm_pty_allocate(int *, int *, char *, int);
57void mm_session_pty_cleanup2(void *);
58
59/* SSHv1 interfaces */
60void mm_ssh1_session_id(u_char *);
61int mm_ssh1_session_key(BIGNUM *);
62
63/* Key export functions */
64struct Newkeys *mm_newkeys_from_blob(u_char *, int);
65int mm_newkeys_to_blob(int, u_char **, u_int *);
66
67void monitor_apply_keystate(struct monitor *);
68void mm_get_keystate(struct monitor *);
69void mm_send_keystate(struct monitor*);
70
71/* bsdauth */
72int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
73int mm_bsdauth_respond(void *, u_int, char **);
74
75/* skey */
76int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
77int mm_skey_respond(void *, u_int, char **);
78
79/* zlib allocation hooks */
80
81void *mm_zalloc(struct mm_master *, u_int, u_int);
82void mm_zfree(struct mm_master *, void *);
83void mm_init_compression(struct mm_master *);
84
85#endif /* _MM_H_ */
diff --git a/servconf.c b/servconf.c
index 9bbd994ca..3b6b55e93 100644
--- a/servconf.c
+++ b/servconf.c
@@ -10,7 +10,7 @@
10 */ 10 */
11 11
12#include "includes.h" 12#include "includes.h"
13RCSID("$OpenBSD: servconf.c,v 1.101 2002/02/04 12:15:25 markus Exp $"); 13RCSID("$OpenBSD: servconf.c,v 1.102 2002/03/18 17:50:31 provos Exp $");
14 14
15#if defined(KRB4) || defined(KRB5) 15#if defined(KRB4) || defined(KRB5)
16#include <krb.h> 16#include <krb.h>
@@ -36,6 +36,8 @@ static void add_one_listen_addr(ServerOptions *, char *, u_short);
36 36
37/* AF_UNSPEC or AF_INET or AF_INET6 */ 37/* AF_UNSPEC or AF_INET or AF_INET6 */
38extern int IPv4or6; 38extern int IPv4or6;
39/* Use of privilege separation or not */
40extern int use_privsep;
39 41
40/* Initializes the server options to their default values. */ 42/* Initializes the server options to their default values. */
41 43
@@ -110,6 +112,13 @@ initialize_server_options(ServerOptions *options)
110 options->client_alive_count_max = -1; 112 options->client_alive_count_max = -1;
111 options->authorized_keys_file = NULL; 113 options->authorized_keys_file = NULL;
112 options->authorized_keys_file2 = NULL; 114 options->authorized_keys_file2 = NULL;
115
116 options->unprivileged_user = -1;
117 options->unprivileged_group = -1;
118 options->unprivileged_dir = NULL;
119
120 /* Needs to be accessable in many places */
121 use_privsep = -1;
113} 122}
114 123
115void 124void
@@ -235,6 +244,16 @@ fill_default_server_options(ServerOptions *options)
235 } 244 }
236 if (options->authorized_keys_file == NULL) 245 if (options->authorized_keys_file == NULL)
237 options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS; 246 options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
247
248 /* Turn privilege separation _off_ by default */
249 if (use_privsep == -1)
250 use_privsep = 0;
251 if (options->unprivileged_user == -1)
252 options->unprivileged_user = 32767;
253 if (options->unprivileged_group == -1)
254 options->unprivileged_group = 32767;
255 if (options->unprivileged_dir == NULL)
256 options->unprivileged_dir = "/var/empty";
238} 257}
239 258
240/* Keyword tokens. */ 259/* Keyword tokens. */
@@ -267,6 +286,7 @@ typedef enum {
267 sBanner, sVerifyReverseMapping, sHostbasedAuthentication, 286 sBanner, sVerifyReverseMapping, sHostbasedAuthentication,
268 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 287 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
269 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, 288 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
289 sUsePrivilegeSeparation, sUnprivUser, sUnprivGroup, sUnprivDir,
270 sDeprecated 290 sDeprecated
271} ServerOpCodes; 291} ServerOpCodes;
272 292
@@ -342,6 +362,10 @@ static struct {
342 { "clientalivecountmax", sClientAliveCountMax }, 362 { "clientalivecountmax", sClientAliveCountMax },
343 { "authorizedkeysfile", sAuthorizedKeysFile }, 363 { "authorizedkeysfile", sAuthorizedKeysFile },
344 { "authorizedkeysfile2", sAuthorizedKeysFile2 }, 364 { "authorizedkeysfile2", sAuthorizedKeysFile2 },
365 { "useprivilegeseparation", sUsePrivilegeSeparation},
366 { "unprivuser", sUnprivUser},
367 { "unprivgroup", sUnprivGroup},
368 { "unprivdir", sUnprivDir},
345 { NULL, sBadOption } 369 { NULL, sBadOption }
346}; 370};
347 371
@@ -718,6 +742,22 @@ parse_flag:
718 intptr = &options->allow_tcp_forwarding; 742 intptr = &options->allow_tcp_forwarding;
719 goto parse_flag; 743 goto parse_flag;
720 744
745 case sUsePrivilegeSeparation:
746 intptr = &use_privsep;
747 goto parse_flag;
748
749 case sUnprivUser:
750 intptr = &options->unprivileged_user;
751 goto parse_flag;
752
753 case sUnprivGroup:
754 intptr = &options->unprivileged_group;
755 goto parse_flag;
756
757 case sUnprivDir:
758 charptr = &options->unprivileged_dir;
759 goto parse_filename;
760
721 case sAllowUsers: 761 case sAllowUsers:
722 while ((arg = strdelim(&cp)) && *arg != '\0') { 762 while ((arg = strdelim(&cp)) && *arg != '\0') {
723 if (options->num_allow_users >= MAX_ALLOW_USERS) 763 if (options->num_allow_users >= MAX_ALLOW_USERS)
diff --git a/servconf.h b/servconf.h
index 3134b222a..b5d110a5a 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: servconf.h,v 1.54 2002/03/04 17:27:39 stevesk Exp $ */ 1/* $OpenBSD: servconf.h,v 1.55 2002/03/18 17:50:31 provos Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -131,6 +131,9 @@ typedef struct {
131 char *authorized_keys_file2; 131 char *authorized_keys_file2;
132 int pam_authentication_via_kbd_int; 132 int pam_authentication_via_kbd_int;
133 133
134 int unprivileged_user; /* User unprivileged child uses */
135 int unprivileged_group; /* Group unprivileged child uses */
136 char *unprivileged_dir; /* Chroot dir for unprivileged user */
134} ServerOptions; 137} ServerOptions;
135 138
136void initialize_server_options(ServerOptions *); 139void initialize_server_options(ServerOptions *);
diff --git a/serverloop.c b/serverloop.c
index 46b12ee3d..f3a659188 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -35,7 +35,7 @@
35 */ 35 */
36 36
37#include "includes.h" 37#include "includes.h"
38RCSID("$OpenBSD: serverloop.c,v 1.98 2002/02/06 14:55:16 markus Exp $"); 38RCSID("$OpenBSD: serverloop.c,v 1.99 2002/03/18 17:50:31 provos Exp $");
39 39
40#include "xmalloc.h" 40#include "xmalloc.h"
41#include "packet.h" 41#include "packet.h"
@@ -784,7 +784,7 @@ server_loop2(Authctxt *authctxt)
784 channel_free_all(); 784 channel_free_all();
785 785
786 /* free remaining sessions, e.g. remove wtmp entries */ 786 /* free remaining sessions, e.g. remove wtmp entries */
787 session_destroy_all(); 787 session_destroy_all(NULL);
788} 788}
789 789
790static void 790static void
diff --git a/session.c b/session.c
index 29467029d..e5ea637d5 100644
--- a/session.c
+++ b/session.c
@@ -33,7 +33,7 @@
33 */ 33 */
34 34
35#include "includes.h" 35#include "includes.h"
36RCSID("$OpenBSD: session.c,v 1.129 2002/03/18 03:41:08 provos Exp $"); 36RCSID("$OpenBSD: session.c,v 1.130 2002/03/18 17:50:31 provos Exp $");
37 37
38#include "ssh.h" 38#include "ssh.h"
39#include "ssh1.h" 39#include "ssh1.h"
@@ -56,6 +56,7 @@ RCSID("$OpenBSD: session.c,v 1.129 2002/03/18 03:41:08 provos Exp $");
56#include "serverloop.h" 56#include "serverloop.h"
57#include "canohost.h" 57#include "canohost.h"
58#include "session.h" 58#include "session.h"
59#include "monitor_wrap.h"
59 60
60#ifdef HAVE_CYGWIN 61#ifdef HAVE_CYGWIN
61#include <windows.h> 62#include <windows.h>
@@ -63,39 +64,11 @@ RCSID("$OpenBSD: session.c,v 1.129 2002/03/18 03:41:08 provos Exp $");
63#define is_winnt (GetVersion() < 0x80000000) 64#define is_winnt (GetVersion() < 0x80000000)
64#endif 65#endif
65 66
66/* types */
67
68#define TTYSZ 64
69typedef struct Session Session;
70struct Session {
71 int used;
72 int self;
73 struct passwd *pw;
74 Authctxt *authctxt;
75 pid_t pid;
76 /* tty */
77 char *term;
78 int ptyfd, ttyfd, ptymaster;
79 int row, col, xpixel, ypixel;
80 char tty[TTYSZ];
81 /* X11 */
82 int display_number;
83 char *display;
84 int screen;
85 char *auth_display;
86 char *auth_proto;
87 char *auth_data;
88 int single_connection;
89 /* proto 2 */
90 int chanid;
91 int is_subsystem;
92};
93
94/* func */ 67/* func */
95 68
96Session *session_new(void); 69Session *session_new(void);
97void session_set_fds(Session *, int, int, int); 70void session_set_fds(Session *, int, int, int);
98static void session_pty_cleanup(void *); 71void session_pty_cleanup(void *);
99void session_proctitle(Session *); 72void session_proctitle(Session *);
100int session_setup_x11fwd(Session *); 73int session_setup_x11fwd(Session *);
101void do_exec_pty(Session *, const char *); 74void do_exec_pty(Session *, const char *);
@@ -112,7 +85,6 @@ int check_quietlogin(Session *, const char *);
112static void do_authenticated1(Authctxt *); 85static void do_authenticated1(Authctxt *);
113static void do_authenticated2(Authctxt *); 86static void do_authenticated2(Authctxt *);
114 87
115static void session_close(Session *);
116static int session_pty_req(Session *); 88static int session_pty_req(Session *);
117 89
118/* import */ 90/* import */
@@ -1087,7 +1059,7 @@ do_nologin(struct passwd *pw)
1087} 1059}
1088 1060
1089/* Set login name, uid, gid, and groups. */ 1061/* Set login name, uid, gid, and groups. */
1090static void 1062void
1091do_setusercontext(struct passwd *pw) 1063do_setusercontext(struct passwd *pw)
1092{ 1064{
1093#ifdef HAVE_CYGWIN 1065#ifdef HAVE_CYGWIN
@@ -1142,6 +1114,23 @@ do_setusercontext(struct passwd *pw)
1142 fatal("Failed to set uids to %u.", (u_int) pw->pw_uid); 1114 fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
1143} 1115}
1144 1116
1117void
1118launch_login(struct passwd *pw, const char *hostname)
1119{
1120 /* Launch login(1). */
1121
1122 execl("/usr/bin/login", "login", "-h", hostname,
1123#ifdef LOGIN_NEEDS_TERM
1124 (s->term ? s->term : "unknown"),
1125#endif /* LOGIN_NEEDS_TERM */
1126 "-p", "-f", "--", pw->pw_name, (char *)NULL);
1127
1128 /* Login couldn't be executed, die. */
1129
1130 perror("login");
1131 exit(1);
1132}
1133
1145/* 1134/*
1146 * Performs common processing for the child, such as setting up the 1135 * Performs common processing for the child, such as setting up the
1147 * environment, closing extra file descriptors, setting the user and group 1136 * environment, closing extra file descriptors, setting the user and group
@@ -1267,18 +1256,8 @@ do_child(Session *s, const char *command)
1267 signal(SIGPIPE, SIG_DFL); 1256 signal(SIGPIPE, SIG_DFL);
1268 1257
1269 if (options.use_login) { 1258 if (options.use_login) {
1270 /* Launch login(1). */ 1259 launch_login(pw, hostname);
1271 1260 /* NEVERREACHED */
1272 execl(LOGIN_PROGRAM, "login", "-h", hostname,
1273#ifdef LOGIN_NEEDS_TERM
1274 (s->term ? s->term : "unknown"),
1275#endif /* LOGIN_NEEDS_TERM */
1276 "-p", "-f", "--", pw->pw_name, (char *)NULL);
1277
1278 /* Login couldn't be executed, die. */
1279
1280 perror("login");
1281 exit(1);
1282 } 1261 }
1283 1262
1284 /* Get the last component of the shell name. */ 1263 /* Get the last component of the shell name. */
@@ -1388,6 +1367,22 @@ session_open(Authctxt *authctxt, int chanid)
1388 return 1; 1367 return 1;
1389} 1368}
1390 1369
1370Session *
1371session_by_tty(char *tty)
1372{
1373 int i;
1374 for (i = 0; i < MAX_SESSIONS; i++) {
1375 Session *s = &sessions[i];
1376 if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
1377 debug("session_by_tty: session %d tty %s", i, tty);
1378 return s;
1379 }
1380 }
1381 debug("session_by_tty: unknown tty %.100s", tty);
1382 session_dump();
1383 return NULL;
1384}
1385
1391static Session * 1386static Session *
1392session_by_channel(int id) 1387session_by_channel(int id)
1393{ 1388{
@@ -1436,7 +1431,7 @@ session_pty_req(Session *s)
1436{ 1431{
1437 u_int len; 1432 u_int len;
1438 int n_bytes; 1433 int n_bytes;
1439 1434
1440 if (no_pty_flag) { 1435 if (no_pty_flag) {
1441 debug("Allocating a pty not permitted for this authentication."); 1436 debug("Allocating a pty not permitted for this authentication.");
1442 return 0; 1437 return 0;
@@ -1465,7 +1460,7 @@ session_pty_req(Session *s)
1465 1460
1466 /* Allocate a pty and open it. */ 1461 /* Allocate a pty and open it. */
1467 debug("Allocating pty."); 1462 debug("Allocating pty.");
1468 if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty))) { 1463 if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) {
1469 if (s->term) 1464 if (s->term)
1470 xfree(s->term); 1465 xfree(s->term);
1471 s->term = NULL; 1466 s->term = NULL;
@@ -1486,7 +1481,8 @@ session_pty_req(Session *s)
1486 * time in case we call fatal() (e.g., the connection gets closed). 1481 * time in case we call fatal() (e.g., the connection gets closed).
1487 */ 1482 */
1488 fatal_add_cleanup(session_pty_cleanup, (void *)s); 1483 fatal_add_cleanup(session_pty_cleanup, (void *)s);
1489 pty_setowner(s->pw, s->tty); 1484 if (!use_privsep)
1485 pty_setowner(s->pw, s->tty);
1490 1486
1491 /* Set window size from the packet. */ 1487 /* Set window size from the packet. */
1492 pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); 1488 pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
@@ -1649,8 +1645,8 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr)
1649 * Function to perform pty cleanup. Also called if we get aborted abnormally 1645 * Function to perform pty cleanup. Also called if we get aborted abnormally
1650 * (e.g., due to a dropped connection). 1646 * (e.g., due to a dropped connection).
1651 */ 1647 */
1652static void 1648void
1653session_pty_cleanup(void *session) 1649session_pty_cleanup2(void *session)
1654{ 1650{
1655 Session *s = session; 1651 Session *s = session;
1656 1652
@@ -1668,7 +1664,8 @@ session_pty_cleanup(void *session)
1668 record_logout(s->pid, s->tty, s->pw->pw_name); 1664 record_logout(s->pid, s->tty, s->pw->pw_name);
1669 1665
1670 /* Release the pseudo-tty. */ 1666 /* Release the pseudo-tty. */
1671 pty_release(s->tty); 1667 if (getuid() == 0)
1668 pty_release(s->tty);
1672 1669
1673 /* 1670 /*
1674 * Close the server side of the socket pairs. We must do this after 1671 * Close the server side of the socket pairs. We must do this after
@@ -1676,12 +1673,18 @@ session_pty_cleanup(void *session)
1676 * while we're still cleaning up. 1673 * while we're still cleaning up.
1677 */ 1674 */
1678 if (close(s->ptymaster) < 0) 1675 if (close(s->ptymaster) < 0)
1679 error("close(s->ptymaster): %s", strerror(errno)); 1676 error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno));
1680 1677
1681 /* unlink pty from session */ 1678 /* unlink pty from session */
1682 s->ttyfd = -1; 1679 s->ttyfd = -1;
1683} 1680}
1684 1681
1682void
1683session_pty_cleanup(void *session)
1684{
1685 PRIVSEP(session_pty_cleanup2(session));
1686}
1687
1685static void 1688static void
1686session_exit_message(Session *s, int status) 1689session_exit_message(Session *s, int status)
1687{ 1690{
@@ -1727,7 +1730,7 @@ session_exit_message(Session *s, int status)
1727 s->chanid = -1; 1730 s->chanid = -1;
1728} 1731}
1729 1732
1730static void 1733void
1731session_close(Session *s) 1734session_close(Session *s)
1732{ 1735{
1733 debug("session_close: session %d pid %d", s->self, s->pid); 1736 debug("session_close: session %d pid %d", s->self, s->pid);
@@ -1794,13 +1797,17 @@ session_close_by_channel(int id, void *arg)
1794} 1797}
1795 1798
1796void 1799void
1797session_destroy_all(void) 1800session_destroy_all(void (*closefunc)(Session *))
1798{ 1801{
1799 int i; 1802 int i;
1800 for (i = 0; i < MAX_SESSIONS; i++) { 1803 for (i = 0; i < MAX_SESSIONS; i++) {
1801 Session *s = &sessions[i]; 1804 Session *s = &sessions[i];
1802 if (s->used) 1805 if (s->used) {
1803 session_close(s); 1806 if (closefunc != NULL)
1807 closefunc(s);
1808 else
1809 session_close(s);
1810 }
1804 } 1811 }
1805} 1812}
1806 1813
diff --git a/session.h b/session.h
index ec8284a5f..81f024c9b 100644
--- a/session.h
+++ b/session.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: session.h,v 1.14 2002/02/03 17:53:25 markus Exp $ */ 1/* $OpenBSD: session.h,v 1.15 2002/03/18 17:50:31 provos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -26,12 +26,42 @@
26#ifndef SESSION_H 26#ifndef SESSION_H
27#define SESSION_H 27#define SESSION_H
28 28
29#define TTYSZ 64
30typedef struct Session Session;
31struct Session {
32 int used;
33 int self;
34 struct passwd *pw;
35 Authctxt *authctxt;
36 pid_t pid;
37 /* tty */
38 char *term;
39 int ptyfd, ttyfd, ptymaster;
40 int row, col, xpixel, ypixel;
41 char tty[TTYSZ];
42 /* X11 */
43 int display_number;
44 char *display;
45 int screen;
46 char *auth_display;
47 char *auth_proto;
48 char *auth_data;
49 int single_connection;
50 /* proto 2 */
51 int chanid;
52 int is_subsystem;
53};
54
29void do_authenticated(Authctxt *); 55void do_authenticated(Authctxt *);
30 56
31int session_open(Authctxt*, int); 57int session_open(Authctxt*, int);
32int session_input_channel_req(Channel *, const char *); 58int session_input_channel_req(Channel *, const char *);
33void session_close_by_pid(pid_t, int); 59void session_close_by_pid(pid_t, int);
34void session_close_by_channel(int, void *); 60void session_close_by_channel(int, void *);
35void session_destroy_all(void); 61void session_destroy_all(void (*)(Session *));
36 62
63Session *session_new(void);
64Session *session_by_tty(char *);
65void session_close(Session *);
66void do_setusercontext(struct passwd *);
37#endif 67#endif
diff --git a/sshd.c b/sshd.c
index 0764588fc..c82603d58 100644
--- a/sshd.c
+++ b/sshd.c
@@ -15,8 +15,10 @@
15 * called by a name other than "ssh" or "Secure Shell". 15 * called by a name other than "ssh" or "Secure Shell".
16 * 16 *
17 * SSH2 implementation: 17 * SSH2 implementation:
18 * Privilege Separation:
18 * 19 *
19 * Copyright (c) 2000 Markus Friedl. All rights reserved. 20 * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved.
21 * Copyright (c) 2002 Niels Provos. All rights reserved.
20 * 22 *
21 * Redistribution and use in source and binary forms, with or without 23 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions 24 * modification, are permitted provided that the following conditions
@@ -40,11 +42,12 @@
40 */ 42 */
41 43
42#include "includes.h" 44#include "includes.h"
43RCSID("$OpenBSD: sshd.c,v 1.230 2002/03/18 01:12:14 provos Exp $"); 45RCSID("$OpenBSD: sshd.c,v 1.231 2002/03/18 17:50:31 provos Exp $");
44 46
45#include <openssl/dh.h> 47#include <openssl/dh.h>
46#include <openssl/bn.h> 48#include <openssl/bn.h>
47#include <openssl/md5.h> 49#include <openssl/md5.h>
50#include <openssl/rand.h>
48 51
49#include "ssh.h" 52#include "ssh.h"
50#include "ssh1.h" 53#include "ssh1.h"
@@ -73,6 +76,10 @@ RCSID("$OpenBSD: sshd.c,v 1.230 2002/03/18 01:12:14 provos Exp $");
73#include "dispatch.h" 76#include "dispatch.h"
74#include "channels.h" 77#include "channels.h"
75#include "session.h" 78#include "session.h"
79#include "monitor_mm.h"
80#include "monitor.h"
81#include "monitor_wrap.h"
82#include "monitor_fdpass.h"
76 83
77#ifdef LIBWRAP 84#ifdef LIBWRAP
78#include <tcpd.h> 85#include <tcpd.h>
@@ -190,8 +197,13 @@ u_int utmp_len = MAXHOSTNAMELEN;
190int *startup_pipes = NULL; 197int *startup_pipes = NULL;
191int startup_pipe; /* in child */ 198int startup_pipe; /* in child */
192 199
200/* variables used for privilege separation */
201extern struct monitor *monitor;
202extern int use_privsep;
203
193/* Prototypes for various functions defined later in this file. */ 204/* Prototypes for various functions defined later in this file. */
194void destroy_sensitive_data(void); 205void destroy_sensitive_data(void);
206void demote_sensitive_data(void);
195 207
196static void do_ssh1_kex(void); 208static void do_ssh1_kex(void);
197static void do_ssh2_kex(void); 209static void do_ssh2_kex(void);
@@ -478,6 +490,115 @@ destroy_sensitive_data(void)
478 memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH); 490 memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH);
479} 491}
480 492
493/* Demote private to public keys for network child */
494void
495demote_sensitive_data(void)
496{
497 Key *tmp;
498 int i;
499
500 if (sensitive_data.server_key) {
501 tmp = key_demote(sensitive_data.server_key);
502 key_free(sensitive_data.server_key);
503 sensitive_data.server_key = tmp;
504 }
505
506 for (i = 0; i < options.num_host_key_files; i++) {
507 if (sensitive_data.host_keys[i]) {
508 tmp = key_demote(sensitive_data.host_keys[i]);
509 key_free(sensitive_data.host_keys[i]);
510 sensitive_data.host_keys[i] = tmp;
511 if (tmp->type == KEY_RSA1)
512 sensitive_data.ssh1_host_key = tmp;
513 }
514 }
515
516 /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */
517}
518
519void
520privsep_preauth_child(void)
521{
522 u_int32_t rand[256];
523 int i;
524
525 /* Enable challenge-response authentication for privilege separation */
526 privsep_challenge_enable();
527
528 for (i = 0; i < 256; i++)
529 rand[i] = arc4random();
530 RAND_seed(rand, sizeof(rand));
531
532 /* Demote the private keys to public keys. */
533 demote_sensitive_data();
534
535 /* Change our root directory*/
536 if (chroot(options.unprivileged_dir) == -1)
537 fatal("chroot(/var/empty)");
538 if (chdir("/") == -1)
539 fatal("chdir(/)");
540
541 /* Drop our privileges */
542 setegid(options.unprivileged_group);
543 setgid(options.unprivileged_group);
544 seteuid(options.unprivileged_user);
545 setuid(options.unprivileged_user);
546}
547
548void
549privsep_postauth(Authctxt *authctxt, pid_t pid)
550{
551 extern Authctxt *x_authctxt;
552 int status;
553
554 /* Wait for the child's exit status */
555 waitpid(pid, &status, 0);
556
557 /* XXX - Remote port forwarding */
558 x_authctxt = authctxt;
559
560 if (authctxt->pw->pw_uid == 0 || options.use_login) {
561 /* File descriptor passing is broken or root login */
562 monitor_apply_keystate(monitor);
563 use_privsep = 0;
564 return;
565 }
566
567 /* Authentication complete */
568 alarm(0);
569 if (startup_pipe != -1) {
570 close(startup_pipe);
571 startup_pipe = -1;
572 }
573
574 /* New socket pair */
575 monitor_reinit(monitor);
576
577 monitor->m_pid = fork();
578 if (monitor->m_pid == -1)
579 fatal("fork of unprivileged child failed");
580 else if (monitor->m_pid != 0) {
581 debug2("User child is on pid %d", pid);
582 close(monitor->m_recvfd);
583 monitor_child_postauth(monitor);
584
585 /* NEVERREACHED */
586 exit(0);
587 }
588
589 close(monitor->m_sendfd);
590
591 /* Demote the private keys to public keys. */
592 demote_sensitive_data();
593
594 /* Drop privileges */
595 do_setusercontext(authctxt->pw);
596
597 /* It is safe now to apply the key state */
598 monitor_apply_keystate(monitor);
599}
600
601
481static char * 602static char *
482list_hostkey_types(void) 603list_hostkey_types(void)
483{ 604{
@@ -507,7 +628,7 @@ list_hostkey_types(void)
507 return p; 628 return p;
508} 629}
509 630
510static Key * 631Key *
511get_hostkey_by_type(int type) 632get_hostkey_by_type(int type)
512{ 633{
513 int i; 634 int i;
@@ -519,6 +640,25 @@ get_hostkey_by_type(int type)
519 return NULL; 640 return NULL;
520} 641}
521 642
643Key *
644get_hostkey_by_index(int ind)
645{
646 if (ind < 0 || ind >= options.num_host_key_files)
647 return (NULL);
648 return (sensitive_data.host_keys[ind]);
649}
650
651int
652get_hostkey_index(Key *key)
653{
654 int i;
655 for (i = 0; i < options.num_host_key_files; i++) {
656 if (key == sensitive_data.host_keys[i])
657 return (i);
658 }
659 return (-1);
660}
661
522/* 662/*
523 * returns 1 if connection should be dropped, 0 otherwise. 663 * returns 1 if connection should be dropped, 0 otherwise.
524 * dropping starts at connection #max_startups_begin with a probability 664 * dropping starts at connection #max_startups_begin with a probability
@@ -1233,6 +1373,37 @@ main(int ac, char **av)
1233 1373
1234 packet_set_nonblocking(); 1374 packet_set_nonblocking();
1235 1375
1376 if (!use_privsep)
1377 goto skip_privilegeseparation;
1378
1379 /* Set up unprivileged child process to deal with network data */
1380 monitor = monitor_init();
1381 /* Store a pointer to the kex for later rekeying */
1382 monitor->m_pkex = &xxx_kex;
1383
1384 pid = fork();
1385 if (pid == -1)
1386 fatal("fork of unprivileged child failed");
1387 else if (pid != 0) {
1388 debug2("Network child is on pid %d", pid);
1389
1390 close(monitor->m_recvfd);
1391 authctxt = monitor_child_preauth(monitor);
1392 close(monitor->m_sendfd);
1393
1394 /* Sync memory */
1395 monitor_sync(monitor);
1396 goto authenticated;
1397 } else {
1398 close(monitor->m_sendfd);
1399
1400 /* Demote the child */
1401 if (getuid() == 0 || geteuid() == 0)
1402 privsep_preauth_child();
1403 }
1404
1405 skip_privilegeseparation:
1406
1236 /* perform the key exchange */ 1407 /* perform the key exchange */
1237 /* authenticate user and start session */ 1408 /* authenticate user and start session */
1238 if (compat20) { 1409 if (compat20) {
@@ -1242,6 +1413,23 @@ main(int ac, char **av)
1242 do_ssh1_kex(); 1413 do_ssh1_kex();
1243 authctxt = do_authentication(); 1414 authctxt = do_authentication();
1244 } 1415 }
1416 if (use_privsep)
1417 mm_send_keystate(monitor);
1418
1419 /* If we use privilege separation, the unprivileged child exits */
1420 if (use_privsep)
1421 exit(0);
1422
1423 authenticated:
1424 /*
1425 * In privilege separation, we fork another child and prepare
1426 * file descriptor passing.
1427 */
1428 if (use_privsep) {
1429 privsep_postauth(authctxt, pid);
1430 if (!compat20)
1431 destroy_sensitive_data();
1432 }
1245 1433
1246 /* Perform session preparation. */ 1434 /* Perform session preparation. */
1247 do_authenticated(authctxt); 1435 do_authenticated(authctxt);
@@ -1254,6 +1442,10 @@ main(int ac, char **av)
1254#endif /* USE_PAM */ 1442#endif /* USE_PAM */
1255 1443
1256 packet_close(); 1444 packet_close();
1445
1446 if (use_privsep)
1447 mm_terminate();
1448
1257 exit(0); 1449 exit(0);
1258} 1450}
1259 1451
@@ -1261,7 +1453,7 @@ main(int ac, char **av)
1261 * Decrypt session_key_int using our private server key and private host key 1453 * Decrypt session_key_int using our private server key and private host key
1262 * (key with larger modulus first). 1454 * (key with larger modulus first).
1263 */ 1455 */
1264static int 1456int
1265ssh1_session_key(BIGNUM *session_key_int) 1457ssh1_session_key(BIGNUM *session_key_int)
1266{ 1458{
1267 int rsafail = 0; 1459 int rsafail = 0;
@@ -1417,7 +1609,8 @@ do_ssh1_kex(void)
1417 packet_check_eom(); 1609 packet_check_eom();
1418 1610
1419 /* Decrypt session_key_int using host/server keys */ 1611 /* Decrypt session_key_int using host/server keys */
1420 rsafail = ssh1_session_key(session_key_int); 1612 rsafail = PRIVSEP(ssh1_session_key(session_key_int));
1613
1421 /* 1614 /*
1422 * Extract session key from the decrypted integer. The key is in the 1615 * Extract session key from the decrypted integer. The key is in the
1423 * least significant 256 bits of the integer; the first byte of the 1616 * least significant 256 bits of the integer; the first byte of the
@@ -1468,9 +1661,12 @@ do_ssh1_kex(void)
1468 for (i = 0; i < 16; i++) 1661 for (i = 0; i < 16; i++)
1469 session_id[i] = session_key[i] ^ session_key[i + 16]; 1662 session_id[i] = session_key[i] ^ session_key[i + 16];
1470 } 1663 }
1471 /* Destroy the private and public keys. They will no longer be needed. */ 1664 /* Destroy the private and public keys. No longer. */
1472 destroy_sensitive_data(); 1665 destroy_sensitive_data();
1473 1666
1667 if (use_privsep)
1668 mm_ssh1_session_id(session_id);
1669
1474 /* Destroy the decrypted integer. It is no longer needed. */ 1670 /* Destroy the decrypted integer. It is no longer needed. */
1475 BN_clear_free(session_key_int); 1671 BN_clear_free(session_key_int);
1476 1672
@@ -1517,6 +1713,7 @@ do_ssh2_kex(void)
1517 kex->client_version_string=client_version_string; 1713 kex->client_version_string=client_version_string;
1518 kex->server_version_string=server_version_string; 1714 kex->server_version_string=server_version_string;
1519 kex->load_host_key=&get_hostkey_by_type; 1715 kex->load_host_key=&get_hostkey_by_type;
1716 kex->host_key_index=&get_hostkey_index;
1520 1717
1521 xxx_kex = kex; 1718 xxx_kex = kex;
1522 1719