summaryrefslogtreecommitdiff
path: root/session.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2000-04-12 18:45:05 +1000
committerDamien Miller <djm@mindrot.org>2000-04-12 18:45:05 +1000
commitefb4afe0265333ce554f699c2a19ae249dd8d1b5 (patch)
tree8fe5e0bb9791e7fa3d1788084ae669f7a9dcd2e0 /session.c
parent11e37f638d3cc064371521001eaeb2d75bfe4a8d (diff)
- More large OpenBSD CVS updates:
- [auth.c auth.h servconf.c servconf.h serverloop.c session.c] [session.h ssh.h sshd.c README.openssh2] ssh2 server side, see README.openssh2; enable with 'sshd -2' - [channels.c] no adjust after close - [sshd.c compat.c ] interop w/ latest ssh.com windows client.
Diffstat (limited to 'session.c')
-rw-r--r--session.c328
1 files changed, 319 insertions, 9 deletions
diff --git a/session.c b/session.c
index 2128fe394..835a46945 100644
--- a/session.c
+++ b/session.c
@@ -2,9 +2,13 @@
2 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 2 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3 * All rights reserved 3 * All rights reserved
4 */ 4 */
5/*
6 * SSH2 support by Markus Friedl.
7 * Copyright (c) 2000 Markus Friedl. All rights reserved.
8 */
5 9
6#include "includes.h" 10#include "includes.h"
7RCSID("$OpenBSD: session.c,v 1.1 2000/03/28 21:15:45 markus Exp $"); 11RCSID("$OpenBSD: session.c,v 1.2 2000/04/06 08:55:22 markus Exp $");
8 12
9#include "xmalloc.h" 13#include "xmalloc.h"
10#include "ssh.h" 14#include "ssh.h"
@@ -19,6 +23,10 @@ RCSID("$OpenBSD: session.c,v 1.1 2000/03/28 21:15:45 markus Exp $");
19#include "channels.h" 23#include "channels.h"
20#include "nchan.h" 24#include "nchan.h"
21 25
26#include "bufaux.h"
27#include "ssh2.h"
28#include "auth.h"
29
22/* types */ 30/* types */
23 31
24#define TTYSZ 64 32#define TTYSZ 64
@@ -448,9 +456,13 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw)
448 close(pout[1]); 456 close(pout[1]);
449 close(perr[1]); 457 close(perr[1]);
450 458
451 /* Enter the interactive session. */ 459 if (compat20) {
452 server_loop(pid, pin[1], pout[0], perr[0]); 460 session_set_fds(s, pin[1], pout[0], perr[0]);
453 /* server_loop has closed pin[1], pout[1], and perr[1]. */ 461 } else {
462 /* Enter the interactive session. */
463 server_loop(pid, pin[1], pout[0], perr[0]);
464 /* server_loop has closed pin[1], pout[1], and perr[1]. */
465 }
454#else /* USE_PIPES */ 466#else /* USE_PIPES */
455 /* We are the parent. Close the child sides of the socket pairs. */ 467 /* We are the parent. Close the child sides of the socket pairs. */
456 close(inout[0]); 468 close(inout[0]);
@@ -460,8 +472,12 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw)
460 * Enter the interactive session. Note: server_loop must be able to 472 * Enter the interactive session. Note: server_loop must be able to
461 * handle the case that fdin and fdout are the same. 473 * handle the case that fdin and fdout are the same.
462 */ 474 */
463 server_loop(pid, inout[1], inout[1], err[1]); 475 if (compat20) {
464 /* server_loop has closed inout[1] and err[1]. */ 476 session_set_fds(s, inout[1], inout[1], err[1]);
477 } else {
478 server_loop(pid, inout[1], inout[1], err[1]);
479 /* server_loop has closed inout[1] and err[1]. */
480 }
465#endif /* USE_PIPES */ 481#endif /* USE_PIPES */
466} 482}
467 483
@@ -631,9 +647,13 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
631 s->ptymaster = ptymaster; 647 s->ptymaster = ptymaster;
632 648
633 /* Enter interactive session. */ 649 /* Enter interactive session. */
634 server_loop(pid, ptyfd, fdout, -1); 650 if (compat20) {
635 /* server_loop _has_ closed ptyfd and fdout. */ 651 session_set_fds(s, ptyfd, fdout, -1);
636 session_pty_cleanup(s); 652 } else {
653 server_loop(pid, ptyfd, fdout, -1);
654 /* server_loop _has_ closed ptyfd and fdout. */
655 session_pty_cleanup(s);
656 }
637} 657}
638 658
639/* 659/*
@@ -1126,6 +1146,181 @@ session_dump(void)
1126 } 1146 }
1127} 1147}
1128 1148
1149int
1150session_open(int chanid)
1151{
1152 Session *s = session_new();
1153 debug("session_open: channel %d", chanid);
1154 if (s == NULL) {
1155 error("no more sessions");
1156 return 0;
1157 }
1158 debug("session_open: session %d: link with channel %d", s->self, chanid);
1159 s->chanid = chanid;
1160 s->pw = auth_get_user();
1161 if (s->pw == NULL)
1162 fatal("no user for session %i channel %d",
1163 s->self, s->chanid);
1164 return 1;
1165}
1166
1167Session *
1168session_by_channel(int id)
1169{
1170 int i;
1171 for(i = 0; i < MAX_SESSIONS; i++) {
1172 Session *s = &sessions[i];
1173 if (s->used && s->chanid == id) {
1174 debug("session_by_channel: session %d channel %d", i, id);
1175 return s;
1176 }
1177 }
1178 debug("session_by_channel: unknown channel %d", id);
1179 session_dump();
1180 return NULL;
1181}
1182
1183Session *
1184session_by_pid(pid_t pid)
1185{
1186 int i;
1187 debug("session_by_pid: pid %d", pid);
1188 for(i = 0; i < MAX_SESSIONS; i++) {
1189 Session *s = &sessions[i];
1190 if (s->used && s->pid == pid)
1191 return s;
1192 }
1193 error("session_by_pid: unknown pid %d", pid);
1194 session_dump();
1195 return NULL;
1196}
1197
1198int
1199session_window_change_req(Session *s)
1200{
1201 s->col = packet_get_int();
1202 s->row = packet_get_int();
1203 s->xpixel = packet_get_int();
1204 s->ypixel = packet_get_int();
1205 pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1206 return 1;
1207}
1208
1209int
1210session_pty_req(Session *s)
1211{
1212 unsigned int len;
1213
1214 if (s->ttyfd != -1)
1215 return -1;
1216 s->term = packet_get_string(&len);
1217 s->col = packet_get_int();
1218 s->row = packet_get_int();
1219 s->xpixel = packet_get_int();
1220 s->ypixel = packet_get_int();
1221
1222 if (strcmp(s->term, "") == 0) {
1223 xfree(s->term);
1224 s->term = NULL;
1225 }
1226 /* Allocate a pty and open it. */
1227 if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty))) {
1228 xfree(s->term);
1229 s->term = NULL;
1230 s->ptyfd = -1;
1231 s->ttyfd = -1;
1232 error("session_pty_req: session %d alloc failed", s->self);
1233 return -1;
1234 }
1235 debug("session_pty_req: session %d alloc %s", s->self, s->tty);
1236 /*
1237 * Add a cleanup function to clear the utmp entry and record logout
1238 * time in case we call fatal() (e.g., the connection gets closed).
1239 */
1240 fatal_add_cleanup(pty_cleanup_proc, (void *)s);
1241 pty_setowner(s->pw, s->tty);
1242 /* Get window size from the packet. */
1243 pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1244
1245 return 1;
1246}
1247
1248void
1249session_input_channel_req(int id, void *arg)
1250{
1251 unsigned int len;
1252 int reply;
1253 int success = 0;
1254 char *rtype;
1255 Session *s;
1256 Channel *c;
1257
1258 rtype = packet_get_string(&len);
1259 reply = packet_get_char();
1260
1261 s = session_by_channel(id);
1262 if (s == NULL)
1263 fatal("session_input_channel_req: channel %d: no session", id);
1264 c = channel_lookup(id);
1265 if (c == NULL)
1266 fatal("session_input_channel_req: channel %d: bad channel", id);
1267
1268 debug("session_input_channel_req: session %d channel %d request %s reply %d",
1269 s->self, id, rtype, reply);
1270
1271 /*
1272 * a session is in LARVAL state until a shell
1273 * or programm is executed
1274 */
1275 if (c->type == SSH_CHANNEL_LARVAL) {
1276 if (strcmp(rtype, "shell") == 0) {
1277 if (s->ttyfd == -1)
1278 do_exec_no_pty(s, NULL, s->pw);
1279 else
1280 do_exec_pty(s, NULL, s->pw);
1281 success = 1;
1282 } else if (strcmp(rtype, "exec") == 0) {
1283 char *command = packet_get_string(&len);
1284 if (s->ttyfd == -1)
1285 do_exec_no_pty(s, command, s->pw);
1286 else
1287 do_exec_pty(s, command, s->pw);
1288 xfree(command);
1289 success = 1;
1290 } else if (strcmp(rtype, "pty-req") == 0) {
1291 if (session_pty_req(s) > 0)
1292 success = 1;
1293 }
1294 }
1295 if (strcmp(rtype, "window-change") == 0) {
1296 success = session_window_change_req(s);
1297 }
1298
1299 if (reply) {
1300 packet_start(success ?
1301 SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
1302 packet_put_int(c->remote_id);
1303 packet_send();
1304 }
1305 xfree(rtype);
1306}
1307
1308void
1309session_set_fds(Session *s, int fdin, int fdout, int fderr)
1310{
1311 if (!compat20)
1312 fatal("session_set_fds: called for proto != 2.0");
1313 /*
1314 * now that have a child and a pipe to the child,
1315 * we can activate our channel and register the fd's
1316 */
1317 if (s->chanid == -1)
1318 fatal("no channel for session %d", s->self);
1319 channel_set_fds(s->chanid,
1320 fdout, fdin, fderr,
1321 fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ);
1322}
1323
1129void 1324void
1130session_pty_cleanup(Session *s) 1325session_pty_cleanup(Session *s)
1131{ 1326{
@@ -1151,3 +1346,118 @@ session_pty_cleanup(Session *s)
1151 if (close(s->ptymaster) < 0) 1346 if (close(s->ptymaster) < 0)
1152 error("close(s->ptymaster): %s", strerror(errno)); 1347 error("close(s->ptymaster): %s", strerror(errno));
1153} 1348}
1349
1350void
1351session_exit_message(Session *s, int status)
1352{
1353 Channel *c;
1354 if (s == NULL)
1355 fatal("session_close: no session");
1356 c = channel_lookup(s->chanid);
1357 if (c == NULL)
1358 fatal("session_close: session %d: no channel %d",
1359 s->self, s->chanid);
1360 debug("session_exit_message: session %d channel %d pid %d",
1361 s->self, s->chanid, s->pid);
1362
1363 if (WIFEXITED(status)) {
1364 channel_request_start(s->chanid,
1365 "exit-status", 0);
1366 packet_put_int(WEXITSTATUS(status));
1367 packet_send();
1368 } else if (WIFSIGNALED(status)) {
1369 channel_request_start(s->chanid,
1370 "exit-signal", 0);
1371 packet_put_int(WTERMSIG(status));
1372 packet_put_char(WCOREDUMP(status));
1373 packet_put_cstring("");
1374 packet_put_cstring("");
1375 packet_send();
1376 } else {
1377 /* Some weird exit cause. Just exit. */
1378 packet_disconnect("wait returned status %04x.", status);
1379 }
1380
1381 /* disconnect channel */
1382 debug("session_exit_message: release channel %d", s->chanid);
1383 channel_cancel_cleanup(s->chanid);
1384 if (c->istate == CHAN_INPUT_OPEN)
1385 chan_read_failed(c);
1386 chan_write_failed(c);
1387 s->chanid = -1;
1388}
1389
1390void
1391session_free(Session *s)
1392{
1393 debug("session_free: session %d pid %d", s->self, s->pid);
1394 if (s->term)
1395 xfree(s->term);
1396 if (s->display)
1397 xfree(s->display);
1398 if (s->auth_data)
1399 xfree(s->auth_data);
1400 if (s->auth_proto)
1401 xfree(s->auth_proto);
1402 s->used = 0;
1403}
1404
1405void
1406session_close(Session *s)
1407{
1408 session_pty_cleanup(s);
1409 session_free(s);
1410}
1411
1412void
1413session_close_by_pid(pid_t pid, int status)
1414{
1415 Session *s = session_by_pid(pid);
1416 if (s == NULL) {
1417 debug("session_close_by_pid: no session for pid %d", s->pid);
1418 return;
1419 }
1420 if (s->chanid != -1)
1421 session_exit_message(s, status);
1422 session_close(s);
1423}
1424
1425/*
1426 * this is called when a channel dies before
1427 * the session 'child' itself dies
1428 */
1429void
1430session_close_by_channel(int id, void *arg)
1431{
1432 Session *s = session_by_channel(id);
1433 if (s == NULL) {
1434 debug("session_close_by_channel: no session for channel %d", id);
1435 return;
1436 }
1437 /* disconnect channel */
1438 channel_cancel_cleanup(s->chanid);
1439 s->chanid = -1;
1440
1441 debug("session_close_by_channel: channel %d kill %d", id, s->pid);
1442 if (s->pid == 0) {
1443 /* close session immediately */
1444 session_close(s);
1445 } else {
1446 /* notify child, delay session cleanup */
1447 if (kill(s->pid, (s->ttyfd == -1) ? SIGTERM : SIGHUP) < 0)
1448 error("session_close_by_channel: kill %d: %s",
1449 s->pid, strerror(errno));
1450 }
1451}
1452
1453void
1454do_authenticated2(void)
1455{
1456 /*
1457 * Cancel the alarm we set to limit the time taken for
1458 * authentication.
1459 */
1460 alarm(0);
1461 log("do_authenticated2");
1462 server_loop2();
1463}