Gentoo Archives: gentoo-commits

From: "Ian Delaney (idella4)" <idella4@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-x86 commit in net-irc/quassel/files: DOS-sec.patch
Date: Mon, 30 Mar 2015 05:47:52
Message-Id: 20150330054744.8B0CC14D3C@oystercatcher.gentoo.org
1 idella4 15/03/30 05:47:44
2
3 Added: DOS-sec.patch
4 Log:
5 revbump; add sec patch from bug #544230, rm affected version
6
7 (Portage version: 2.2.18/cvs/Linux x86_64, signed Manifest commit with key 0xB8072B0D)
8
9 Revision Changes Path
10 1.1 net-irc/quassel/files/DOS-sec.patch
11
12 file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/net-irc/quassel/files/DOS-sec.patch?rev=1.1&view=markup
13 plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/net-irc/quassel/files/DOS-sec.patch?rev=1.1&content-type=text/plain
14
15 Index: DOS-sec.patch
16 ===================================================================
17 diff --git a/src/core/corebasichandler.cpp b/src/core/corebasichandler.cpp
18 index dfa8a99..fbfc76c 100644
19 --- a/src/core/corebasichandler.cpp
20 +++ b/src/core/corebasichandler.cpp
21 @@ -33,6 +33,9 @@ CoreBasicHandler::CoreBasicHandler(CoreNetwork *parent)
22 connect(this, SIGNAL(putCmd(QString, const QList<QByteArray> &, const QByteArray &)),
23 network(), SLOT(putCmd(QString, const QList<QByteArray> &, const QByteArray &)));
24
25 + connect(this, SIGNAL(putCmd(QString, const QList<QList<QByteArray>> &, const QByteArray &)),
26 + network(), SLOT(putCmd(QString, const QList<QList<QByteArray>> &, const QByteArray &)));
27 +
28 connect(this, SIGNAL(putRawLine(const QByteArray &)),
29 network(), SLOT(putRawLine(const QByteArray &)));
30 }
31 diff --git a/src/core/corebasichandler.h b/src/core/corebasichandler.h
32 index 20d057f..a4b5a7f 100644
33 --- a/src/core/corebasichandler.h
34 +++ b/src/core/corebasichandler.h
35 @@ -55,6 +55,7 @@ class CoreBasicHandler : public BasicHandler
36 signals:
37 void displayMsg(Message::Type, BufferInfo::Type, const QString &target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None);
38 void putCmd(const QString &cmd, const QList<QByteArray> &params, const QByteArray &prefix = QByteArray());
39 + void putCmd(const QString &cmd, const QList<QList<QByteArray>> &params, const QByteArray &prefix = QByteArray());
40 void putRawLine(const QByteArray &msg);
41
42 protected:
43 diff --git a/src/core/corenetwork.cpp b/src/core/corenetwork.cpp
44 index 7e9ce26..932af6f 100644
45 --- a/src/core/corenetwork.cpp
46 +++ b/src/core/corenetwork.cpp
47 @@ -284,6 +284,16 @@ void CoreNetwork::putCmd(const QString &cmd, const QList<QByteArray> &params, co
48 }
49
50
51 +void CoreNetwork::putCmd(const QString &cmd, const QList<QList<QByteArray>> &params, const QByteArray &prefix)
52 +{
53 + QListIterator<QList<QByteArray>> i(params);
54 + while (i.hasNext()) {
55 + QList<QByteArray> msg = i.next();
56 + putCmd(cmd, msg, prefix);
57 + }
58 +}
59 +
60 +
61 void CoreNetwork::setChannelJoined(const QString &channel)
62 {
63 _autoWhoQueue.prepend(channel.toLower()); // prepend so this new chan is the first to be checked
64 @@ -980,3 +990,79 @@ void CoreNetwork::requestSetNetworkInfo(const NetworkInfo &info)
65 }
66 }
67 }
68 +
69 +
70 +QList<QList<QByteArray>> CoreNetwork::splitMessage(const QString &cmd, const QString &message, std::function<QList<QByteArray>(QString &)> cmdGenerator)
71 +{
72 + QString wrkMsg(message);
73 + QList<QList<QByteArray>> msgsToSend;
74 +
75 + // do while (wrkMsg.size() > 0)
76 + do {
77 + // First, check to see if the whole message can be sent at once. The
78 + // cmdGenerator function is passed in by the caller and is used to encode
79 + // and encrypt (if applicable) the message, since different callers might
80 + // want to use different encoding or encode different values.
81 + int splitPos = wrkMsg.size();
82 + QList<QByteArray> initialSplitMsgEnc = cmdGenerator(wrkMsg);
83 + int initialOverrun = userInputHandler()->lastParamOverrun(cmd, initialSplitMsgEnc);
84 +
85 + if (initialOverrun) {
86 + // If the message was too long to be sent, first try splitting it along
87 + // word boundaries with QTextBoundaryFinder.
88 + QString splitMsg(wrkMsg);
89 + QTextBoundaryFinder qtbf(QTextBoundaryFinder::Word, splitMsg);
90 + qtbf.setPosition(initialSplitMsgEnc[1].size() - initialOverrun);
91 + QList<QByteArray> splitMsgEnc;
92 + int overrun = initialOverrun;
93 +
94 + while (overrun) {
95 + splitPos = qtbf.toPreviousBoundary();
96 +
97 + // splitPos==-1 means the QTBF couldn't find a split point at all and
98 + // splitPos==0 means the QTBF could only find a boundary at the beginning of
99 + // the string. Neither one of these works for us.
100 + if (splitPos > 0) {
101 + // If a split point could be found, split the message there, calculate the
102 + // overrun, and continue with the loop.
103 + splitMsg = splitMsg.left(splitPos);
104 + splitMsgEnc = cmdGenerator(splitMsg);
105 + overrun = userInputHandler()->lastParamOverrun(cmd, splitMsgEnc);
106 + }
107 + else {
108 + // If a split point could not be found (the beginning of the message
109 + // is reached without finding a split point short enough to send) and we
110 + // are still in Word mode, switch to Grapheme mode. We also need to restore
111 + // the full wrkMsg to splitMsg, since splitMsg may have been cut down during
112 + // the previous attempt to find a split point.
113 + if (qtbf.type() == QTextBoundaryFinder::Word) {
114 + splitMsg = wrkMsg;
115 + splitPos = splitMsg.size();
116 + QTextBoundaryFinder graphemeQtbf(QTextBoundaryFinder::Grapheme, splitMsg);
117 + graphemeQtbf.setPosition(initialSplitMsgEnc[1].size() - initialOverrun);
118 + qtbf = graphemeQtbf;
119 + }
120 + else {
121 + // If the QTBF fails to find a split point in Grapheme mode, we give up.
122 + // This should never happen, but it should be handled anyway.
123 + qWarning() << "Unexpected failure to split message!";
124 + return msgsToSend;
125 + }
126 + }
127 + }
128 +
129 + // Once a message of sendable length has been found, remove it from the wrkMsg and
130 + // add it to the list of messages to be sent.
131 + wrkMsg.remove(0, splitPos);
132 + msgsToSend.append(splitMsgEnc);
133 + }
134 + else{
135 + // If the entire remaining message is short enough to be sent all at once, remove
136 + // it from the wrkMsg and add it to the list of messages to be sent.
137 + wrkMsg.remove(0, splitPos);
138 + msgsToSend.append(initialSplitMsgEnc);
139 + }
140 + } while (wrkMsg.size() > 0);
141 +
142 + return msgsToSend;
143 +}
144 diff --git a/src/core/corenetwork.h b/src/core/corenetwork.h
145 index 87121ba..05565a4 100644
146 --- a/src/core/corenetwork.h
147 +++ b/src/core/corenetwork.h
148 @@ -40,6 +40,8 @@
149
150 #include "coresession.h"
151
152 +#include <functional>
153 +
154 class CoreIdentity;
155 class CoreUserInputHandler;
156 class CoreIgnoreListManager;
157 @@ -93,6 +95,8 @@ class CoreNetwork : public Network
158 inline quint16 localPort() const { return socket.localPort(); }
159 inline quint16 peerPort() const { return socket.peerPort(); }
160
161 + QList<QList<QByteArray>> splitMessage(const QString &cmd, const QString &message, std::function<QList<QByteArray>(QString &)> cmdGenerator);
162 +
163 public slots:
164 virtual void setMyNick(const QString &mynick);
165
166 @@ -112,6 +116,7 @@ public slots:
167 void userInput(BufferInfo bufferInfo, QString msg);
168 void putRawLine(QByteArray input);
169 void putCmd(const QString &cmd, const QList<QByteArray> &params, const QByteArray &prefix = QByteArray());
170 + void putCmd(const QString &cmd, const QList<QList<QByteArray>> &params, const QByteArray &prefix = QByteArray());
171
172 void setChannelJoined(const QString &channel);
173 void setChannelParted(const QString &channel);
174 diff --git a/src/core/coreuserinputhandler.cpp b/src/core/coreuserinputhandler.cpp
175 index 33d1f67..72ac996 100644
176 --- a/src/core/coreuserinputhandler.cpp
177 +++ b/src/core/coreuserinputhandler.cpp
178 @@ -473,12 +473,16 @@ void CoreUserInputHandler::handleMsg(const BufferInfo &bufferInfo, const QString
179 return;
180
181 QString target = msg.section(' ', 0, 0);
182 - QByteArray encMsg = userEncode(target, msg.section(' ', 1));
183 + QString msgSection = msg.section(' ', 1);
184 +
185 + std::function<QByteArray(const QString &, const QString &)> encodeFunc = [this] (const QString &target, const QString &message) -> QByteArray {
186 + return userEncode(target, message);
187 + };
188
189 #ifdef HAVE_QCA2
190 - putPrivmsg(serverEncode(target), encMsg, network()->cipher(target));
191 + putPrivmsg(target, msgSection, encodeFunc, network()->cipher(target));
192 #else
193 - putPrivmsg(serverEncode(target), encMsg);
194 + putPrivmsg(target, msgSection, encodeFunc);
195 #endif
196 }
197
198 @@ -594,11 +598,14 @@ void CoreUserInputHandler::handleSay(const BufferInfo &bufferInfo, const QString
199 if (bufferInfo.bufferName().isEmpty() || !bufferInfo.acceptsRegularMessages())
200 return; // server buffer
201
202 - QByteArray encMsg = channelEncode(bufferInfo.bufferName(), msg);
203 + std::function<QByteArray(const QString &, const QString &)> encodeFunc = [this] (const QString &target, const QString &message) -> QByteArray {
204 + return channelEncode(target, message);
205 + };
206 +
207 #ifdef HAVE_QCA2
208 - putPrivmsg(serverEncode(bufferInfo.bufferName()), encMsg, network()->cipher(bufferInfo.bufferName()));
209 + putPrivmsg(bufferInfo.bufferName(), msg, encodeFunc, network()->cipher(bufferInfo.bufferName()));
210 #else
211 - putPrivmsg(serverEncode(bufferInfo.bufferName()), encMsg);
212 + putPrivmsg(bufferInfo.bufferName(), msg, encodeFunc);
213 #endif
214 emit displayMsg(Message::Plain, bufferInfo.type(), bufferInfo.bufferName(), msg, network()->myNick(), Message::Self);
215 }
216 @@ -763,56 +770,23 @@ void CoreUserInputHandler::defaultHandler(QString cmd, const BufferInfo &bufferI
217 }
218
219
220 -void CoreUserInputHandler::putPrivmsg(const QByteArray &target, const QByteArray &message, Cipher *cipher)
221 +void CoreUserInputHandler::putPrivmsg(const QString &target, const QString &message, std::function<QByteArray(const QString &, const QString &)> encodeFunc, Cipher *cipher)
222 {
223 - // Encrypted messages need special care. There's no clear relation between cleartext and encrypted message length,
224 - // so we can't just compute the maxSplitPos. Instead, we need to loop through the splitpoints until the crypted
225 - // version is short enough...
226 - // TODO: check out how the various possible encryption methods behave length-wise and make
227 - // this clean by predicting the length of the crypted msg.
228 - // For example, blowfish-ebc seems to create 8-char chunks.
229 + QString cmd("PRIVMSG");
230 + QByteArray targetEnc = serverEncode(target);
231
232 - static const char *cmd = "PRIVMSG";
233 - static const char *splitter = " .,-!?";
234 + std::function<QList<QByteArray>(QString &)> cmdGenerator = [&] (QString &splitMsg) -> QList<QByteArray> {
235 + QByteArray splitMsgEnc = encodeFunc(target, splitMsg);
236
237 - int maxSplitPos = message.count();
238 - int splitPos = maxSplitPos;
239 - forever {
240 - QByteArray crypted = message.left(splitPos);
241 - bool isEncrypted = false;
242 #ifdef HAVE_QCA2
243 - if (cipher && !cipher->key().isEmpty() && !message.isEmpty()) {
244 - isEncrypted = cipher->encrypt(crypted);
245 + if (cipher && !cipher->key().isEmpty() && !splitMsg.isEmpty()) {
246 + cipher->encrypt(splitMsgEnc);
247 }
248 #endif
249 - int overrun = lastParamOverrun(cmd, QList<QByteArray>() << target << crypted);
250 - if (overrun) {
251 - // In case this is not an encrypted msg, we can just cut off at the end
252 - if (!isEncrypted)
253 - maxSplitPos = message.count() - overrun;
254 -
255 - splitPos = -1;
256 - for (const char *splitChar = splitter; *splitChar != 0; splitChar++) {
257 - splitPos = qMax(splitPos, message.lastIndexOf(*splitChar, maxSplitPos) + 1); // keep split char on old line
258 - }
259 - if (splitPos <= 0 || splitPos > maxSplitPos)
260 - splitPos = maxSplitPos;
261 -
262 - maxSplitPos = splitPos - 1;
263 - if (maxSplitPos <= 0) { // this should never happen, but who knows...
264 - qWarning() << tr("[Error] Could not encrypt your message: %1").arg(message.data());
265 - return;
266 - }
267 - continue; // we never come back here for !encrypted!
268 - }
269 -
270 - // now we have found a valid splitpos (or didn't need to split to begin with)
271 - putCmd(cmd, QList<QByteArray>() << target << crypted);
272 - if (splitPos < message.count())
273 - putPrivmsg(target, message.mid(splitPos), cipher);
274 + return QList<QByteArray>() << targetEnc << splitMsgEnc;
275 + };
276
277 - return;
278 - }
279 + putCmd(cmd, network()->splitMessage(cmd, message, cmdGenerator));
280 }
281
282
283 diff --git a/src/core/coreuserinputhandler.h b/src/core/coreuserinputhandler.h
284 index 69a429e..6e69ce6 100644
285 --- a/src/core/coreuserinputhandler.h
286 +++ b/src/core/coreuserinputhandler.h
287 @@ -88,7 +88,7 @@ public slots:
288 private:
289 void doMode(const BufferInfo& bufferInfo, const QChar &addOrRemove, const QChar &mode, const QString &nickList);
290 void banOrUnban(const BufferInfo &bufferInfo, const QString &text, bool ban);
291 - void putPrivmsg(const QByteArray &target, const QByteArray &message, Cipher *cipher = 0);
292 + void putPrivmsg(const QString &target, const QString &message, std::function<QByteArray(const QString &, const QString &)> encodeFunc, Cipher *cipher = 0);
293
294 #ifdef HAVE_QCA2
295 QByteArray encrypt(const QString &target, const QByteArray &message, bool *didEncrypt = 0) const;
296 diff --git a/src/core/ctcpparser.cpp b/src/core/ctcpparser.cpp
297 index fba3d13..37b0af3 100644
298 --- a/src/core/ctcpparser.cpp
299 +++ b/src/core/ctcpparser.cpp
300 @@ -312,29 +312,13 @@ QByteArray CtcpParser::pack(const QByteArray &ctcpTag, const QByteArray &message
301
302 void CtcpParser::query(CoreNetwork *net, const QString &bufname, const QString &ctcpTag, const QString &message)
303 {
304 - QList<QByteArray> params;
305 - params << net->serverEncode(bufname) << lowLevelQuote(pack(net->serverEncode(ctcpTag), net->userEncode(bufname, message)));
306 -
307 - static const char *splitter = " .,-!?";
308 - int maxSplitPos = message.count();
309 - int splitPos = maxSplitPos;
310 + QString cmd("PRIVMSG");
311
312 - int overrun = net->userInputHandler()->lastParamOverrun("PRIVMSG", params);
313 - if (overrun) {
314 - maxSplitPos = message.count() - overrun -2;
315 - splitPos = -1;
316 - for (const char *splitChar = splitter; *splitChar != 0; splitChar++) {
317 - splitPos = qMax(splitPos, message.lastIndexOf(*splitChar, maxSplitPos) + 1); // keep split char on old line
318 - }
319 - if (splitPos <= 0 || splitPos > maxSplitPos)
320 - splitPos = maxSplitPos;
321 -
322 - params = params.mid(0, 1) << lowLevelQuote(pack(net->serverEncode(ctcpTag), net->userEncode(bufname, message.left(splitPos))));
323 - }
324 - net->putCmd("PRIVMSG", params);
325 + std::function<QList<QByteArray>(QString &)> cmdGenerator = [&] (QString &splitMsg) -> QList<QByteArray> {
326 + return QList<QByteArray>() << net->serverEncode(bufname) << lowLevelQuote(pack(net->serverEncode(ctcpTag), net->userEncode(bufname, splitMsg)));
327 + };
328
329 - if (splitPos < message.count())
330 - query(net, bufname, ctcpTag, message.mid(splitPos));
331 + net->putCmd(cmd, net->splitMessage(cmd, message, cmdGenerator));
332 }