OpenCoverage

ttymodes.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/openssh/src/ttymodes.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/* $OpenBSD: ttymodes.c,v 1.34 2018/07/09 21:20:26 markus Exp $ */-
2/*-
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>-
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland-
5 * All rights reserved-
6 *-
7 * As far as I am concerned, the code I have written for this software-
8 * can be used freely for any purpose. Any derived versions of this-
9 * software must be clearly marked as such, and if the derived work is-
10 * incompatible with the protocol description in the RFC file, it must be-
11 * called by a name other than "ssh" or "Secure Shell".-
12 */-
13-
14/*-
15 * SSH2 tty modes support by Kevin Steves.-
16 * Copyright (c) 2001 Kevin Steves. All rights reserved.-
17 *-
18 * Redistribution and use in source and binary forms, with or without-
19 * modification, are permitted provided that the following conditions-
20 * are met:-
21 * 1. Redistributions of source code must retain the above copyright-
22 * notice, this list of conditions and the following disclaimer.-
23 * 2. Redistributions in binary form must reproduce the above copyright-
24 * notice, this list of conditions and the following disclaimer in the-
25 * documentation and/or other materials provided with the distribution.-
26 *-
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR-
28 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES-
29 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.-
30 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,-
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT-
32 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,-
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY-
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT-
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF-
36 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.-
37 */-
38-
39/*-
40 * Encoding and decoding of terminal modes in a portable way.-
41 * Much of the format is defined in ttymodes.h; it is included multiple times-
42 * into this file with the appropriate macro definitions to generate the-
43 * suitable code.-
44 */-
45-
46#include "includes.h"-
47-
48#include <sys/types.h>-
49-
50#include <errno.h>-
51#include <string.h>-
52#include <termios.h>-
53#include <stdarg.h>-
54-
55#include "packet.h"-
56#include "log.h"-
57#include "compat.h"-
58#include "sshbuf.h"-
59#include "ssherr.h"-
60-
61#define TTY_OP_END 0-
62/*-
63 * uint32 (u_int) follows speed.-
64 */-
65#define TTY_OP_ISPEED 128-
66#define TTY_OP_OSPEED 129-
67-
68/*-
69 * Converts POSIX speed_t to a baud rate. The values of the-
70 * constants for speed_t are not themselves portable.-
71 */-
72static int-
73speed_to_baud(speed_t speed)-
74{-
75 switch (speed) {-
76 case B0:
never executed: case 0000000 :
0
77 return 0;
never executed: return 0;
0
78 case B50:
never executed: case 0000001 :
0
79 return 50;
never executed: return 50;
0
80 case B75:
never executed: case 0000002 :
0
81 return 75;
never executed: return 75;
0
82 case B110:
never executed: case 0000003 :
0
83 return 110;
never executed: return 110;
0
84 case B134:
never executed: case 0000004 :
0
85 return 134;
never executed: return 134;
0
86 case B150:
never executed: case 0000005 :
0
87 return 150;
never executed: return 150;
0
88 case B200:
never executed: case 0000006 :
0
89 return 200;
never executed: return 200;
0
90 case B300:
never executed: case 0000007 :
0
91 return 300;
never executed: return 300;
0
92 case B600:
never executed: case 0000010 :
0
93 return 600;
never executed: return 600;
0
94 case B1200:
never executed: case 0000011 :
0
95 return 1200;
never executed: return 1200;
0
96 case B1800:
never executed: case 0000012 :
0
97 return 1800;
never executed: return 1800;
0
98 case B2400:
never executed: case 0000013 :
0
99 return 2400;
never executed: return 2400;
0
100 case B4800:
never executed: case 0000014 :
0
101 return 4800;
never executed: return 4800;
0
102 case B9600:
never executed: case 0000015 :
0
103 return 9600;
never executed: return 9600;
0
104-
105#ifdef B19200-
106 case B19200:
never executed: case 0000016 :
0
107 return 19200;
never executed: return 19200;
0
108#else /* B19200 */-
109#ifdef EXTA-
110 case EXTA:-
111 return 19200;-
112#endif /* EXTA */-
113#endif /* B19200 */-
114-
115#ifdef B38400-
116 case B38400:
never executed: case 0000017 :
0
117 return 38400;
never executed: return 38400;
0
118#else /* B38400 */-
119#ifdef EXTB-
120 case EXTB:-
121 return 38400;-
122#endif /* EXTB */-
123#endif /* B38400 */-
124-
125#ifdef B7200-
126 case B7200:-
127 return 7200;-
128#endif /* B7200 */-
129#ifdef B14400-
130 case B14400:-
131 return 14400;-
132#endif /* B14400 */-
133#ifdef B28800-
134 case B28800:-
135 return 28800;-
136#endif /* B28800 */-
137#ifdef B57600-
138 case B57600:
never executed: case 0010001 :
0
139 return 57600;
never executed: return 57600;
0
140#endif /* B57600 */-
141#ifdef B76800-
142 case B76800:-
143 return 76800;-
144#endif /* B76800 */-
145#ifdef B115200-
146 case B115200:
never executed: case 0010002 :
0
147 return 115200;
never executed: return 115200;
0
148#endif /* B115200 */-
149#ifdef B230400-
150 case B230400:
never executed: case 0010003 :
0
151 return 230400;
never executed: return 230400;
0
152#endif /* B230400 */-
153 default:
never executed: default:
0
154 return 9600;
never executed: return 9600;
0
155 }-
156}-
157-
158/*-
159 * Converts a numeric baud rate to a POSIX speed_t.-
160 */-
161static speed_t-
162baud_to_speed(int baud)-
163{-
164 switch (baud) {-
165 case 0:
never executed: case 0:
0
166 return B0;
never executed: return 0000000 ;
0
167 case 50:
never executed: case 50:
0
168 return B50;
never executed: return 0000001 ;
0
169 case 75:
never executed: case 75:
0
170 return B75;
never executed: return 0000002 ;
0
171 case 110:
never executed: case 110:
0
172 return B110;
never executed: return 0000003 ;
0
173 case 134:
never executed: case 134:
0
174 return B134;
never executed: return 0000004 ;
0
175 case 150:
never executed: case 150:
0
176 return B150;
never executed: return 0000005 ;
0
177 case 200:
never executed: case 200:
0
178 return B200;
never executed: return 0000006 ;
0
179 case 300:
never executed: case 300:
0
180 return B300;
never executed: return 0000007 ;
0
181 case 600:
never executed: case 600:
0
182 return B600;
never executed: return 0000010 ;
0
183 case 1200:
never executed: case 1200:
0
184 return B1200;
never executed: return 0000011 ;
0
185 case 1800:
never executed: case 1800:
0
186 return B1800;
never executed: return 0000012 ;
0
187 case 2400:
never executed: case 2400:
0
188 return B2400;
never executed: return 0000013 ;
0
189 case 4800:
never executed: case 4800:
0
190 return B4800;
never executed: return 0000014 ;
0
191 case 9600:
never executed: case 9600:
0
192 return B9600;
never executed: return 0000015 ;
0
193-
194#ifdef B19200-
195 case 19200:
never executed: case 19200:
0
196 return B19200;
never executed: return 0000016 ;
0
197#else /* B19200 */-
198#ifdef EXTA-
199 case 19200:-
200 return EXTA;-
201#endif /* EXTA */-
202#endif /* B19200 */-
203-
204#ifdef B38400-
205 case 38400:
never executed: case 38400:
0
206 return B38400;
never executed: return 0000017 ;
0
207#else /* B38400 */-
208#ifdef EXTB-
209 case 38400:-
210 return EXTB;-
211#endif /* EXTB */-
212#endif /* B38400 */-
213-
214#ifdef B7200-
215 case 7200:-
216 return B7200;-
217#endif /* B7200 */-
218#ifdef B14400-
219 case 14400:-
220 return B14400;-
221#endif /* B14400 */-
222#ifdef B28800-
223 case 28800:-
224 return B28800;-
225#endif /* B28800 */-
226#ifdef B57600-
227 case 57600:
never executed: case 57600:
0
228 return B57600;
never executed: return 0010001 ;
0
229#endif /* B57600 */-
230#ifdef B76800-
231 case 76800:-
232 return B76800;-
233#endif /* B76800 */-
234#ifdef B115200-
235 case 115200:
never executed: case 115200:
0
236 return B115200;
never executed: return 0010002 ;
0
237#endif /* B115200 */-
238#ifdef B230400-
239 case 230400:
never executed: case 230400:
0
240 return B230400;
never executed: return 0010003 ;
0
241#endif /* B230400 */-
242 default:
never executed: default:
0
243 return B9600;
never executed: return 0000015 ;
0
244 }-
245}-
246-
247/*-
248 * Encode a special character into SSH line format.-
249 */-
250static u_int-
251special_char_encode(cc_t c)-
252{-
253#ifdef _POSIX_VDISABLE-
254 if (c == _POSIX_VDISABLE)-
255 return 255;-
256#endif /* _POSIX_VDISABLE */-
257 return c;
never executed: return c;
0
258}-
259-
260/*-
261 * Decode a special character from SSH line format.-
262 */-
263static cc_t-
264special_char_decode(u_int c)-
265{-
266#ifdef _POSIX_VDISABLE-
267 if (c == 255)-
268 return _POSIX_VDISABLE;-
269#endif /* _POSIX_VDISABLE */-
270 return c;
never executed: return c;
0
271}-
272-
273/*-
274 * Encodes terminal modes for the terminal referenced by fd-
275 * or tiop in a portable manner, and appends the modes to a packet-
276 * being constructed.-
277 */-
278void-
279ssh_tty_make_modes(struct ssh *ssh, int fd, struct termios *tiop)-
280{-
281 struct termios tio;-
282 struct sshbuf *buf;-
283 int r, ibaud, obaud;-
284-
285 if ((buf = sshbuf_new()) == NULL)
(buf = sshbuf_...== ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
286 fatal("%s: sshbuf_new failed", __func__);
never executed: fatal("%s: sshbuf_new failed", __func__);
0
287-
288 if (tiop == NULL) {
tiop == ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
289 if (fd == -1) {
fd == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
290 debug("%s: no fd or tio", __func__);-
291 goto end;
never executed: goto end;
0
292 }-
293 if (tcgetattr(fd, &tio) == -1) {
tcgetattr(fd, &tio) == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
294 logit("tcgetattr: %.100s", strerror(errno));-
295 goto end;
never executed: goto end;
0
296 }-
297 } else
never executed: end of block
0
298 tio = *tiop;
never executed: tio = *tiop;
0
299-
300 /* Store input and output baud rates. */-
301 obaud = speed_to_baud(cfgetospeed(&tio));-
302 ibaud = speed_to_baud(cfgetispeed(&tio));-
303 if ((r = sshbuf_put_u8(buf, TTY_OP_OSPEED)) != 0 ||
(r = sshbuf_pu...uf, 129)) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
304 (r = sshbuf_put_u32(buf, obaud)) != 0 ||
(r = sshbuf_pu..., obaud)) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
305 (r = sshbuf_put_u8(buf, TTY_OP_ISPEED)) != 0 ||
(r = sshbuf_pu...uf, 128)) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
306 (r = sshbuf_put_u32(buf, ibaud)) != 0)
(r = sshbuf_pu..., ibaud)) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
307 fatal("%s: buffer error: %s", __func__, ssh_err(r));
never executed: fatal("%s: buffer error: %s", __func__, ssh_err(r));
0
308-
309 /* Store values of mode flags. */-
310#define TTYCHAR(NAME, OP) \-
311 if ((r = sshbuf_put_u8(buf, OP)) != 0 || \-
312 (r = sshbuf_put_u32(buf, \-
313 special_char_encode(tio.c_cc[NAME]))) != 0) \-
314 fatal("%s: buffer error: %s", __func__, ssh_err(r)); \-
315-
316#define SSH_TTYMODE_IUTF8 42 /* for SSH_BUG_UTF8TTYMODE */-
317-
318#define TTYMODE(NAME, FIELD, OP) \-
319 if (OP == SSH_TTYMODE_IUTF8 && (datafellows & SSH_BUG_UTF8TTYMODE)) { \-
320 debug3("%s: SSH_BUG_UTF8TTYMODE", __func__); \-
321 } else if ((r = sshbuf_put_u8(buf, OP)) != 0 || \-
322 (r = sshbuf_put_u32(buf, ((tio.FIELD & NAME) != 0))) != 0) \-
323 fatal("%s: buffer error: %s", __func__, ssh_err(r)); \-
324-
325#include "ttymodes.h"-
326-
327#undef TTYCHAR-
328#undef TTYMODE-
329-
330end:
code before this statement never executed: end:
0
331 /* Mark end of mode data. */-
332 if ((r = sshbuf_put_u8(buf, TTY_OP_END)) != 0 ||
(r = sshbuf_pu...(buf, 0)) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
333 (r = sshpkt_put_stringb(ssh, buf)) != 0)
(r = sshpkt_pu...sh, buf)) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
334 fatal("%s: packet error: %s", __func__, ssh_err(r));
never executed: fatal("%s: packet error: %s", __func__, ssh_err(r));
0
335 sshbuf_free(buf);-
336}
never executed: end of block
0
337-
338/*-
339 * Decodes terminal modes for the terminal referenced by fd in a portable-
340 * manner from a packet being read.-
341 */-
342void-
343ssh_tty_parse_modes(struct ssh *ssh, int fd)-
344{-
345 struct termios tio;-
346 struct sshbuf *buf;-
347 const u_char *data;-
348 u_char opcode;-
349 u_int baud, u;-
350 int r, failure = 0;-
351 size_t len;-
352-
353 if ((r = sshpkt_get_string_direct(ssh, &data, &len)) != 0)
(r = sshpkt_ge...a, &len)) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
354 fatal("%s: packet error: %s", __func__, ssh_err(r));
never executed: fatal("%s: packet error: %s", __func__, ssh_err(r));
0
355 if (len == 0)
len == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
356 return;
never executed: return;
0
357 if ((buf = sshbuf_from(data, len)) == NULL) {
(buf = sshbuf_...== ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
358 error("%s: sshbuf_from failed", __func__);-
359 return;
never executed: return;
0
360 }-
361-
362 /*-
363 * Get old attributes for the terminal. We will modify these-
364 * flags. I am hoping that if there are any machine-specific-
365 * modes, they will initially have reasonable values.-
366 */-
367 if (tcgetattr(fd, &tio) == -1) {
tcgetattr(fd, &tio) == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
368 logit("tcgetattr: %.100s", strerror(errno));-
369 failure = -1;-
370 }
never executed: end of block
0
371-
372 while (sshbuf_len(buf) > 0) {
sshbuf_len(buf) > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
373 if ((r = sshbuf_get_u8(buf, &opcode)) != 0)
(r = sshbuf_ge...&opcode)) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
374 fatal("%s: packet error: %s", __func__, ssh_err(r));
never executed: fatal("%s: packet error: %s", __func__, ssh_err(r));
0
375 switch (opcode) {-
376 case TTY_OP_END:
never executed: case 0:
0
377 goto set;
never executed: goto set;
0
378-
379 case TTY_OP_ISPEED:
never executed: case 128:
0
380 if ((r = sshbuf_get_u32(buf, &baud)) != 0)
(r = sshbuf_ge..., &baud)) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
381 fatal("%s: packet error: %s",
never executed: fatal("%s: packet error: %s", __func__, ssh_err(r));
0
382 __func__, ssh_err(r));
never executed: fatal("%s: packet error: %s", __func__, ssh_err(r));
0
383 if (failure != -1 &&
failure != -1Description
TRUEnever evaluated
FALSEnever evaluated
0
384 cfsetispeed(&tio, baud_to_speed(baud)) == -1)
cfsetispeed(&t...d(baud)) == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
385 error("cfsetispeed failed for %d", baud);
never executed: error("cfsetispeed failed for %d", baud);
0
386 break;
never executed: break;
0
387-
388 case TTY_OP_OSPEED:
never executed: case 129:
0
389 if ((r = sshbuf_get_u32(buf, &baud)) != 0)
(r = sshbuf_ge..., &baud)) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
390 fatal("%s: packet error: %s",
never executed: fatal("%s: packet error: %s", __func__, ssh_err(r));
0
391 __func__, ssh_err(r));
never executed: fatal("%s: packet error: %s", __func__, ssh_err(r));
0
392 if (failure != -1 &&
failure != -1Description
TRUEnever evaluated
FALSEnever evaluated
0
393 cfsetospeed(&tio, baud_to_speed(baud)) == -1)
cfsetospeed(&t...d(baud)) == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
394 error("cfsetospeed failed for %d", baud);
never executed: error("cfsetospeed failed for %d", baud);
0
395 break;
never executed: break;
0
396-
397#define TTYCHAR(NAME, OP) \-
398 case OP: \-
399 if ((r = sshbuf_get_u32(buf, &u)) != 0) \-
400 fatal("%s: packet error: %s", __func__, \-
401 ssh_err(r)); \-
402 tio.c_cc[NAME] = special_char_decode(u); \-
403 break;-
404#define TTYMODE(NAME, FIELD, OP) \-
405 case OP: \-
406 if ((r = sshbuf_get_u32(buf, &u)) != 0) \-
407 fatal("%s: packet error: %s", __func__, \-
408 ssh_err(r)); \-
409 if (u) \-
410 tio.FIELD |= NAME; \-
411 else \-
412 tio.FIELD &= ~NAME; \-
413 break;-
414-
415#include "ttymodes.h"-
416-
417#undef TTYCHAR-
418#undef TTYMODE-
419-
420 default:
never executed: default:
0
421 debug("Ignoring unsupported tty mode opcode %d (0x%x)",-
422 opcode, opcode);-
423 /*-
424 * SSH2:-
425 * Opcodes 1 to 159 are defined to have a uint32-
426 * argument.-
427 * Opcodes 160 to 255 are undefined and cause parsing-
428 * to stop.-
429 */-
430 if (opcode > 0 && opcode < 160) {
opcode > 0Description
TRUEnever evaluated
FALSEnever evaluated
opcode < 160Description
TRUEnever evaluated
FALSEnever evaluated
0
431 if ((r = sshbuf_get_u32(buf, NULL)) != 0)
(r = sshbuf_ge...d *)0) )) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
432 fatal("%s: packet error: %s", __func__,
never executed: fatal("%s: packet error: %s", __func__, ssh_err(r));
0
433 ssh_err(r));
never executed: fatal("%s: packet error: %s", __func__, ssh_err(r));
0
434 break;
never executed: break;
0
435 } else {-
436 logit("%s: unknown opcode %d", __func__,-
437 opcode);-
438 goto set;
never executed: goto set;
0
439 }-
440 }-
441 }-
442-
443set:
code before this statement never executed: set:
0
444 len = sshbuf_len(buf);-
445 sshbuf_free(buf);-
446 if (len > 0) {
len > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
447 logit("%s: %zu bytes left", __func__, len);-
448 return; /* Don't process bytes passed */
never executed: return;
0
449 }-
450 if (failure == -1)
failure == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
451 return; /* Packet parsed ok but tcgetattr() failed */
never executed: return;
0
452-
453 /* Set the new modes for the terminal. */-
454 if (tcsetattr(fd, TCSANOW, &tio) == -1)
tcsetattr(fd, 0 , &tio) == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
455 logit("Setting tty modes failed: %.100s", strerror(errno));
never executed: logit("Setting tty modes failed: %.100s", strerror( (*__errno_location ()) ));
0
456}
never executed: end of block
0
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.2.2