|
Lines 93-101
void session_set_fds(Session *, int, int
Link Here
|
| 93 |
void session_pty_cleanup(Session *); |
93 |
void session_pty_cleanup(Session *); |
| 94 |
void session_proctitle(Session *); |
94 |
void session_proctitle(Session *); |
| 95 |
int session_setup_x11fwd(Session *); |
95 |
int session_setup_x11fwd(Session *); |
| 96 |
void do_exec_pty(Session *, const char *); |
96 |
int do_exec_pty(Session *, const char *); |
| 97 |
void do_exec_no_pty(Session *, const char *); |
97 |
int do_exec_no_pty(Session *, const char *); |
| 98 |
void do_exec(Session *, const char *); |
98 |
int do_exec(Session *, const char *); |
| 99 |
void do_login(Session *, const char *); |
99 |
void do_login(Session *, const char *); |
| 100 |
void do_child(Session *, const char *); |
100 |
void do_child(Session *, const char *); |
| 101 |
void do_motd(void); |
101 |
void do_motd(void); |
|
Lines 120-127
extern Buffer loginmsg;
Link Here
|
| 120 |
const char *original_command = NULL; |
120 |
const char *original_command = NULL; |
| 121 |
|
121 |
|
| 122 |
/* data */ |
122 |
/* data */ |
| 123 |
#define MAX_SESSIONS 10 |
123 |
static int sessions_first_unused = -1; |
| 124 |
Session sessions[MAX_SESSIONS]; |
124 |
static int sessions_nalloc = 0; |
|
|
125 |
static Session *sessions = NULL; |
| 125 |
|
126 |
|
| 126 |
#define SUBSYSTEM_NONE 0 |
127 |
#define SUBSYSTEM_NONE 0 |
| 127 |
#define SUBSYSTEM_EXT 1 |
128 |
#define SUBSYSTEM_EXT 1 |
|
Lines 153-159
static int
Link Here
|
| 153 |
auth_input_request_forwarding(struct passwd * pw) |
154 |
auth_input_request_forwarding(struct passwd * pw) |
| 154 |
{ |
155 |
{ |
| 155 |
Channel *nc; |
156 |
Channel *nc; |
| 156 |
int sock; |
157 |
int sock = -1; |
| 157 |
struct sockaddr_un sunaddr; |
158 |
struct sockaddr_un sunaddr; |
| 158 |
|
159 |
|
| 159 |
if (auth_sock_name != NULL) { |
160 |
if (auth_sock_name != NULL) { |
|
Lines 165-207
auth_input_request_forwarding(struct pas
Link Here
|
| 165 |
temporarily_use_uid(pw); |
166 |
temporarily_use_uid(pw); |
| 166 |
|
167 |
|
| 167 |
/* Allocate a buffer for the socket name, and format the name. */ |
168 |
/* Allocate a buffer for the socket name, and format the name. */ |
| 168 |
auth_sock_name = xmalloc(MAXPATHLEN); |
169 |
auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX"); |
| 169 |
auth_sock_dir = xmalloc(MAXPATHLEN); |
|
|
| 170 |
strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN); |
| 171 |
|
170 |
|
| 172 |
/* Create private directory for socket */ |
171 |
/* Create private directory for socket */ |
| 173 |
if (mkdtemp(auth_sock_dir) == NULL) { |
172 |
if (mkdtemp(auth_sock_dir) == NULL) { |
| 174 |
packet_send_debug("Agent forwarding disabled: " |
173 |
packet_send_debug("Agent forwarding disabled: " |
| 175 |
"mkdtemp() failed: %.100s", strerror(errno)); |
174 |
"mkdtemp() failed: %.100s", strerror(errno)); |
| 176 |
restore_uid(); |
175 |
restore_uid(); |
| 177 |
xfree(auth_sock_name); |
|
|
| 178 |
xfree(auth_sock_dir); |
176 |
xfree(auth_sock_dir); |
| 179 |
auth_sock_name = NULL; |
|
|
| 180 |
auth_sock_dir = NULL; |
177 |
auth_sock_dir = NULL; |
| 181 |
return 0; |
178 |
goto authsock_err; |
| 182 |
} |
179 |
} |
| 183 |
snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld", |
180 |
|
| 184 |
auth_sock_dir, (long) getpid()); |
181 |
auth_sock_name = xmalloc(MAXPATHLEN); |
|
|
182 |
xasprintf(&auth_sock_name, "%s/agent.%ld", |
| 183 |
auth_sock_dir, (long) getpid()); |
| 185 |
|
184 |
|
| 186 |
/* Create the socket. */ |
185 |
/* Create the socket. */ |
| 187 |
sock = socket(AF_UNIX, SOCK_STREAM, 0); |
186 |
sock = socket(AF_UNIX, SOCK_STREAM, 0); |
| 188 |
if (sock < 0) |
187 |
if (sock < 0) { |
| 189 |
packet_disconnect("socket: %.100s", strerror(errno)); |
188 |
error("socket: %.100s", strerror(errno)); |
|
|
189 |
restore_uid(); |
| 190 |
goto authsock_err; |
| 191 |
} |
| 190 |
|
192 |
|
| 191 |
/* Bind it to the name. */ |
193 |
/* Bind it to the name. */ |
| 192 |
memset(&sunaddr, 0, sizeof(sunaddr)); |
194 |
memset(&sunaddr, 0, sizeof(sunaddr)); |
| 193 |
sunaddr.sun_family = AF_UNIX; |
195 |
sunaddr.sun_family = AF_UNIX; |
| 194 |
strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path)); |
196 |
strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path)); |
| 195 |
|
197 |
|
| 196 |
if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) |
198 |
if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { |
| 197 |
packet_disconnect("bind: %.100s", strerror(errno)); |
199 |
error("bind: %.100s", strerror(errno)); |
|
|
200 |
restore_uid(); |
| 201 |
goto authsock_err; |
| 202 |
} |
| 198 |
|
203 |
|
| 199 |
/* Restore the privileged uid. */ |
204 |
/* Restore the privileged uid. */ |
| 200 |
restore_uid(); |
205 |
restore_uid(); |
| 201 |
|
206 |
|
| 202 |
/* Start listening on the socket. */ |
207 |
/* Start listening on the socket. */ |
| 203 |
if (listen(sock, SSH_LISTEN_BACKLOG) < 0) |
208 |
if (listen(sock, SSH_LISTEN_BACKLOG) < 0) { |
| 204 |
packet_disconnect("listen: %.100s", strerror(errno)); |
209 |
error("listen: %.100s", strerror(errno)); |
|
|
210 |
goto authsock_err; |
| 211 |
} |
| 205 |
|
212 |
|
| 206 |
/* Allocate a channel for the authentication agent socket. */ |
213 |
/* Allocate a channel for the authentication agent socket. */ |
| 207 |
nc = channel_new("auth socket", |
214 |
nc = channel_new("auth socket", |
|
Lines 210-215
auth_input_request_forwarding(struct pas
Link Here
|
| 210 |
0, "auth socket", 1); |
217 |
0, "auth socket", 1); |
| 211 |
strlcpy(nc->path, auth_sock_name, sizeof(nc->path)); |
218 |
strlcpy(nc->path, auth_sock_name, sizeof(nc->path)); |
| 212 |
return 1; |
219 |
return 1; |
|
|
220 |
|
| 221 |
authsock_err: |
| 222 |
if (auth_sock_name != NULL) |
| 223 |
xfree(auth_sock_name); |
| 224 |
if (auth_sock_dir != NULL) { |
| 225 |
rmdir(auth_sock_dir); |
| 226 |
xfree(auth_sock_dir); |
| 227 |
} |
| 228 |
if (sock != -1) |
| 229 |
close(sock); |
| 230 |
auth_sock_name = NULL; |
| 231 |
auth_sock_dir = NULL; |
| 232 |
return 0; |
| 213 |
} |
233 |
} |
| 214 |
|
234 |
|
| 215 |
static void |
235 |
static void |
|
Lines 358-364
do_authenticated1(Authctxt *authctxt)
Link Here
|
| 358 |
if (type == SSH_CMSG_EXEC_CMD) { |
378 |
if (type == SSH_CMSG_EXEC_CMD) { |
| 359 |
command = packet_get_string(&dlen); |
379 |
command = packet_get_string(&dlen); |
| 360 |
debug("Exec command '%.500s'", command); |
380 |
debug("Exec command '%.500s'", command); |
| 361 |
do_exec(s, command); |
381 |
if (do_exec(s, command) != 0) |
|
|
382 |
cleanup_exit(255); |
| 362 |
xfree(command); |
383 |
xfree(command); |
| 363 |
} else { |
384 |
} else { |
| 364 |
do_exec(s, NULL); |
385 |
do_exec(s, NULL); |
|
Lines 391-418
do_authenticated1(Authctxt *authctxt)
Link Here
|
| 391 |
* will call do_child from the child, and server_loop from the parent after |
412 |
* will call do_child from the child, and server_loop from the parent after |
| 392 |
* setting up file descriptors and such. |
413 |
* setting up file descriptors and such. |
| 393 |
*/ |
414 |
*/ |
| 394 |
void |
415 |
int |
| 395 |
do_exec_no_pty(Session *s, const char *command) |
416 |
do_exec_no_pty(Session *s, const char *command) |
| 396 |
{ |
417 |
{ |
| 397 |
pid_t pid; |
418 |
pid_t pid; |
| 398 |
|
|
|
| 399 |
int inout[2], err[2]; |
419 |
int inout[2], err[2]; |
|
|
420 |
|
| 400 |
/* Uses socket pairs to communicate with the program. */ |
421 |
/* Uses socket pairs to communicate with the program. */ |
| 401 |
if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 || |
422 |
if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) { |
| 402 |
socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) |
423 |
error("%s: socketpair #1: %.100s", __func__, strerror(errno)); |
| 403 |
packet_disconnect("Could not create socket pairs: %.100s", |
424 |
return -1; |
| 404 |
strerror(errno)); |
425 |
} |
|
|
426 |
if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) { |
| 427 |
error("%s: socketpair #2: %.100s", __func__, strerror(errno)); |
| 428 |
close(inout[0]); |
| 429 |
close(inout[1]); |
| 430 |
return -1; |
| 431 |
} |
| 432 |
|
| 405 |
if (s == NULL) |
433 |
if (s == NULL) |
| 406 |
fatal("do_exec_no_pty: no session"); |
434 |
fatal("do_exec_no_pty: no session"); |
| 407 |
|
435 |
|
| 408 |
session_proctitle(s); |
436 |
session_proctitle(s); |
| 409 |
|
437 |
|
| 410 |
/* Fork the child. */ |
438 |
/* Fork the child. */ |
| 411 |
if ((pid = fork()) == 0) { |
439 |
switch ((pid = fork())) { |
|
|
440 |
case -1: |
| 441 |
error("%s: fork: %.100s", __func__, strerror(errno)); |
| 442 |
close(inout[0]); |
| 443 |
close(inout[1]); |
| 444 |
close(err[0]); |
| 445 |
close(err[1]); |
| 446 |
return -1; |
| 447 |
case 0: |
| 412 |
is_child = 1; |
448 |
is_child = 1; |
| 413 |
|
449 |
|
| 414 |
/* Child. Reinitialize the log since the pid has changed. */ |
450 |
/* Child. Reinitialize the log since the pid has changed. */ |
| 415 |
log_init(__progname, options.log_level, options.log_facility, log_stderr); |
451 |
log_init(__progname, options.log_level, |
|
|
452 |
options.log_facility, log_stderr); |
| 416 |
|
453 |
|
| 417 |
/* |
454 |
/* |
| 418 |
* Create a new session and process group since the 4.4BSD |
455 |
* Create a new session and process group since the 4.4BSD |
|
Lines 430-436
do_exec_no_pty(Session *s, const char *c
Link Here
|
| 430 |
close(err[1]); |
467 |
close(err[1]); |
| 431 |
if (dup2(inout[0], 0) < 0) /* stdin */ |
468 |
if (dup2(inout[0], 0) < 0) /* stdin */ |
| 432 |
perror("dup2 stdin"); |
469 |
perror("dup2 stdin"); |
| 433 |
if (dup2(inout[0], 1) < 0) /* stdout. Note: same socket as stdin. */ |
470 |
if (dup2(inout[0], 1) < 0) /* stdout (same as stdin) */ |
| 434 |
perror("dup2 stdout"); |
471 |
perror("dup2 stdout"); |
| 435 |
if (dup2(err[0], 2) < 0) /* stderr */ |
472 |
if (dup2(err[0], 2) < 0) /* stderr */ |
| 436 |
perror("dup2 stderr"); |
473 |
perror("dup2 stderr"); |
|
Lines 438-446
do_exec_no_pty(Session *s, const char *c
Link Here
|
| 438 |
/* Do processing for the child (exec command etc). */ |
475 |
/* Do processing for the child (exec command etc). */ |
| 439 |
do_child(s, command); |
476 |
do_child(s, command); |
| 440 |
/* NOTREACHED */ |
477 |
/* NOTREACHED */ |
|
|
478 |
default: |
| 479 |
break; |
| 441 |
} |
480 |
} |
| 442 |
if (pid < 0) |
481 |
|
| 443 |
packet_disconnect("fork failed: %.100s", strerror(errno)); |
|
|
| 444 |
s->pid = pid; |
482 |
s->pid = pid; |
| 445 |
/* Set interactive/non-interactive mode. */ |
483 |
/* Set interactive/non-interactive mode. */ |
| 446 |
packet_set_interactive(s->display != NULL); |
484 |
packet_set_interactive(s->display != NULL); |
|
Lines 454-464
do_exec_no_pty(Session *s, const char *c
Link Here
|
| 454 |
* handle the case that fdin and fdout are the same. |
492 |
* handle the case that fdin and fdout are the same. |
| 455 |
*/ |
493 |
*/ |
| 456 |
if (compat20) { |
494 |
if (compat20) { |
| 457 |
session_set_fds(s, inout[1], inout[1], s->is_subsystem ? -1 : err[1]); |
495 |
session_set_fds(s, inout[1], inout[1], |
|
|
496 |
s->is_subsystem ? -1 : err[1]); |
| 497 |
if (s->is_subsystem) |
| 498 |
close(err[1]); |
| 458 |
} else { |
499 |
} else { |
| 459 |
server_loop(pid, inout[1], inout[1], err[1]); |
500 |
server_loop(pid, inout[1], inout[1], err[1]); |
| 460 |
/* server_loop has closed inout[1] and err[1]. */ |
501 |
/* server_loop has closed inout[1] and err[1]. */ |
| 461 |
} |
502 |
} |
|
|
503 |
return 0; |
| 462 |
} |
504 |
} |
| 463 |
|
505 |
|
| 464 |
/* |
506 |
/* |
|
Lines 467-473
do_exec_no_pty(Session *s, const char *c
Link Here
|
| 467 |
* setting up file descriptors, controlling tty, updating wtmp, utmp, |
509 |
* setting up file descriptors, controlling tty, updating wtmp, utmp, |
| 468 |
* lastlog, and other such operations. |
510 |
* lastlog, and other such operations. |
| 469 |
*/ |
511 |
*/ |
| 470 |
void |
512 |
int |
| 471 |
do_exec_pty(Session *s, const char *command) |
513 |
do_exec_pty(Session *s, const char *command) |
| 472 |
{ |
514 |
{ |
| 473 |
int fdout, ptyfd, ttyfd, ptymaster; |
515 |
int fdout, ptyfd, ttyfd, ptymaster; |
|
Lines 478-489
do_exec_pty(Session *s, const char *comm
Link Here
|
| 478 |
ptyfd = s->ptyfd; |
520 |
ptyfd = s->ptyfd; |
| 479 |
ttyfd = s->ttyfd; |
521 |
ttyfd = s->ttyfd; |
| 480 |
|
522 |
|
|
|
523 |
/* |
| 524 |
* Create another descriptor of the pty master side for use as the |
| 525 |
* standard input. We could use the original descriptor, but this |
| 526 |
* simplifies code in server_loop. The descriptor is bidirectional. |
| 527 |
* Do this before forking (and cleanup in the child) so as to |
| 528 |
* detect and gracefully fail out-of-fd conditions. |
| 529 |
*/ |
| 530 |
if ((fdout = dup(ptyfd)) < 0) { |
| 531 |
error("%s: dup #1: %s", __func__, strerror(errno)); |
| 532 |
close(ttyfd); |
| 533 |
close(ptyfd); |
| 534 |
return -1; |
| 535 |
} |
| 536 |
/* we keep a reference to the pty master */ |
| 537 |
if ((ptymaster = dup(ptyfd)) < 0) { |
| 538 |
error("%s: dup #2: %s", __func__, strerror(errno)); |
| 539 |
close(ttyfd); |
| 540 |
close(ptyfd); |
| 541 |
close(fdout); |
| 542 |
return -1; |
| 543 |
} |
| 544 |
|
| 481 |
/* Fork the child. */ |
545 |
/* Fork the child. */ |
| 482 |
if ((pid = fork()) == 0) { |
546 |
switch ((pid = fork())) { |
|
|
547 |
case -1: |
| 548 |
error("%s: fork: %.100s", __func__, strerror(errno)); |
| 549 |
close(fdout); |
| 550 |
close(ptymaster); |
| 551 |
close(ttyfd); |
| 552 |
close(ptyfd); |
| 553 |
return -1; |
| 554 |
case 0: |
| 483 |
is_child = 1; |
555 |
is_child = 1; |
| 484 |
|
556 |
|
|
|
557 |
close(fdout); |
| 558 |
close(ptymaster); |
| 559 |
|
| 485 |
/* Child. Reinitialize the log because the pid has changed. */ |
560 |
/* Child. Reinitialize the log because the pid has changed. */ |
| 486 |
log_init(__progname, options.log_level, options.log_facility, log_stderr); |
561 |
log_init(__progname, options.log_level, |
|
|
562 |
options.log_facility, log_stderr); |
| 487 |
/* Close the master side of the pseudo tty. */ |
563 |
/* Close the master side of the pseudo tty. */ |
| 488 |
close(ptyfd); |
564 |
close(ptyfd); |
| 489 |
|
565 |
|
|
Lines 505-537
do_exec_pty(Session *s, const char *comm
Link Here
|
| 505 |
if (!(options.use_login && command == NULL)) |
581 |
if (!(options.use_login && command == NULL)) |
| 506 |
do_login(s, command); |
582 |
do_login(s, command); |
| 507 |
|
583 |
|
| 508 |
/* Do common processing for the child, such as execing the command. */ |
584 |
/* |
|
|
585 |
* Do common processing for the child, such as execing |
| 586 |
* the command. |
| 587 |
*/ |
| 509 |
do_child(s, command); |
588 |
do_child(s, command); |
| 510 |
/* NOTREACHED */ |
589 |
/* NOTREACHED */ |
|
|
590 |
default: |
| 591 |
break; |
| 511 |
} |
592 |
} |
| 512 |
if (pid < 0) |
|
|
| 513 |
packet_disconnect("fork failed: %.100s", strerror(errno)); |
| 514 |
s->pid = pid; |
593 |
s->pid = pid; |
| 515 |
|
594 |
|
| 516 |
/* Parent. Close the slave side of the pseudo tty. */ |
595 |
/* Parent. Close the slave side of the pseudo tty. */ |
| 517 |
close(ttyfd); |
596 |
close(ttyfd); |
| 518 |
|
597 |
|
| 519 |
/* |
|
|
| 520 |
* Create another descriptor of the pty master side for use as the |
| 521 |
* standard input. We could use the original descriptor, but this |
| 522 |
* simplifies code in server_loop. The descriptor is bidirectional. |
| 523 |
*/ |
| 524 |
fdout = dup(ptyfd); |
| 525 |
if (fdout < 0) |
| 526 |
packet_disconnect("dup #1 failed: %.100s", strerror(errno)); |
| 527 |
|
| 528 |
/* we keep a reference to the pty master */ |
| 529 |
ptymaster = dup(ptyfd); |
| 530 |
if (ptymaster < 0) |
| 531 |
packet_disconnect("dup #2 failed: %.100s", strerror(errno)); |
| 532 |
s->ptymaster = ptymaster; |
| 533 |
|
| 534 |
/* Enter interactive session. */ |
598 |
/* Enter interactive session. */ |
|
|
599 |
s->ptymaster = ptymaster; |
| 535 |
packet_set_interactive(1); |
600 |
packet_set_interactive(1); |
| 536 |
if (compat20) { |
601 |
if (compat20) { |
| 537 |
session_set_fds(s, ptyfd, fdout, -1); |
602 |
session_set_fds(s, ptyfd, fdout, -1); |
|
Lines 539-553
do_exec_pty(Session *s, const char *comm
Link Here
|
| 539 |
server_loop(pid, ptyfd, fdout, -1); |
604 |
server_loop(pid, ptyfd, fdout, -1); |
| 540 |
/* server_loop _has_ closed ptyfd and fdout. */ |
605 |
/* server_loop _has_ closed ptyfd and fdout. */ |
| 541 |
} |
606 |
} |
|
|
607 |
return 0; |
| 542 |
} |
608 |
} |
| 543 |
|
609 |
|
| 544 |
/* |
610 |
/* |
| 545 |
* This is called to fork and execute a command. If another command is |
611 |
* This is called to fork and execute a command. If another command is |
| 546 |
* to be forced, execute that instead. |
612 |
* to be forced, execute that instead. |
| 547 |
*/ |
613 |
*/ |
| 548 |
void |
614 |
int |
| 549 |
do_exec(Session *s, const char *command) |
615 |
do_exec(Session *s, const char *command) |
| 550 |
{ |
616 |
{ |
|
|
617 |
int ret; |
| 618 |
|
| 551 |
if (options.adm_forced_command) { |
619 |
if (options.adm_forced_command) { |
| 552 |
original_command = command; |
620 |
original_command = command; |
| 553 |
command = options.adm_forced_command; |
621 |
command = options.adm_forced_command; |
|
Lines 574-582
do_exec(Session *s, const char *command)
Link Here
|
| 574 |
} |
642 |
} |
| 575 |
#endif |
643 |
#endif |
| 576 |
if (s->ttyfd != -1) |
644 |
if (s->ttyfd != -1) |
| 577 |
do_exec_pty(s, command); |
645 |
ret = do_exec_pty(s, command); |
| 578 |
else |
646 |
else |
| 579 |
do_exec_no_pty(s, command); |
647 |
ret = do_exec_no_pty(s, command); |
| 580 |
|
648 |
|
| 581 |
original_command = NULL; |
649 |
original_command = NULL; |
| 582 |
|
650 |
|
|
Lines 586-591
do_exec(Session *s, const char *command)
Link Here
|
| 586 |
* multiple copies of the login messages. |
654 |
* multiple copies of the login messages. |
| 587 |
*/ |
655 |
*/ |
| 588 |
buffer_clear(&loginmsg); |
656 |
buffer_clear(&loginmsg); |
|
|
657 |
|
| 658 |
return ret; |
| 589 |
} |
659 |
} |
| 590 |
|
660 |
|
| 591 |
|
661 |
|
|
Lines 1291-1333
do_child(Session *s, const char *command
Link Here
|
| 1291 |
exit(1); |
1361 |
exit(1); |
| 1292 |
} |
1362 |
} |
| 1293 |
|
1363 |
|
|
|
1364 |
void |
| 1365 |
session_unused(int id) |
| 1366 |
{ |
| 1367 |
debug3("%s: session id %d unused", __func__, id); |
| 1368 |
if (id >= options.max_sessions || |
| 1369 |
id >= sessions_nalloc) { |
| 1370 |
fatal("%s: insane session id %d (max %d nalloc %d)", |
| 1371 |
__func__, id, options.max_sessions, sessions_nalloc); |
| 1372 |
} |
| 1373 |
bzero(&sessions[id], sizeof(*sessions)); |
| 1374 |
sessions[id].self = id; |
| 1375 |
sessions[id].used = 0; |
| 1376 |
sessions[id].chanid = -1; |
| 1377 |
sessions[id].ptyfd = -1; |
| 1378 |
sessions[id].ttyfd = -1; |
| 1379 |
sessions[id].ptymaster = -1; |
| 1380 |
sessions[id].x11_chanids = NULL; |
| 1381 |
sessions[id].next_unused = sessions_first_unused; |
| 1382 |
sessions_first_unused = id; |
| 1383 |
} |
| 1384 |
|
| 1294 |
Session * |
1385 |
Session * |
| 1295 |
session_new(void) |
1386 |
session_new(void) |
| 1296 |
{ |
1387 |
{ |
| 1297 |
int i; |
1388 |
Session *s, *tmp; |
| 1298 |
static int did_init = 0; |
1389 |
|
| 1299 |
if (!did_init) { |
1390 |
if (sessions_first_unused == -1) { |
| 1300 |
debug("session_new: init"); |
1391 |
if (sessions_nalloc >= options.max_sessions) |
| 1301 |
for (i = 0; i < MAX_SESSIONS; i++) { |
1392 |
return NULL; |
| 1302 |
sessions[i].used = 0; |
1393 |
debug2("%s: allocate (allocated %d max %d)", |
| 1303 |
} |
1394 |
__func__, sessions_nalloc, options.max_sessions); |
| 1304 |
did_init = 1; |
1395 |
tmp = xrealloc(sessions, sessions_nalloc + 1, |
| 1305 |
} |
1396 |
sizeof(*sessions)); |
| 1306 |
for (i = 0; i < MAX_SESSIONS; i++) { |
1397 |
if (tmp == NULL) { |
| 1307 |
Session *s = &sessions[i]; |
1398 |
error("%s: cannot allocate %d sessions", |
| 1308 |
if (! s->used) { |
1399 |
__func__, sessions_nalloc + 1); |
| 1309 |
memset(s, 0, sizeof(*s)); |
1400 |
return NULL; |
| 1310 |
s->chanid = -1; |
1401 |
} |
| 1311 |
s->ptyfd = -1; |
1402 |
sessions = tmp; |
| 1312 |
s->ttyfd = -1; |
1403 |
session_unused(sessions_nalloc++); |
| 1313 |
s->used = 1; |
1404 |
} |
| 1314 |
s->self = i; |
1405 |
|
| 1315 |
s->x11_chanids = NULL; |
1406 |
if (sessions_first_unused >= sessions_nalloc || |
| 1316 |
debug("session_new: session %d", i); |
1407 |
sessions_first_unused < 0) { |
| 1317 |
return s; |
1408 |
fatal("%s: insane first_unused %d max %d nalloc %d", |
| 1318 |
} |
1409 |
__func__, sessions_first_unused, options.max_sessions, |
| 1319 |
} |
1410 |
sessions_nalloc); |
| 1320 |
return NULL; |
1411 |
} |
|
|
1412 |
|
| 1413 |
s = &sessions[sessions_first_unused]; |
| 1414 |
if (s->used) { |
| 1415 |
fatal("%s: session %d already used", |
| 1416 |
__func__, sessions_first_unused); |
| 1417 |
} |
| 1418 |
sessions_first_unused = s->next_unused; |
| 1419 |
s->used = 1; |
| 1420 |
s->next_unused = -1; |
| 1421 |
debug("session_new: session %d", s->self); |
| 1422 |
|
| 1423 |
return s; |
| 1321 |
} |
1424 |
} |
| 1322 |
|
1425 |
|
| 1323 |
static void |
1426 |
static void |
| 1324 |
session_dump(void) |
1427 |
session_dump(void) |
| 1325 |
{ |
1428 |
{ |
| 1326 |
int i; |
1429 |
int i; |
| 1327 |
for (i = 0; i < MAX_SESSIONS; i++) { |
1430 |
for (i = 0; i < sessions_nalloc; i++) { |
| 1328 |
Session *s = &sessions[i]; |
1431 |
Session *s = &sessions[i]; |
| 1329 |
debug("dump: used %d session %d %p channel %d pid %ld", |
1432 |
|
|
|
1433 |
debug("dump: used %d next_unused %d session %d %p " |
| 1434 |
"channel %d pid %ld", |
| 1330 |
s->used, |
1435 |
s->used, |
|
|
1436 |
s->next_unused, |
| 1331 |
s->self, |
1437 |
s->self, |
| 1332 |
s, |
1438 |
s, |
| 1333 |
s->chanid, |
1439 |
s->chanid, |
|
Lines 1357-1363
Session *
Link Here
|
| 1357 |
session_by_tty(char *tty) |
1463 |
session_by_tty(char *tty) |
| 1358 |
{ |
1464 |
{ |
| 1359 |
int i; |
1465 |
int i; |
| 1360 |
for (i = 0; i < MAX_SESSIONS; i++) { |
1466 |
for (i = 0; i < sessions_nalloc; i++) { |
| 1361 |
Session *s = &sessions[i]; |
1467 |
Session *s = &sessions[i]; |
| 1362 |
if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) { |
1468 |
if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) { |
| 1363 |
debug("session_by_tty: session %d tty %s", i, tty); |
1469 |
debug("session_by_tty: session %d tty %s", i, tty); |
|
Lines 1373-1382
static Session *
Link Here
|
| 1373 |
session_by_channel(int id) |
1479 |
session_by_channel(int id) |
| 1374 |
{ |
1480 |
{ |
| 1375 |
int i; |
1481 |
int i; |
| 1376 |
for (i = 0; i < MAX_SESSIONS; i++) { |
1482 |
for (i = 0; i < sessions_nalloc; i++) { |
| 1377 |
Session *s = &sessions[i]; |
1483 |
Session *s = &sessions[i]; |
| 1378 |
if (s->used && s->chanid == id) { |
1484 |
if (s->used && s->chanid == id) { |
| 1379 |
debug("session_by_channel: session %d channel %d", i, id); |
1485 |
debug("session_by_channel: session %d channel %d", |
|
|
1486 |
i, id); |
| 1380 |
return s; |
1487 |
return s; |
| 1381 |
} |
1488 |
} |
| 1382 |
} |
1489 |
} |
|
Lines 1390-1396
session_by_x11_channel(int id)
Link Here
|
| 1390 |
{ |
1497 |
{ |
| 1391 |
int i, j; |
1498 |
int i, j; |
| 1392 |
|
1499 |
|
| 1393 |
for (i = 0; i < MAX_SESSIONS; i++) { |
1500 |
for (i = 0; i < sessions_nalloc; i++) { |
| 1394 |
Session *s = &sessions[i]; |
1501 |
Session *s = &sessions[i]; |
| 1395 |
|
1502 |
|
| 1396 |
if (s->x11_chanids == NULL || !s->used) |
1503 |
if (s->x11_chanids == NULL || !s->used) |
|
Lines 1413-1419
session_by_pid(pid_t pid)
Link Here
|
| 1413 |
{ |
1520 |
{ |
| 1414 |
int i; |
1521 |
int i; |
| 1415 |
debug("session_by_pid: pid %ld", (long)pid); |
1522 |
debug("session_by_pid: pid %ld", (long)pid); |
| 1416 |
for (i = 0; i < MAX_SESSIONS; i++) { |
1523 |
for (i = 0; i < sessions_nalloc; i++) { |
| 1417 |
Session *s = &sessions[i]; |
1524 |
Session *s = &sessions[i]; |
| 1418 |
if (s->used && s->pid == pid) |
1525 |
if (s->used && s->pid == pid) |
| 1419 |
return s; |
1526 |
return s; |
|
Lines 1469-1475
session_pty_req(Session *s)
Link Here
|
| 1469 |
|
1576 |
|
| 1470 |
/* Allocate a pty and open it. */ |
1577 |
/* Allocate a pty and open it. */ |
| 1471 |
debug("Allocating pty."); |
1578 |
debug("Allocating pty."); |
| 1472 |
if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) { |
1579 |
if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, |
|
|
1580 |
sizeof(s->tty)))) { |
| 1473 |
if (s->term) |
1581 |
if (s->term) |
| 1474 |
xfree(s->term); |
1582 |
xfree(s->term); |
| 1475 |
s->term = NULL; |
1583 |
s->term = NULL; |
|
Lines 1522-1529
session_subsystem_req(Session *s)
Link Here
|
| 1522 |
s->is_subsystem = SUBSYSTEM_EXT; |
1630 |
s->is_subsystem = SUBSYSTEM_EXT; |
| 1523 |
} |
1631 |
} |
| 1524 |
debug("subsystem: exec() %s", cmd); |
1632 |
debug("subsystem: exec() %s", cmd); |
| 1525 |
do_exec(s, cmd); |
1633 |
success = do_exec(s, cmd) == 0; |
| 1526 |
success = 1; |
|
|
| 1527 |
break; |
1634 |
break; |
| 1528 |
} |
1635 |
} |
| 1529 |
} |
1636 |
} |
|
Lines 1566-1584
static int
Link Here
|
| 1566 |
session_shell_req(Session *s) |
1673 |
session_shell_req(Session *s) |
| 1567 |
{ |
1674 |
{ |
| 1568 |
packet_check_eom(); |
1675 |
packet_check_eom(); |
| 1569 |
do_exec(s, NULL); |
1676 |
return do_exec(s, NULL) == 0; |
| 1570 |
return 1; |
|
|
| 1571 |
} |
1677 |
} |
| 1572 |
|
1678 |
|
| 1573 |
static int |
1679 |
static int |
| 1574 |
session_exec_req(Session *s) |
1680 |
session_exec_req(Session *s) |
| 1575 |
{ |
1681 |
{ |
| 1576 |
u_int len; |
1682 |
u_int len, success; |
|
|
1683 |
|
| 1577 |
char *command = packet_get_string(&len); |
1684 |
char *command = packet_get_string(&len); |
| 1578 |
packet_check_eom(); |
1685 |
packet_check_eom(); |
| 1579 |
do_exec(s, command); |
1686 |
success = do_exec(s, command) == 0; |
| 1580 |
xfree(command); |
1687 |
xfree(command); |
| 1581 |
return 1; |
1688 |
return success; |
| 1582 |
} |
1689 |
} |
| 1583 |
|
1690 |
|
| 1584 |
static int |
1691 |
static int |
|
Lines 1588-1595
session_break_req(Session *s)
Link Here
|
| 1588 |
packet_get_int(); /* ignored */ |
1695 |
packet_get_int(); /* ignored */ |
| 1589 |
packet_check_eom(); |
1696 |
packet_check_eom(); |
| 1590 |
|
1697 |
|
| 1591 |
if (s->ttyfd == -1 || |
1698 |
if (s->ttyfd == -1 || tcsendbreak(s->ttyfd, 0) < 0) |
| 1592 |
tcsendbreak(s->ttyfd, 0) < 0) |
|
|
| 1593 |
return 0; |
1699 |
return 0; |
| 1594 |
return 1; |
1700 |
return 1; |
| 1595 |
} |
1701 |
} |
|
Lines 1736-1743
session_pty_cleanup2(Session *s)
Link Here
|
| 1736 |
* the pty cleanup, so that another process doesn't get this pty |
1842 |
* the pty cleanup, so that another process doesn't get this pty |
| 1737 |
* while we're still cleaning up. |
1843 |
* while we're still cleaning up. |
| 1738 |
*/ |
1844 |
*/ |
| 1739 |
if (close(s->ptymaster) < 0) |
1845 |
if (s->ptymaster != -1 && close(s->ptymaster) < 0) |
| 1740 |
error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno)); |
1846 |
error("close(s->ptymaster/%d): %s", |
|
|
1847 |
s->ptymaster, strerror(errno)); |
| 1741 |
|
1848 |
|
| 1742 |
/* unlink pty from session */ |
1849 |
/* unlink pty from session */ |
| 1743 |
s->ttyfd = -1; |
1850 |
s->ttyfd = -1; |
|
Lines 1893-1899
session_close(Session *s)
Link Here
|
| 1893 |
xfree(s->auth_data); |
2000 |
xfree(s->auth_data); |
| 1894 |
if (s->auth_proto) |
2001 |
if (s->auth_proto) |
| 1895 |
xfree(s->auth_proto); |
2002 |
xfree(s->auth_proto); |
| 1896 |
s->used = 0; |
|
|
| 1897 |
if (s->env != NULL) { |
2003 |
if (s->env != NULL) { |
| 1898 |
for (i = 0; i < s->num_env; i++) { |
2004 |
for (i = 0; i < s->num_env; i++) { |
| 1899 |
xfree(s->env[i].name); |
2005 |
xfree(s->env[i].name); |
|
Lines 1902-1907
session_close(Session *s)
Link Here
|
| 1902 |
xfree(s->env); |
2008 |
xfree(s->env); |
| 1903 |
} |
2009 |
} |
| 1904 |
session_proctitle(s); |
2010 |
session_proctitle(s); |
|
|
2011 |
session_unused(s->self); |
| 1905 |
} |
2012 |
} |
| 1906 |
|
2013 |
|
| 1907 |
void |
2014 |
void |
|
Lines 1965-1971
void
Link Here
|
| 1965 |
session_destroy_all(void (*closefunc)(Session *)) |
2072 |
session_destroy_all(void (*closefunc)(Session *)) |
| 1966 |
{ |
2073 |
{ |
| 1967 |
int i; |
2074 |
int i; |
| 1968 |
for (i = 0; i < MAX_SESSIONS; i++) { |
2075 |
for (i = 0; i < sessions_nalloc; i++) { |
| 1969 |
Session *s = &sessions[i]; |
2076 |
Session *s = &sessions[i]; |
| 1970 |
if (s->used) { |
2077 |
if (s->used) { |
| 1971 |
if (closefunc != NULL) |
2078 |
if (closefunc != NULL) |
|
Lines 1982-1988
session_tty_list(void)
Link Here
|
| 1982 |
static char buf[1024]; |
2089 |
static char buf[1024]; |
| 1983 |
int i; |
2090 |
int i; |
| 1984 |
buf[0] = '\0'; |
2091 |
buf[0] = '\0'; |
| 1985 |
for (i = 0; i < MAX_SESSIONS; i++) { |
2092 |
for (i = 0; i < sessions_nalloc; i++) { |
| 1986 |
Session *s = &sessions[i]; |
2093 |
Session *s = &sessions[i]; |
| 1987 |
if (s->used && s->ttyfd != -1) { |
2094 |
if (s->used && s->ttyfd != -1) { |
| 1988 |
if (buf[0] != '\0') |
2095 |
if (buf[0] != '\0') |