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> ¶ms, const QByteArray &prefix = QByteArray()); |
39 |
+ void putCmd(const QString &cmd, const QList<QList<QByteArray>> ¶ms, 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> ¶ms, co |
48 |
} |
49 |
|
50 |
|
51 |
+void CoreNetwork::putCmd(const QString &cmd, const QList<QList<QByteArray>> ¶ms, 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> ¶ms, const QByteArray &prefix = QByteArray()); |
170 |
+ void putCmd(const QString &cmd, const QList<QList<QByteArray>> ¶ms, 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 |
} |