~ubuntu-branches/ubuntu/precise/dropbear/precise

« back to all changes in this revision

Viewing changes to svr-chansession.c

  • Committer: Bazaar Package Importer
  • Author(s): Gerrit Pape
  • Date: 2007-03-02 20:48:18 UTC
  • mfrom: (1.3.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20070302204818-ozmbou2sbyj7dus5
Tags: 0.49-1
* new upstream release, fixes
  * CVE-2007-1099: dropbear dbclient insufficient warning on hostkey
    mismatch (closes: #412899).
  * dbclient uses static "Password:" prompt instead of using the server's
    prompt (closes: #394996).
* debian/control: Suggests: openssh-client, not ssh (closes: #405686);
  Standards-Version: 3.7.2.2.
* debian/README.Debian: ssh -> openssh-server, openssh-client; remove
  'Replacing OpenSSH "sshd" with Dropbear' part, this is simply done by not
  installing the openssh-server package.
* debian/README.runit: runsvstat -> sv status.

Show diffs side-by-side

added added

removed removed

Lines of Context:
59
59
                struct ChanSess * chansess);
60
60
static void send_msg_chansess_exitsignal(struct Channel * channel,
61
61
                struct ChanSess * chansess);
62
 
static int sesscheckclose(struct Channel *channel);
63
62
static void get_termmodes(struct ChanSess *chansess);
64
63
 
65
64
 
68
67
 
69
68
static int sesscheckclose(struct Channel *channel) {
70
69
        struct ChanSess *chansess = (struct ChanSess*)channel->typedata;
71
 
        return chansess->exit.exitpid >= 0;
 
70
        TRACE(("sesscheckclose, pid is %d", chansess->exit.exitpid))
 
71
        return chansess->exit.exitpid != -1;
72
72
}
73
73
 
74
74
/* Handler for childs exiting, store the state for return to the client */
89
89
 
90
90
        TRACE(("enter sigchld handler"))
91
91
        while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
 
92
                TRACE(("sigchld handler: pid %d", pid))
 
93
 
 
94
                exit = NULL;
92
95
                /* find the corresponding chansess */
93
96
                for (i = 0; i < svr_ses.childpidsize; i++) {
94
97
                        if (svr_ses.childpids[i].pid == pid) {
95
 
 
 
98
                                TRACE(("found match session"));
96
99
                                exit = &svr_ses.childpids[i].chansess->exit;
97
100
                                break;
98
101
                        }
100
103
 
101
104
                /* If the pid wasn't matched, then we might have hit the race mentioned
102
105
                 * above. So we just store the info for the parent to deal with */
103
 
                if (i == svr_ses.childpidsize) {
 
106
                if (exit == NULL) {
 
107
                        TRACE(("using lastexit"));
104
108
                        exit = &svr_ses.lastexit;
105
109
                }
106
110
 
119
123
                        /* we use this to determine how pid exited */
120
124
                        exit->exitsignal = -1;
121
125
                }
122
 
                exit = NULL;
 
126
                
 
127
                /* Make sure that the main select() loop wakes up */
 
128
                while (1) {
 
129
                        /* isserver is just a random byte to write. We can't do anything
 
130
                        about an error so should just ignore it */
 
131
                        if (write(ses.signal_pipe[1], &ses.isserver, 1) == 1
 
132
                                        || errno != EINTR) {
 
133
                                break;
 
134
                        }
 
135
                }
123
136
        }
124
137
 
125
 
        
126
138
        sa_chld.sa_handler = sesssigchild_handler;
127
139
        sa_chld.sa_flags = SA_NOCLDSTOP;
128
140
        sigaction(SIGCHLD, &sa_chld, NULL);
130
142
}
131
143
 
132
144
/* send the exit status or the signal causing termination for a session */
133
 
/* XXX server */
134
145
static void send_exitsignalstatus(struct Channel *channel) {
135
146
 
136
147
        struct ChanSess *chansess = (struct ChanSess*)channel->typedata;
169
180
 
170
181
        int i;
171
182
        char* signame = NULL;
172
 
 
173
183
        dropbear_assert(chansess->exit.exitpid != -1);
174
184
        dropbear_assert(chansess->exit.exitsignal > 0);
175
185
 
 
186
        TRACE(("send_msg_chansess_exitsignal %d", chansess->exit.exitsignal))
 
187
 
176
188
        CHECKCLEARTOWRITE();
177
189
 
178
190
        /* we check that we can match a signal name, otherwise
244
256
        unsigned int i;
245
257
        struct logininfo *li;
246
258
 
247
 
        chansess = (struct ChanSess*)channel->typedata;
248
 
 
249
 
        send_exitsignalstatus(channel);
250
 
 
251
259
        TRACE(("enter closechansess"))
 
260
 
 
261
        chansess = (struct ChanSess*)channel->typedata;
 
262
 
252
263
        if (chansess == NULL) {
253
264
                TRACE(("leave closechansess: chansess == NULL"))
254
265
                return;
255
266
        }
256
267
 
 
268
        send_exitsignalstatus(channel);
 
269
 
257
270
        m_free(chansess->cmd);
258
271
        m_free(chansess->term);
259
272
 
281
294
                if (svr_ses.childpids[i].chansess == chansess) {
282
295
                        dropbear_assert(svr_ses.childpids[i].pid > 0);
283
296
                        TRACE(("closing pid %d", svr_ses.childpids[i].pid))
284
 
                        TRACE(("exitpid = %d", chansess->exit.exitpid))
 
297
                        TRACE(("exitpid is %d", chansess->exit.exitpid))
285
298
                        svr_ses.childpids[i].pid = -1;
286
299
                        svr_ses.childpids[i].chansess = NULL;
287
300
                }
410
423
        
411
424
        pty_change_window_size(chansess->master, termr, termc, termw, termh);
412
425
 
413
 
        return DROPBEAR_FAILURE;
 
426
        return DROPBEAR_SUCCESS;
414
427
}
415
428
 
416
429
static void get_termmodes(struct ChanSess *chansess) {
588
601
                }
589
602
        }
590
603
 
 
604
#ifdef LOG_COMMANDS
 
605
        if (chansess->cmd) {
 
606
                dropbear_log(LOG_INFO, "user %s executing '%s'", 
 
607
                                                ses.authstate.printableuser, chansess->cmd);
 
608
        } else {
 
609
                dropbear_log(LOG_INFO, "user %s executing login shell", 
 
610
                                                ses.authstate.printableuser);
 
611
        }
 
612
#endif
 
613
 
591
614
        if (chansess->term == NULL) {
592
615
                /* no pty */
593
616
                ret = noptycommand(channel, chansess);
635
658
        if (!pid) {
636
659
                /* child */
637
660
 
 
661
                TRACE(("back to normal sigchld"))
 
662
                /* Revert to normal sigchld handling */
 
663
                if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) {
 
664
                        dropbear_exit("signal() error");
 
665
                }
 
666
 
638
667
                /* redirect stdin/stdout */
639
668
#define FDIN 0
640
669
#define FDOUT 1
659
688
                /* parent */
660
689
                TRACE(("continue noptycommand: parent"))
661
690
                chansess->pid = pid;
 
691
                TRACE(("child pid is %d", pid))
662
692
 
663
693
                addchildpid(chansess, pid);
664
694
 
665
695
                if (svr_ses.lastexit.exitpid != -1) {
 
696
                        TRACE(("parent side: lastexitpid is %d", svr_ses.lastexit.exitpid))
666
697
                        /* The child probably exited and the signal handler triggered
667
698
                         * possibly before we got around to adding the childpid. So we fill
668
 
                         * out it's data manually */
 
699
                         * out its data manually */
669
700
                        for (i = 0; i < svr_ses.childpidsize; i++) {
670
 
                                if (svr_ses.childpids[i].pid == pid) {
 
701
                                if (svr_ses.childpids[i].pid == svr_ses.lastexit.exitpid) {
 
702
                                        TRACE(("found match for lastexitpid"))
671
703
                                        svr_ses.childpids[i].chansess->exit = svr_ses.lastexit;
672
704
                                        svr_ses.lastexit.exitpid = -1;
673
705
                                }
674
706
                        }
675
707
                }
676
708
 
677
 
 
678
709
                close(infds[FDIN]);
679
710
                close(outfds[FDOUT]);
680
711
                close(errfds[FDOUT]);
730
761
        if (pid == 0) {
731
762
                /* child */
732
763
                
 
764
                TRACE(("back to normal sigchld"))
 
765
                /* Revert to normal sigchld handling */
 
766
                if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) {
 
767
                        dropbear_exit("signal() error");
 
768
                }
 
769
                
733
770
                /* redirect stdin/stdout/stderr */
734
771
                close(chansess->master);
735
772
 
997
1034
        newvar[plen] = '=';
998
1035
        memcpy(&newvar[plen+1], var, vlen);
999
1036
        newvar[plen+vlen+1] = '\0';
 
1037
        /* newvar is leaked here, but that's part of putenv()'s semantics */
1000
1038
        if (putenv(newvar) < 0) {
1001
1039
                dropbear_exit("environ error");
1002
1040
        }