annotate circbuffer.c @ 1788:1fc0012b9c38

Fix handling of replies to global requests (#112) The current code assumes that all global requests want / need a reply. This isn't always true and the request itself indicates if it wants a reply or not. It causes a specific problem with [email protected] messages. These are sent by OpenSSH after authentication to inform the client of potential other host keys for the host. This can be used to add a new type of host key or to rotate host keys. The initial information message from the server is sent as a global request, but with want_reply set to false. This means that the server doesn't expect an answer to this message. Instead the client needs to send a prove request as a reply if it wants to receive proof of ownership for the host keys. The bug doesn't cause any current problems with due to how OpenSSH treats receiving the failure message. It instead treats it as a keepalive message and further ignores it. Arguably this is a protocol violation though of Dropbear and it is only accidental that it doesn't cause a problem with OpenSSH. The bug was found when adding host keys support to libssh, which is more strict protocol wise and treats the unexpected failure message an error, also see https://gitlab.com/libssh/libssh-mirror/-/merge_requests/145 for more information. The fix here is to honor the want_reply flag in the global request and to only send a reply if the other side expects a reply.
author Dirkjan Bussink <d.bussink@gmail.com>
date Thu, 10 Dec 2020 16:13:13 +0100
parents 06d52bcb8094
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
108
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1 /*
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2 * Dropbear SSH
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3 *
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4 * Copyright (c) 2002-2004 Matt Johnston
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5 * All rights reserved.
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6 *
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8 * of this software and associated documentation files (the "Software"), to deal
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9 * in the Software without restriction, including without limitation the rights
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
11 * copies of the Software, and to permit persons to whom the Software is
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
12 * furnished to do so, subject to the following conditions:
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
13 *
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
14 * The above copyright notice and this permission notice shall be included in
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
15 * all copies or substantial portions of the Software.
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
16 *
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
23 * SOFTWARE. */
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
24
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
25 #include "includes.h"
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
26 #include "dbutil.h"
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
27 #include "circbuffer.h"
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
28
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
29 #define MAX_CBUF_SIZE 100000000
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
30
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
31 circbuffer * cbuf_new(unsigned int size) {
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
32
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
33 circbuffer *cbuf = NULL;
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
34
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
35 if (size > MAX_CBUF_SIZE) {
594
a98a2138364a Improve capitalisation for all logged strings
Matt Johnston <matt@ucc.asn.au>
parents: 241
diff changeset
36 dropbear_exit("Bad cbuf size");
108
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
37 }
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
38
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
39 cbuf = (circbuffer*)m_malloc(sizeof(circbuffer));
1167
1397a677cb5c lazy allocation of circbuffer
Matt Johnston <matt@ucc.asn.au>
parents: 1079
diff changeset
40 /* data is malloced on first write */
1397a677cb5c lazy allocation of circbuffer
Matt Johnston <matt@ucc.asn.au>
parents: 1079
diff changeset
41 cbuf->data = NULL;
108
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
42 cbuf->used = 0;
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
43 cbuf->readpos = 0;
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
44 cbuf->writepos = 0;
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
45 cbuf->size = size;
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
46
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
47 return cbuf;
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
48 }
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
49
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
50 void cbuf_free(circbuffer * cbuf) {
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
51
1167
1397a677cb5c lazy allocation of circbuffer
Matt Johnston <matt@ucc.asn.au>
parents: 1079
diff changeset
52 if (cbuf->data) {
1397a677cb5c lazy allocation of circbuffer
Matt Johnston <matt@ucc.asn.au>
parents: 1079
diff changeset
53 m_burn(cbuf->data, cbuf->size);
1397a677cb5c lazy allocation of circbuffer
Matt Johnston <matt@ucc.asn.au>
parents: 1079
diff changeset
54 m_free(cbuf->data);
1397a677cb5c lazy allocation of circbuffer
Matt Johnston <matt@ucc.asn.au>
parents: 1079
diff changeset
55 }
108
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
56 m_free(cbuf);
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
57 }
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
58
1459
06d52bcb8094 Pointer parameter could be declared as pointing to const
Francois Perrad <francois.perrad@gadz.org>
parents: 1167
diff changeset
59 unsigned int cbuf_getused(const circbuffer * cbuf) {
108
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
60
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
61 return cbuf->used;
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
62
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
63 }
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
64
1459
06d52bcb8094 Pointer parameter could be declared as pointing to const
Francois Perrad <francois.perrad@gadz.org>
parents: 1167
diff changeset
65 unsigned int cbuf_getavail(const circbuffer * cbuf) {
108
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
66
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
67 return cbuf->size - cbuf->used;
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
68
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
69 }
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
70
1459
06d52bcb8094 Pointer parameter could be declared as pointing to const
Francois Perrad <francois.perrad@gadz.org>
parents: 1167
diff changeset
71 unsigned int cbuf_writelen(const circbuffer *cbuf) {
108
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
72
241
c5d3ef11155f * use own assertions which should get logged properly
Matt Johnston <matt@ucc.asn.au>
parents: 165
diff changeset
73 dropbear_assert(cbuf->used <= cbuf->size);
c5d3ef11155f * use own assertions which should get logged properly
Matt Johnston <matt@ucc.asn.au>
parents: 165
diff changeset
74 dropbear_assert(((2*cbuf->size)+cbuf->writepos-cbuf->readpos)%cbuf->size == cbuf->used%cbuf->size);
c5d3ef11155f * use own assertions which should get logged properly
Matt Johnston <matt@ucc.asn.au>
parents: 165
diff changeset
75 dropbear_assert(((2*cbuf->size)+cbuf->readpos-cbuf->writepos)%cbuf->size == (cbuf->size-cbuf->used)%cbuf->size);
108
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
76
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
77 if (cbuf->used == cbuf->size) {
165
0cfba3034be5 Fixed DEBUG_TRACE macro so that we don't get semicolons left about the place
Matt Johnston <matt@ucc.asn.au>
parents: 108
diff changeset
78 TRACE(("cbuf_writelen: full buffer"))
108
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
79 return 0; /* full */
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
80 }
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
81
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
82 if (cbuf->writepos < cbuf->readpos) {
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
83 return cbuf->readpos - cbuf->writepos;
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
84 }
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
85
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
86 return cbuf->size - cbuf->writepos;
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
87 }
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
88
1459
06d52bcb8094 Pointer parameter could be declared as pointing to const
Francois Perrad <francois.perrad@gadz.org>
parents: 1167
diff changeset
89 void cbuf_readptrs(const circbuffer *cbuf,
1054
c71df09bc610 Avoid copying data into circular buffer
Matt Johnston <matt@ucc.asn.au>
parents: 709
diff changeset
90 unsigned char **p1, unsigned int *len1,
c71df09bc610 Avoid copying data into circular buffer
Matt Johnston <matt@ucc.asn.au>
parents: 709
diff changeset
91 unsigned char **p2, unsigned int *len2) {
c71df09bc610 Avoid copying data into circular buffer
Matt Johnston <matt@ucc.asn.au>
parents: 709
diff changeset
92 *p1 = &cbuf->data[cbuf->readpos];
c71df09bc610 Avoid copying data into circular buffer
Matt Johnston <matt@ucc.asn.au>
parents: 709
diff changeset
93 *len1 = MIN(cbuf->used, cbuf->size - cbuf->readpos);
c71df09bc610 Avoid copying data into circular buffer
Matt Johnston <matt@ucc.asn.au>
parents: 709
diff changeset
94
c71df09bc610 Avoid copying data into circular buffer
Matt Johnston <matt@ucc.asn.au>
parents: 709
diff changeset
95 if (*len1 < cbuf->used) {
c71df09bc610 Avoid copying data into circular buffer
Matt Johnston <matt@ucc.asn.au>
parents: 709
diff changeset
96 *p2 = cbuf->data;
c71df09bc610 Avoid copying data into circular buffer
Matt Johnston <matt@ucc.asn.au>
parents: 709
diff changeset
97 *len2 = cbuf->used - *len1;
c71df09bc610 Avoid copying data into circular buffer
Matt Johnston <matt@ucc.asn.au>
parents: 709
diff changeset
98 } else {
c71df09bc610 Avoid copying data into circular buffer
Matt Johnston <matt@ucc.asn.au>
parents: 709
diff changeset
99 *p2 = NULL;
c71df09bc610 Avoid copying data into circular buffer
Matt Johnston <matt@ucc.asn.au>
parents: 709
diff changeset
100 *len2 = 0;
c71df09bc610 Avoid copying data into circular buffer
Matt Johnston <matt@ucc.asn.au>
parents: 709
diff changeset
101 }
c71df09bc610 Avoid copying data into circular buffer
Matt Johnston <matt@ucc.asn.au>
parents: 709
diff changeset
102 }
c71df09bc610 Avoid copying data into circular buffer
Matt Johnston <matt@ucc.asn.au>
parents: 709
diff changeset
103
108
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
104 unsigned char* cbuf_writeptr(circbuffer *cbuf, unsigned int len) {
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
105
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
106 if (len > cbuf_writelen(cbuf)) {
594
a98a2138364a Improve capitalisation for all logged strings
Matt Johnston <matt@ucc.asn.au>
parents: 241
diff changeset
107 dropbear_exit("Bad cbuf write");
108
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
108 }
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
109
1167
1397a677cb5c lazy allocation of circbuffer
Matt Johnston <matt@ucc.asn.au>
parents: 1079
diff changeset
110 if (!cbuf->data) {
1397a677cb5c lazy allocation of circbuffer
Matt Johnston <matt@ucc.asn.au>
parents: 1079
diff changeset
111 /* lazy allocation */
1397a677cb5c lazy allocation of circbuffer
Matt Johnston <matt@ucc.asn.au>
parents: 1079
diff changeset
112 cbuf->data = (unsigned char*)m_malloc(cbuf->size);
1397a677cb5c lazy allocation of circbuffer
Matt Johnston <matt@ucc.asn.au>
parents: 1079
diff changeset
113 }
1397a677cb5c lazy allocation of circbuffer
Matt Johnston <matt@ucc.asn.au>
parents: 1079
diff changeset
114
108
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
115 return &cbuf->data[cbuf->writepos];
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
116 }
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
117
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
118 void cbuf_incrwrite(circbuffer *cbuf, unsigned int len) {
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
119 if (len > cbuf_writelen(cbuf)) {
594
a98a2138364a Improve capitalisation for all logged strings
Matt Johnston <matt@ucc.asn.au>
parents: 241
diff changeset
120 dropbear_exit("Bad cbuf write");
108
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
121 }
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
122
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
123 cbuf->used += len;
241
c5d3ef11155f * use own assertions which should get logged properly
Matt Johnston <matt@ucc.asn.au>
parents: 165
diff changeset
124 dropbear_assert(cbuf->used <= cbuf->size);
108
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
125 cbuf->writepos = (cbuf->writepos + len) % cbuf->size;
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
126 }
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
127
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
128
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
129 void cbuf_incrread(circbuffer *cbuf, unsigned int len) {
241
c5d3ef11155f * use own assertions which should get logged properly
Matt Johnston <matt@ucc.asn.au>
parents: 165
diff changeset
130 dropbear_assert(cbuf->used >= len);
108
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
131 cbuf->used -= len;
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
132 cbuf->readpos = (cbuf->readpos + len) % cbuf->size;
10f4d3319780 - added circular buffering for channels
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
133 }