1*63afb9a5SDavid du Colombier #include "ssh.h"
2*63afb9a5SDavid du Colombier
3*63afb9a5SDavid du Colombier static void
recv_ssh_smsg_public_key(Conn * c)4*63afb9a5SDavid du Colombier recv_ssh_smsg_public_key(Conn *c)
5*63afb9a5SDavid du Colombier {
6*63afb9a5SDavid du Colombier Msg *m;
7*63afb9a5SDavid du Colombier
8*63afb9a5SDavid du Colombier m = recvmsg(c, SSH_SMSG_PUBLIC_KEY);
9*63afb9a5SDavid du Colombier memmove(c->cookie, getbytes(m, COOKIELEN), COOKIELEN);
10*63afb9a5SDavid du Colombier c->serverkey = getRSApub(m);
11*63afb9a5SDavid du Colombier c->hostkey = getRSApub(m);
12*63afb9a5SDavid du Colombier c->flags = getlong(m);
13*63afb9a5SDavid du Colombier c->ciphermask = getlong(m);
14*63afb9a5SDavid du Colombier c->authmask = getlong(m);
15*63afb9a5SDavid du Colombier free(m);
16*63afb9a5SDavid du Colombier }
17*63afb9a5SDavid du Colombier
18*63afb9a5SDavid du Colombier static void
send_ssh_cmsg_session_key(Conn * c)19*63afb9a5SDavid du Colombier send_ssh_cmsg_session_key(Conn *c)
20*63afb9a5SDavid du Colombier {
21*63afb9a5SDavid du Colombier int i, n, buflen, serverkeylen, hostkeylen;
22*63afb9a5SDavid du Colombier mpint *b;
23*63afb9a5SDavid du Colombier uchar *buf;
24*63afb9a5SDavid du Colombier Msg *m;
25*63afb9a5SDavid du Colombier RSApub *ksmall, *kbig;
26*63afb9a5SDavid du Colombier
27*63afb9a5SDavid du Colombier m = allocmsg(c, SSH_CMSG_SESSION_KEY, 2048);
28*63afb9a5SDavid du Colombier putbyte(m, c->cipher->id);
29*63afb9a5SDavid du Colombier putbytes(m, c->cookie, COOKIELEN);
30*63afb9a5SDavid du Colombier
31*63afb9a5SDavid du Colombier serverkeylen = mpsignif(c->serverkey->n);
32*63afb9a5SDavid du Colombier hostkeylen = mpsignif(c->hostkey->n);
33*63afb9a5SDavid du Colombier ksmall = kbig = nil;
34*63afb9a5SDavid du Colombier if(serverkeylen+128 <= hostkeylen){
35*63afb9a5SDavid du Colombier ksmall = c->serverkey;
36*63afb9a5SDavid du Colombier kbig = c->hostkey;
37*63afb9a5SDavid du Colombier }else if(hostkeylen+128 <= serverkeylen){
38*63afb9a5SDavid du Colombier ksmall = c->hostkey;
39*63afb9a5SDavid du Colombier kbig = c->serverkey;
40*63afb9a5SDavid du Colombier }else
41*63afb9a5SDavid du Colombier error("server session and host keys do not differ by at least 128 bits");
42*63afb9a5SDavid du Colombier
43*63afb9a5SDavid du Colombier buflen = (mpsignif(kbig->n)+7)/8;
44*63afb9a5SDavid du Colombier buf = emalloc(buflen);
45*63afb9a5SDavid du Colombier
46*63afb9a5SDavid du Colombier debug(DBG_CRYPTO, "session key is %.*H\n", SESSKEYLEN, c->sesskey);
47*63afb9a5SDavid du Colombier memmove(buf, c->sesskey, SESSKEYLEN);
48*63afb9a5SDavid du Colombier for(i = 0; i < SESSIDLEN; i++)
49*63afb9a5SDavid du Colombier buf[i] ^= c->sessid[i];
50*63afb9a5SDavid du Colombier debug(DBG_CRYPTO, "munged session key is %.*H\n", SESSKEYLEN, buf);
51*63afb9a5SDavid du Colombier
52*63afb9a5SDavid du Colombier b = rsaencryptbuf(ksmall, buf, SESSKEYLEN);
53*63afb9a5SDavid du Colombier n = (mpsignif(ksmall->n)+7) / 8;
54*63afb9a5SDavid du Colombier mptoberjust(b, buf, n);
55*63afb9a5SDavid du Colombier mpfree(b);
56*63afb9a5SDavid du Colombier debug(DBG_CRYPTO, "encrypted with ksmall is %.*H\n", n, buf);
57*63afb9a5SDavid du Colombier
58*63afb9a5SDavid du Colombier b = rsaencryptbuf(kbig, buf, n);
59*63afb9a5SDavid du Colombier putmpint(m, b);
60*63afb9a5SDavid du Colombier debug(DBG_CRYPTO, "encrypted with kbig is %B\n", b);
61*63afb9a5SDavid du Colombier mpfree(b);
62*63afb9a5SDavid du Colombier
63*63afb9a5SDavid du Colombier memset(buf, 0, buflen);
64*63afb9a5SDavid du Colombier free(buf);
65*63afb9a5SDavid du Colombier
66*63afb9a5SDavid du Colombier putlong(m, c->flags);
67*63afb9a5SDavid du Colombier sendmsg(m);
68*63afb9a5SDavid du Colombier }
69*63afb9a5SDavid du Colombier
70*63afb9a5SDavid du Colombier static int
authuser(Conn * c)71*63afb9a5SDavid du Colombier authuser(Conn *c)
72*63afb9a5SDavid du Colombier {
73*63afb9a5SDavid du Colombier int i;
74*63afb9a5SDavid du Colombier Msg *m;
75*63afb9a5SDavid du Colombier
76*63afb9a5SDavid du Colombier m = allocmsg(c, SSH_CMSG_USER, 4+strlen(c->user));
77*63afb9a5SDavid du Colombier putstring(m, c->user);
78*63afb9a5SDavid du Colombier sendmsg(m);
79*63afb9a5SDavid du Colombier
80*63afb9a5SDavid du Colombier m = recvmsg(c, -1);
81*63afb9a5SDavid du Colombier switch(m->type){
82*63afb9a5SDavid du Colombier case SSH_SMSG_SUCCESS:
83*63afb9a5SDavid du Colombier free(m);
84*63afb9a5SDavid du Colombier return 0;
85*63afb9a5SDavid du Colombier case SSH_SMSG_FAILURE:
86*63afb9a5SDavid du Colombier free(m);
87*63afb9a5SDavid du Colombier break;
88*63afb9a5SDavid du Colombier default:
89*63afb9a5SDavid du Colombier badmsg(m, 0);
90*63afb9a5SDavid du Colombier }
91*63afb9a5SDavid du Colombier
92*63afb9a5SDavid du Colombier for(i=0; i<c->nokauth; i++){
93*63afb9a5SDavid du Colombier debug(DBG_AUTH, "authmask %#lux, consider %s (%#x)\n",
94*63afb9a5SDavid du Colombier c->authmask, c->okauth[i]->name, 1<<c->okauth[i]->id);
95*63afb9a5SDavid du Colombier if(c->authmask & (1<<c->okauth[i]->id))
96*63afb9a5SDavid du Colombier if((*c->okauth[i]->fn)(c) == 0)
97*63afb9a5SDavid du Colombier return 0;
98*63afb9a5SDavid du Colombier }
99*63afb9a5SDavid du Colombier
100*63afb9a5SDavid du Colombier debug(DBG_AUTH, "no auth methods worked; (authmask=%#lux)\n", c->authmask);
101*63afb9a5SDavid du Colombier return -1;
102*63afb9a5SDavid du Colombier }
103*63afb9a5SDavid du Colombier
104*63afb9a5SDavid du Colombier static char
ask(Conn * c,char * answers,char * question)105*63afb9a5SDavid du Colombier ask(Conn *c, char *answers, char *question)
106*63afb9a5SDavid du Colombier {
107*63afb9a5SDavid du Colombier int fd;
108*63afb9a5SDavid du Colombier char buf[256];
109*63afb9a5SDavid du Colombier
110*63afb9a5SDavid du Colombier if(!c->interactive)
111*63afb9a5SDavid du Colombier return answers[0];
112*63afb9a5SDavid du Colombier
113*63afb9a5SDavid du Colombier if((fd = open("/dev/cons", ORDWR)) < 0)
114*63afb9a5SDavid du Colombier return answers[0];
115*63afb9a5SDavid du Colombier
116*63afb9a5SDavid du Colombier fprint(fd, "%s", question);
117*63afb9a5SDavid du Colombier if(read(fd, buf, 256) <= 0 || buf[0]=='\n'){
118*63afb9a5SDavid du Colombier close(fd);
119*63afb9a5SDavid du Colombier return answers[0];
120*63afb9a5SDavid du Colombier }
121*63afb9a5SDavid du Colombier close(fd);
122*63afb9a5SDavid du Colombier return buf[0];
123*63afb9a5SDavid du Colombier }
124*63afb9a5SDavid du Colombier static void
checkkey(Conn * c)125*63afb9a5SDavid du Colombier checkkey(Conn *c)
126*63afb9a5SDavid du Colombier {
127*63afb9a5SDavid du Colombier char *home, *keyfile;
128*63afb9a5SDavid du Colombier
129*63afb9a5SDavid du Colombier debug(DBG_CRYPTO, "checking key %B %B\n", c->hostkey->n, c->hostkey->ek);
130*63afb9a5SDavid du Colombier switch(findkey("/sys/lib/ssh/keyring", c->aliases, c->hostkey)){
131*63afb9a5SDavid du Colombier default:
132*63afb9a5SDavid du Colombier abort();
133*63afb9a5SDavid du Colombier case KeyOk:
134*63afb9a5SDavid du Colombier return;
135*63afb9a5SDavid du Colombier case KeyWrong:
136*63afb9a5SDavid du Colombier fprint(2, "server presented public key different than expected\n");
137*63afb9a5SDavid du Colombier fprint(2, "(expected key in /sys/lib/ssh/keyring). will not continue.\n");
138*63afb9a5SDavid du Colombier error("bad server key");
139*63afb9a5SDavid du Colombier
140*63afb9a5SDavid du Colombier case NoKey:
141*63afb9a5SDavid du Colombier case NoKeyFile:
142*63afb9a5SDavid du Colombier break;
143*63afb9a5SDavid du Colombier }
144*63afb9a5SDavid du Colombier
145*63afb9a5SDavid du Colombier home = getenv("home");
146*63afb9a5SDavid du Colombier if(home == nil){
147*63afb9a5SDavid du Colombier fprint(2, "server %s not on keyring; will not continue.\n", c->host);
148*63afb9a5SDavid du Colombier error("bad server key");
149*63afb9a5SDavid du Colombier }
150*63afb9a5SDavid du Colombier
151*63afb9a5SDavid du Colombier keyfile = smprint("%s/lib/keyring", home);
152*63afb9a5SDavid du Colombier if(keyfile == nil)
153*63afb9a5SDavid du Colombier error("out of memory");
154*63afb9a5SDavid du Colombier
155*63afb9a5SDavid du Colombier switch(findkey(keyfile, c->aliases, c->hostkey)){
156*63afb9a5SDavid du Colombier default:
157*63afb9a5SDavid du Colombier abort();
158*63afb9a5SDavid du Colombier case KeyOk:
159*63afb9a5SDavid du Colombier return;
160*63afb9a5SDavid du Colombier case KeyWrong:
161*63afb9a5SDavid du Colombier fprint(2, "server %s presented public key different than expected\n", c->host);
162*63afb9a5SDavid du Colombier fprint(2, "(expected key in %s). will not continue.\n", keyfile);
163*63afb9a5SDavid du Colombier fprint(2, "this could be a man-in-the-middle attack.\n");
164*63afb9a5SDavid du Colombier switch(ask(c, "eri", "replace key in keyfile (r), continue without replacing key (c), or exit (e) [e]")){
165*63afb9a5SDavid du Colombier case 'e':
166*63afb9a5SDavid du Colombier error("bad key");
167*63afb9a5SDavid du Colombier case 'r':
168*63afb9a5SDavid du Colombier if(replacekey(keyfile, c->aliases, c->hostkey) < 0)
169*63afb9a5SDavid du Colombier error("replacekey: %r");
170*63afb9a5SDavid du Colombier break;
171*63afb9a5SDavid du Colombier case 'c':
172*63afb9a5SDavid du Colombier break;
173*63afb9a5SDavid du Colombier }
174*63afb9a5SDavid du Colombier return;
175*63afb9a5SDavid du Colombier case NoKey:
176*63afb9a5SDavid du Colombier case NoKeyFile:
177*63afb9a5SDavid du Colombier fprint(2, "server %s not on keyring.\n", c->host);
178*63afb9a5SDavid du Colombier switch(ask(c, "eac", "add key to keyfile (a), continue without adding key (c), or exit (e) [e]")){
179*63afb9a5SDavid du Colombier case 'e':
180*63afb9a5SDavid du Colombier error("bad key");
181*63afb9a5SDavid du Colombier case 'a':
182*63afb9a5SDavid du Colombier if(appendkey(keyfile, c->aliases, c->hostkey) < 0)
183*63afb9a5SDavid du Colombier error("appendkey: %r");
184*63afb9a5SDavid du Colombier break;
185*63afb9a5SDavid du Colombier case 'c':
186*63afb9a5SDavid du Colombier break;
187*63afb9a5SDavid du Colombier }
188*63afb9a5SDavid du Colombier return;
189*63afb9a5SDavid du Colombier }
190*63afb9a5SDavid du Colombier }
191*63afb9a5SDavid du Colombier
192*63afb9a5SDavid du Colombier void
sshclienthandshake(Conn * c)193*63afb9a5SDavid du Colombier sshclienthandshake(Conn *c)
194*63afb9a5SDavid du Colombier {
195*63afb9a5SDavid du Colombier char buf[128], *p;
196*63afb9a5SDavid du Colombier int i;
197*63afb9a5SDavid du Colombier Msg *m;
198*63afb9a5SDavid du Colombier
199*63afb9a5SDavid du Colombier /* receive id string */
200*63afb9a5SDavid du Colombier if(readstrnl(c->fd[0], buf, sizeof buf) < 0)
201*63afb9a5SDavid du Colombier error("reading server version: %r");
202*63afb9a5SDavid du Colombier
203*63afb9a5SDavid du Colombier /* id string is "SSH-m.n-comment". We need m=1, n>=5. */
204*63afb9a5SDavid du Colombier if(strncmp(buf, "SSH-", 4) != 0
205*63afb9a5SDavid du Colombier || strtol(buf+4, &p, 10) != 1
206*63afb9a5SDavid du Colombier || *p != '.'
207*63afb9a5SDavid du Colombier || strtol(p+1, &p, 10) < 5
208*63afb9a5SDavid du Colombier || *p != '-')
209*63afb9a5SDavid du Colombier error("protocol mismatch; got %s, need SSH-1.x for x>=5", buf);
210*63afb9a5SDavid du Colombier
211*63afb9a5SDavid du Colombier /* send id string */
212*63afb9a5SDavid du Colombier fprint(c->fd[1], "SSH-1.5-Plan 9\n");
213*63afb9a5SDavid du Colombier
214*63afb9a5SDavid du Colombier recv_ssh_smsg_public_key(c);
215*63afb9a5SDavid du Colombier checkkey(c);
216*63afb9a5SDavid du Colombier
217*63afb9a5SDavid du Colombier for(i=0; i<SESSKEYLEN; i++)
218*63afb9a5SDavid du Colombier c->sesskey[i] = fastrand();
219*63afb9a5SDavid du Colombier c->cipher = nil;
220*63afb9a5SDavid du Colombier for(i=0; i<c->nokcipher; i++)
221*63afb9a5SDavid du Colombier if((1<<c->okcipher[i]->id) & c->ciphermask){
222*63afb9a5SDavid du Colombier c->cipher = c->okcipher[i];
223*63afb9a5SDavid du Colombier break;
224*63afb9a5SDavid du Colombier }
225*63afb9a5SDavid du Colombier if(c->cipher == nil)
226*63afb9a5SDavid du Colombier error("can't agree on ciphers: remote side supports %#lux", c->ciphermask);
227*63afb9a5SDavid du Colombier
228*63afb9a5SDavid du Colombier calcsessid(c);
229*63afb9a5SDavid du Colombier
230*63afb9a5SDavid du Colombier send_ssh_cmsg_session_key(c);
231*63afb9a5SDavid du Colombier
232*63afb9a5SDavid du Colombier c->cstate = (*c->cipher->init)(c, 0); /* turns on encryption */
233*63afb9a5SDavid du Colombier m = recvmsg(c, SSH_SMSG_SUCCESS);
234*63afb9a5SDavid du Colombier free(m);
235*63afb9a5SDavid du Colombier
236*63afb9a5SDavid du Colombier if(authuser(c) < 0)
237*63afb9a5SDavid du Colombier error("client authentication failed");
238*63afb9a5SDavid du Colombier }
239*63afb9a5SDavid du Colombier
240*63afb9a5SDavid du Colombier static int
intgetenv(char * name,int def)241*63afb9a5SDavid du Colombier intgetenv(char *name, int def)
242*63afb9a5SDavid du Colombier {
243*63afb9a5SDavid du Colombier char *s;
244*63afb9a5SDavid du Colombier int n, val;
245*63afb9a5SDavid du Colombier
246*63afb9a5SDavid du Colombier val = def;
247*63afb9a5SDavid du Colombier if((s = getenv(name))!=nil){
248*63afb9a5SDavid du Colombier if((n=atoi(s)) > 0)
249*63afb9a5SDavid du Colombier val = n;
250*63afb9a5SDavid du Colombier free(s);
251*63afb9a5SDavid du Colombier }
252*63afb9a5SDavid du Colombier return val;
253*63afb9a5SDavid du Colombier }
254*63afb9a5SDavid du Colombier
255*63afb9a5SDavid du Colombier /*
256*63afb9a5SDavid du Colombier * assumes that if you care, you're running under vt
257*63afb9a5SDavid du Colombier * and therefore these are set.
258*63afb9a5SDavid du Colombier */
259*63afb9a5SDavid du Colombier int
readgeom(int * nrow,int * ncol,int * width,int * height)260*63afb9a5SDavid du Colombier readgeom(int *nrow, int *ncol, int *width, int *height)
261*63afb9a5SDavid du Colombier {
262*63afb9a5SDavid du Colombier static int fd = -1;
263*63afb9a5SDavid du Colombier char buf[64];
264*63afb9a5SDavid du Colombier
265*63afb9a5SDavid du Colombier if(fd < 0 && (fd = open("/dev/wctl", OREAD)) < 0)
266*63afb9a5SDavid du Colombier return -1;
267*63afb9a5SDavid du Colombier /* wait for event, but don't care what it says */
268*63afb9a5SDavid du Colombier if(read(fd, buf, sizeof buf) < 0)
269*63afb9a5SDavid du Colombier return -1;
270*63afb9a5SDavid du Colombier *nrow = intgetenv("LINES", 24);
271*63afb9a5SDavid du Colombier *ncol = intgetenv("COLS", 80);
272*63afb9a5SDavid du Colombier *width = intgetenv("XPIXELS", 640);
273*63afb9a5SDavid du Colombier *height = intgetenv("YPIXELS", 480);
274*63afb9a5SDavid du Colombier return 0;
275*63afb9a5SDavid du Colombier }
276*63afb9a5SDavid du Colombier
277*63afb9a5SDavid du Colombier void
sendwindowsize(Conn * c,int nrow,int ncol,int width,int height)278*63afb9a5SDavid du Colombier sendwindowsize(Conn *c, int nrow, int ncol, int width, int height)
279*63afb9a5SDavid du Colombier {
280*63afb9a5SDavid du Colombier Msg *m;
281*63afb9a5SDavid du Colombier
282*63afb9a5SDavid du Colombier m = allocmsg(c, SSH_CMSG_WINDOW_SIZE, 4*4);
283*63afb9a5SDavid du Colombier putlong(m, nrow);
284*63afb9a5SDavid du Colombier putlong(m, ncol);
285*63afb9a5SDavid du Colombier putlong(m, width);
286*63afb9a5SDavid du Colombier putlong(m, height);
287*63afb9a5SDavid du Colombier sendmsg(m);
288*63afb9a5SDavid du Colombier }
289*63afb9a5SDavid du Colombier
290*63afb9a5SDavid du Colombier /*
291*63afb9a5SDavid du Colombier * In each option line, the first byte is the option number
292*63afb9a5SDavid du Colombier * and the second is either a boolean bit or actually an
293*63afb9a5SDavid du Colombier * ASCII code.
294*63afb9a5SDavid du Colombier */
295*63afb9a5SDavid du Colombier static uchar ptyopt[] =
296*63afb9a5SDavid du Colombier {
297*63afb9a5SDavid du Colombier 0x01, 0x7F, /* interrupt = DEL */
298*63afb9a5SDavid du Colombier 0x02, 0x11, /* quit = ^Q */
299*63afb9a5SDavid du Colombier 0x03, 0x08, /* backspace = ^H */
300*63afb9a5SDavid du Colombier 0x04, 0x15, /* line kill = ^U */
301*63afb9a5SDavid du Colombier 0x05, 0x04, /* EOF = ^D */
302*63afb9a5SDavid du Colombier 0x20, 0x00, /* don't strip high bit */
303*63afb9a5SDavid du Colombier 0x48, 0x01, /* give us CRs */
304*63afb9a5SDavid du Colombier
305*63afb9a5SDavid du Colombier 0x00, /* end options */
306*63afb9a5SDavid du Colombier };
307*63afb9a5SDavid du Colombier
308*63afb9a5SDavid du Colombier static uchar rawptyopt[] =
309*63afb9a5SDavid du Colombier {
310*63afb9a5SDavid du Colombier 30, 0, /* ignpar */
311*63afb9a5SDavid du Colombier 31, 0, /* parmrk */
312*63afb9a5SDavid du Colombier 32, 0, /* inpck */
313*63afb9a5SDavid du Colombier 33, 0, /* istrip */
314*63afb9a5SDavid du Colombier 34, 0, /* inlcr */
315*63afb9a5SDavid du Colombier 35, 0, /* igncr */
316*63afb9a5SDavid du Colombier 36, 0, /* icnrl */
317*63afb9a5SDavid du Colombier 37, 0, /* iuclc */
318*63afb9a5SDavid du Colombier 38, 0, /* ixon */
319*63afb9a5SDavid du Colombier 39, 1, /* ixany */
320*63afb9a5SDavid du Colombier 40, 0, /* ixoff */
321*63afb9a5SDavid du Colombier 41, 0, /* imaxbel */
322*63afb9a5SDavid du Colombier
323*63afb9a5SDavid du Colombier 50, 0, /* isig: intr, quit, susp processing */
324*63afb9a5SDavid du Colombier 51, 0, /* icanon: erase and kill processing */
325*63afb9a5SDavid du Colombier 52, 0, /* xcase */
326*63afb9a5SDavid du Colombier
327*63afb9a5SDavid du Colombier 53, 0, /* echo */
328*63afb9a5SDavid du Colombier
329*63afb9a5SDavid du Colombier 57, 0, /* noflsh */
330*63afb9a5SDavid du Colombier 58, 0, /* tostop */
331*63afb9a5SDavid du Colombier 59, 0, /* iexten: impl defined control chars */
332*63afb9a5SDavid du Colombier
333*63afb9a5SDavid du Colombier 70, 0, /* opost */
334*63afb9a5SDavid du Colombier
335*63afb9a5SDavid du Colombier 0x00,
336*63afb9a5SDavid du Colombier };
337*63afb9a5SDavid du Colombier
338*63afb9a5SDavid du Colombier void
requestpty(Conn * c)339*63afb9a5SDavid du Colombier requestpty(Conn *c)
340*63afb9a5SDavid du Colombier {
341*63afb9a5SDavid du Colombier char *term;
342*63afb9a5SDavid du Colombier int nrow, ncol, width, height;
343*63afb9a5SDavid du Colombier Msg *m;
344*63afb9a5SDavid du Colombier
345*63afb9a5SDavid du Colombier m = allocmsg(c, SSH_CMSG_REQUEST_PTY, 1024);
346*63afb9a5SDavid du Colombier if((term = getenv("TERM")) == nil)
347*63afb9a5SDavid du Colombier term = "9term";
348*63afb9a5SDavid du Colombier putstring(m, term);
349*63afb9a5SDavid du Colombier
350*63afb9a5SDavid du Colombier readgeom(&nrow, &ncol, &width, &height);
351*63afb9a5SDavid du Colombier putlong(m, nrow); /* characters */
352*63afb9a5SDavid du Colombier putlong(m, ncol);
353*63afb9a5SDavid du Colombier putlong(m, width); /* pixels */
354*63afb9a5SDavid du Colombier putlong(m, height);
355*63afb9a5SDavid du Colombier
356*63afb9a5SDavid du Colombier if(rawhack)
357*63afb9a5SDavid du Colombier putbytes(m, rawptyopt, sizeof rawptyopt);
358*63afb9a5SDavid du Colombier else
359*63afb9a5SDavid du Colombier putbytes(m, ptyopt, sizeof ptyopt);
360*63afb9a5SDavid du Colombier
361*63afb9a5SDavid du Colombier sendmsg(m);
362*63afb9a5SDavid du Colombier
363*63afb9a5SDavid du Colombier m = recvmsg(c, 0);
364*63afb9a5SDavid du Colombier switch(m->type){
365*63afb9a5SDavid du Colombier case SSH_SMSG_SUCCESS:
366*63afb9a5SDavid du Colombier debug(DBG_IO, "PTY allocated\n");
367*63afb9a5SDavid du Colombier break;
368*63afb9a5SDavid du Colombier case SSH_SMSG_FAILURE:
369*63afb9a5SDavid du Colombier debug(DBG_IO, "PTY allocation failed\n");
370*63afb9a5SDavid du Colombier break;
371*63afb9a5SDavid du Colombier default:
372*63afb9a5SDavid du Colombier badmsg(m, 0);
373*63afb9a5SDavid du Colombier }
374*63afb9a5SDavid du Colombier free(m);
375*63afb9a5SDavid du Colombier }
376*63afb9a5SDavid du Colombier
377