diff options
author | Damien Miller <djm@mindrot.org> | 2000-04-12 18:45:05 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2000-04-12 18:45:05 +1000 |
commit | efb4afe0265333ce554f699c2a19ae249dd8d1b5 (patch) | |
tree | 8fe5e0bb9791e7fa3d1788084ae669f7a9dcd2e0 /session.c | |
parent | 11e37f638d3cc064371521001eaeb2d75bfe4a8d (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.c | 328 |
1 files changed, 319 insertions, 9 deletions
@@ -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" |
7 | RCSID("$OpenBSD: session.c,v 1.1 2000/03/28 21:15:45 markus Exp $"); | 11 | RCSID("$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 | ||
1149 | int | ||
1150 | session_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 | |||
1167 | Session * | ||
1168 | session_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 | |||
1183 | Session * | ||
1184 | session_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 | |||
1198 | int | ||
1199 | session_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 | |||
1209 | int | ||
1210 | session_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 | |||
1248 | void | ||
1249 | session_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 | |||
1308 | void | ||
1309 | session_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 | |||
1129 | void | 1324 | void |
1130 | session_pty_cleanup(Session *s) | 1325 | session_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 | |||
1350 | void | ||
1351 | session_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 | |||
1390 | void | ||
1391 | session_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 | |||
1405 | void | ||
1406 | session_close(Session *s) | ||
1407 | { | ||
1408 | session_pty_cleanup(s); | ||
1409 | session_free(s); | ||
1410 | } | ||
1411 | |||
1412 | void | ||
1413 | session_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 | */ | ||
1429 | void | ||
1430 | session_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 | |||
1453 | void | ||
1454 | do_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 | } | ||