09407ff08a52fcb09c47dfcff04fb43a4c87ffa8
1 /*
2 * Support classes for the Pedro mini-XMPP client
3 *
4 * Authors:
5 * Bob Jamison
6 *
7 * Copyright (C) 2005-2007 Bob Jamison
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <sys/stat.h>
30 #include "pedroutil.h"
34 #ifdef __WIN32__
36 #include <windows.h>
38 #else /* UNIX */
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <netdb.h>
44 #include <unistd.h>
45 #include <sys/ioctl.h>
47 #include <pthread.h>
49 #endif /* UNIX */
51 #ifdef HAVE_SSL
52 RELAYTOOL_SSL
53 #endif
56 namespace Pedro
57 {
63 //########################################################################
64 //########################################################################
65 //# B A S E 6 4
66 //########################################################################
67 //########################################################################
70 //#################
71 //# ENCODER
72 //#################
75 static const char *base64encode =
76 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
80 /**
81 * Writes the specified byte to the output buffer
82 */
83 void Base64Encoder::append(int ch)
84 {
85 outBuf <<= 8;
86 outBuf |= (ch & 0xff);
87 bitCount += 8;
88 if (bitCount >= 24)
89 {
90 int indx = (int)((outBuf & 0x00fc0000L) >> 18);
91 int obyte = (int)base64encode[indx & 63];
92 buf.push_back(obyte);
94 indx = (int)((outBuf & 0x0003f000L) >> 12);
95 obyte = (int)base64encode[indx & 63];
96 buf.push_back(obyte);
98 indx = (int)((outBuf & 0x00000fc0L) >> 6);
99 obyte = (int)base64encode[indx & 63];
100 buf.push_back(obyte);
102 indx = (int)((outBuf & 0x0000003fL) );
103 obyte = (int)base64encode[indx & 63];
104 buf.push_back(obyte);
106 bitCount = 0;
107 outBuf = 0L;
108 }
109 }
111 /**
112 * Writes the specified string to the output buffer
113 */
114 void Base64Encoder::append(char *str)
115 {
116 while (*str)
117 append((int)*str++);
118 }
120 /**
121 * Writes the specified string to the output buffer
122 */
123 void Base64Encoder::append(unsigned char *str, int len)
124 {
125 while (len>0)
126 {
127 append((int)*str++);
128 len--;
129 }
130 }
132 /**
133 * Writes the specified string to the output buffer
134 */
135 void Base64Encoder::append(const DOMString &str)
136 {
137 append((char *)str.c_str());
138 }
140 /**
141 * Closes this output stream and releases any system resources
142 * associated with this stream.
143 */
144 DOMString Base64Encoder::finish()
145 {
146 //get any last bytes (1 or 2) out of the buffer
147 if (bitCount == 16)
148 {
149 outBuf <<= 2; //pad to make 18 bits
151 int indx = (int)((outBuf & 0x0003f000L) >> 12);
152 int obyte = (int)base64encode[indx & 63];
153 buf.push_back(obyte);
155 indx = (int)((outBuf & 0x00000fc0L) >> 6);
156 obyte = (int)base64encode[indx & 63];
157 buf.push_back(obyte);
159 indx = (int)((outBuf & 0x0000003fL) );
160 obyte = (int)base64encode[indx & 63];
161 buf.push_back(obyte);
163 buf.push_back('=');
164 }
165 else if (bitCount == 8)
166 {
167 outBuf <<= 4; //pad to make 12 bits
169 int indx = (int)((outBuf & 0x00000fc0L) >> 6);
170 int obyte = (int)base64encode[indx & 63];
171 buf.push_back(obyte);
173 indx = (int)((outBuf & 0x0000003fL) );
174 obyte = (int)base64encode[indx & 63];
175 buf.push_back(obyte);
177 buf.push_back('=');
178 buf.push_back('=');
179 }
181 DOMString ret = buf;
182 reset();
183 return ret;
184 }
187 DOMString Base64Encoder::encode(const DOMString &str)
188 {
189 Base64Encoder encoder;
190 encoder.append(str);
191 DOMString ret = encoder.finish();
192 return ret;
193 }
197 //#################
198 //# DECODER
199 //#################
201 static int base64decode[] =
202 {
203 /*00*/ -1, -1, -1, -1, -1, -1, -1, -1,
204 /*08*/ -1, -1, -1, -1, -1, -1, -1, -1,
205 /*10*/ -1, -1, -1, -1, -1, -1, -1, -1,
206 /*18*/ -1, -1, -1, -1, -1, -1, -1, -1,
207 /*20*/ -1, -1, -1, -1, -1, -1, -1, -1,
208 /*28*/ -1, -1, -1, 62, -1, -1, -1, 63,
209 /*30*/ 52, 53, 54, 55, 56, 57, 58, 59,
210 /*38*/ 60, 61, -1, -1, -1, -1, -1, -1,
211 /*40*/ -1, 0, 1, 2, 3, 4, 5, 6,
212 /*48*/ 7, 8, 9, 10, 11, 12, 13, 14,
213 /*50*/ 15, 16, 17, 18, 19, 20, 21, 22,
214 /*58*/ 23, 24, 25, -1, -1, -1, -1, -1,
215 /*60*/ -1, 26, 27, 28, 29, 30, 31, 32,
216 /*68*/ 33, 34, 35, 36, 37, 38, 39, 40,
217 /*70*/ 41, 42, 43, 44, 45, 46, 47, 48,
218 /*78*/ 49, 50, 51, -1, -1, -1, -1, -1
219 };
223 /**
224 * Appends one char to the decoder
225 */
226 void Base64Decoder::append(int ch)
227 {
228 if (isspace(ch))
229 return;
230 else if (ch == '=') //padding
231 {
232 inBytes[inCount++] = 0;
233 }
234 else
235 {
236 int byteVal = base64decode[ch & 0x7f];
237 //printf("char:%c %d\n", ch, byteVal);
238 if (byteVal < 0)
239 {
240 //Bad lookup value
241 }
242 inBytes[inCount++] = byteVal;
243 }
245 if (inCount >=4 )
246 {
247 unsigned char b0 = ((inBytes[0]<<2) & 0xfc) | ((inBytes[1]>>4) & 0x03);
248 unsigned char b1 = ((inBytes[1]<<4) & 0xf0) | ((inBytes[2]>>2) & 0x0f);
249 unsigned char b2 = ((inBytes[2]<<6) & 0xc0) | ((inBytes[3] ) & 0x3f);
250 buf.push_back(b0);
251 buf.push_back(b1);
252 buf.push_back(b2);
253 inCount = 0;
254 }
256 }
258 void Base64Decoder::append(char *str)
259 {
260 while (*str)
261 append((int)*str++);
262 }
264 void Base64Decoder::append(const DOMString &str)
265 {
266 append((char *)str.c_str());
267 }
269 std::vector<unsigned char> Base64Decoder::finish()
270 {
271 std::vector<unsigned char> ret = buf;
272 reset();
273 return ret;
274 }
276 std::vector<unsigned char> Base64Decoder::decode(const DOMString &str)
277 {
278 Base64Decoder decoder;
279 decoder.append(str);
280 std::vector<unsigned char> ret = decoder.finish();
281 return ret;
282 }
284 DOMString Base64Decoder::decodeToString(const DOMString &str)
285 {
286 Base64Decoder decoder;
287 decoder.append(str);
288 std::vector<unsigned char> ret = decoder.finish();
289 DOMString buf;
290 for (unsigned int i=0 ; i<ret.size() ; i++)
291 buf.push_back(ret[i]);
292 return buf;
293 }
301 //########################################################################
302 //########################################################################
303 //### S H A 1 H A S H I N G
304 //########################################################################
305 //########################################################################
307 void Sha1::hash(unsigned char *dataIn, int len, unsigned char *digest)
308 {
309 Sha1 sha1;
310 sha1.append(dataIn, len);
311 sha1.finish(digest);
312 }
314 static const char *sha1hex = "0123456789abcdef";
316 DOMString Sha1::hashHex(unsigned char *dataIn, int len)
317 {
318 unsigned char hashout[20];
319 hash(dataIn, len, hashout);
320 DOMString ret;
321 for (int i=0 ; i<20 ; i++)
322 {
323 unsigned char ch = hashout[i];
324 ret.push_back(sha1hex[ (ch>>4) & 15 ]);
325 ret.push_back(sha1hex[ ch & 15 ]);
326 }
327 return ret;
328 }
331 DOMString Sha1::hashHex(const DOMString &str)
332 {
333 return hashHex((unsigned char *)str.c_str(), str.size());
334 }
337 void Sha1::init()
338 {
340 longNr = 0;
341 byteNr = 0;
342 nrBytesHi = 0;
343 nrBytesLo = 0;
345 // Initialize H with the magic constants (see FIPS180 for constants)
346 hashBuf[0] = 0x67452301L;
347 hashBuf[1] = 0xefcdab89L;
348 hashBuf[2] = 0x98badcfeL;
349 hashBuf[3] = 0x10325476L;
350 hashBuf[4] = 0xc3d2e1f0L;
352 for (int i = 0; i < 4; i++)
353 inb[i] = 0;
355 for (int i = 0; i < 80; i++)
356 inBuf[i] = 0;
357 }
360 void Sha1::append(unsigned char ch)
361 {
362 if (nrBytesLo == 0xffffffffL)
363 {
364 nrBytesHi++;
365 nrBytesLo = 0;
366 }
367 else
368 nrBytesLo++;
370 inb[byteNr++] = (unsigned long)ch;
371 if (byteNr >= 4)
372 {
373 inBuf[longNr++] = inb[0] << 24 | inb[1] << 16 |
374 inb[2] << 8 | inb[3];
375 byteNr = 0;
376 }
377 if (longNr >= 16)
378 {
379 transform();
380 longNr = 0;
381 }
382 }
385 void Sha1::append(unsigned char *dataIn, int len)
386 {
387 for (int i = 0; i < len; i++)
388 append(dataIn[i]);
389 }
392 void Sha1::append(const DOMString &str)
393 {
394 append((unsigned char *)str.c_str(), str.size());
395 }
398 void Sha1::finish(unsigned char digest[20])
399 {
400 //snapshot the bit count now before padding
401 unsigned long nrBitsLo = (nrBytesLo << 3) & 0xffffffff;
402 unsigned long nrBitsHi = (nrBytesHi << 3) | ((nrBytesLo >> 29) & 7);
404 //Append terminal char
405 append(0x80);
407 //pad until we have a 56 of 64 bytes, allowing for 8 bytes at the end
408 while (longNr != 14)
409 append(0);
412 //##### Append length in bits
413 append((unsigned char)((nrBitsHi>>24) & 0xff));
414 append((unsigned char)((nrBitsHi>>16) & 0xff));
415 append((unsigned char)((nrBitsHi>> 8) & 0xff));
416 append((unsigned char)((nrBitsHi ) & 0xff));
417 append((unsigned char)((nrBitsLo>>24) & 0xff));
418 append((unsigned char)((nrBitsLo>>16) & 0xff));
419 append((unsigned char)((nrBitsLo>> 8) & 0xff));
420 append((unsigned char)((nrBitsLo ) & 0xff));
423 //copy out answer
424 int indx = 0;
425 for (int i=0 ; i<5 ; i++)
426 {
427 digest[indx++] = (unsigned char)((hashBuf[i] >> 24) & 0xff);
428 digest[indx++] = (unsigned char)((hashBuf[i] >> 16) & 0xff);
429 digest[indx++] = (unsigned char)((hashBuf[i] >> 8) & 0xff);
430 digest[indx++] = (unsigned char)((hashBuf[i] ) & 0xff);
431 }
433 // Re-initialize the context (also zeroizes contents)
434 init();
435 }
439 #define SHA_ROTL(X,n) ((((X) << (n)) & 0xffffffff) | (((X) >> (32-(n))) & 0xffffffff))
441 void Sha1::transform()
442 {
443 unsigned long *W = inBuf;
444 unsigned long *H = hashBuf;
446 for (int t = 16; t <= 79; t++)
447 W[t] = SHA_ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
449 unsigned long A = H[0];
450 unsigned long B = H[1];
451 unsigned long C = H[2];
452 unsigned long D = H[3];
453 unsigned long E = H[4];
455 unsigned long TEMP;
457 for (int t = 0; t <= 19; t++)
458 {
459 TEMP = (SHA_ROTL(A,5) + ((B&C)|((~B)&D)) +
460 E + W[t] + 0x5a827999L) & 0xffffffffL;
461 E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
462 }
463 for (int t = 20; t <= 39; t++)
464 {
465 TEMP = (SHA_ROTL(A,5) + (B^C^D) +
466 E + W[t] + 0x6ed9eba1L) & 0xffffffffL;
467 E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
468 }
469 for (int t = 40; t <= 59; t++)
470 {
471 TEMP = (SHA_ROTL(A,5) + ((B&C)|(B&D)|(C&D)) +
472 E + W[t] + 0x8f1bbcdcL) & 0xffffffffL;
473 E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
474 }
475 for (int t = 60; t <= 79; t++)
476 {
477 TEMP = (SHA_ROTL(A,5) + (B^C^D) +
478 E + W[t] + 0xca62c1d6L) & 0xffffffffL;
479 E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
480 }
482 H[0] = (H[0] + A) & 0xffffffffL;
483 H[1] = (H[1] + B) & 0xffffffffL;
484 H[2] = (H[2] + C) & 0xffffffffL;
485 H[3] = (H[3] + D) & 0xffffffffL;
486 H[4] = (H[4] + E) & 0xffffffffL;
487 }
491 //########################################################################
492 //########################################################################
493 //### M D 5 H A S H I N G
494 //########################################################################
495 //########################################################################
500 void Md5::hash(unsigned char *dataIn, unsigned long len, unsigned char *digest)
501 {
502 Md5 md5;
503 md5.append(dataIn, len);
504 md5.finish(digest);
505 }
507 DOMString Md5::hashHex(unsigned char *dataIn, unsigned long len)
508 {
509 Md5 md5;
510 md5.append(dataIn, len);
511 DOMString ret = md5.finishHex();
512 return ret;
513 }
515 DOMString Md5::hashHex(const DOMString &str)
516 {
517 Md5 md5;
518 md5.append(str);
519 DOMString ret = md5.finishHex();
520 return ret;
521 }
524 /**
525 * Initialize MD5 polynomials and storage
526 */
527 void Md5::init()
528 {
529 hashBuf[0] = 0x67452301;
530 hashBuf[1] = 0xefcdab89;
531 hashBuf[2] = 0x98badcfe;
532 hashBuf[3] = 0x10325476;
534 nrBytesHi = 0;
535 nrBytesLo = 0;
536 byteNr = 0;
537 longNr = 0;
538 }
543 /**
544 * Update with one character
545 */
546 void Md5::append(unsigned char ch)
547 {
548 if (nrBytesLo == 0xffffffff)
549 {
550 nrBytesLo = 0;
551 nrBytesHi++;
552 }
553 else
554 nrBytesLo++;
556 //pack 64 bytes into 16 longs
557 inb[byteNr++] = (unsigned long)ch;
558 if (byteNr >= 4)
559 {
560 unsigned long val =
561 inb[3] << 24 | inb[2] << 16 | inb[1] << 8 | inb[0];
562 inBuf[longNr++] = val;
563 byteNr = 0;
564 }
565 if (longNr >= 16)
566 {
567 transform();
568 longNr = 0;
569 }
570 }
573 /*
574 * Update context to reflect the concatenation of another buffer full
575 * of bytes.
576 */
577 void Md5::append(unsigned char *source, unsigned long len)
578 {
579 while (len--)
580 append(*source++);
581 }
584 /*
585 * Update context to reflect the concatenation of another string
586 */
587 void Md5::append(const DOMString &str)
588 {
589 append((unsigned char *)str.c_str(), str.size());
590 }
593 /*
594 * Final wrapup - pad to 64-byte boundary with the bit pattern
595 * 1 0* (64-bit count of bits processed, MSB-first)
596 */
597 void Md5::finish(unsigned char *digest)
598 {
599 //snapshot the bit count now before padding
600 unsigned long nrBitsLo = (nrBytesLo << 3) & 0xffffffff;
601 unsigned long nrBitsHi = (nrBytesHi << 3) | ((nrBytesLo >> 29) & 7);
603 //Append terminal char
604 append(0x80);
606 //pad until we have a 56 of 64 bytes, allowing for 8 bytes at the end
607 while (longNr != 14)
608 append(0);
610 //##### Append length in bits
611 append((unsigned char)((nrBitsLo ) & 0xff));
612 append((unsigned char)((nrBitsLo>> 8) & 0xff));
613 append((unsigned char)((nrBitsLo>>16) & 0xff));
614 append((unsigned char)((nrBitsLo>>24) & 0xff));
615 append((unsigned char)((nrBitsHi ) & 0xff));
616 append((unsigned char)((nrBitsHi>> 8) & 0xff));
617 append((unsigned char)((nrBitsHi>>16) & 0xff));
618 append((unsigned char)((nrBitsHi>>24) & 0xff));
620 //copy out answer
621 int indx = 0;
622 for (int i=0 ; i<4 ; i++)
623 {
624 digest[indx++] = (unsigned char)((hashBuf[i] ) & 0xff);
625 digest[indx++] = (unsigned char)((hashBuf[i] >> 8) & 0xff);
626 digest[indx++] = (unsigned char)((hashBuf[i] >> 16) & 0xff);
627 digest[indx++] = (unsigned char)((hashBuf[i] >> 24) & 0xff);
628 }
630 init(); // Security! ;-)
631 }
635 static const char *md5hex = "0123456789abcdef";
637 DOMString Md5::finishHex()
638 {
639 unsigned char hashout[16];
640 finish(hashout);
641 DOMString ret;
642 for (int i=0 ; i<16 ; i++)
643 {
644 unsigned char ch = hashout[i];
645 ret.push_back(md5hex[ (ch>>4) & 15 ]);
646 ret.push_back(md5hex[ ch & 15 ]);
647 }
648 return ret;
649 }
653 //# The four core functions - F1 is optimized somewhat
655 // #define F1(x, y, z) (x & y | ~x & z)
656 #define M(x) ((x) &= 0xffffffff)
657 #define F1(x, y, z) (z ^ (x & (y ^ z)))
658 #define F2(x, y, z) F1(z, x, y)
659 #define F3(x, y, z) (x ^ y ^ z)
660 #define F4(x, y, z) (y ^ (x | ~z))
662 // ## This is the central step in the MD5 algorithm.
663 #define MD5STEP(f, w, x, y, z, data, s) \
664 ( w += (f(x, y, z) + data), M(w), w = w<<s | w>>(32-s), w += x, M(w) )
666 /*
667 * The core of the MD5 algorithm, this alters an existing MD5 hash to
668 * reflect the addition of 16 longwords of new data. MD5Update blocks
669 * the data and converts bytes into longwords for this routine.
670 * @parm buf points to an array of 4 unsigned 32bit (at least) integers
671 * @parm in points to an array of 16 unsigned 32bit (at least) integers
672 */
673 void Md5::transform()
674 {
675 unsigned long *i = inBuf;
676 unsigned long a = hashBuf[0];
677 unsigned long b = hashBuf[1];
678 unsigned long c = hashBuf[2];
679 unsigned long d = hashBuf[3];
681 MD5STEP(F1, a, b, c, d, i[ 0] + 0xd76aa478, 7);
682 MD5STEP(F1, d, a, b, c, i[ 1] + 0xe8c7b756, 12);
683 MD5STEP(F1, c, d, a, b, i[ 2] + 0x242070db, 17);
684 MD5STEP(F1, b, c, d, a, i[ 3] + 0xc1bdceee, 22);
685 MD5STEP(F1, a, b, c, d, i[ 4] + 0xf57c0faf, 7);
686 MD5STEP(F1, d, a, b, c, i[ 5] + 0x4787c62a, 12);
687 MD5STEP(F1, c, d, a, b, i[ 6] + 0xa8304613, 17);
688 MD5STEP(F1, b, c, d, a, i[ 7] + 0xfd469501, 22);
689 MD5STEP(F1, a, b, c, d, i[ 8] + 0x698098d8, 7);
690 MD5STEP(F1, d, a, b, c, i[ 9] + 0x8b44f7af, 12);
691 MD5STEP(F1, c, d, a, b, i[10] + 0xffff5bb1, 17);
692 MD5STEP(F1, b, c, d, a, i[11] + 0x895cd7be, 22);
693 MD5STEP(F1, a, b, c, d, i[12] + 0x6b901122, 7);
694 MD5STEP(F1, d, a, b, c, i[13] + 0xfd987193, 12);
695 MD5STEP(F1, c, d, a, b, i[14] + 0xa679438e, 17);
696 MD5STEP(F1, b, c, d, a, i[15] + 0x49b40821, 22);
698 MD5STEP(F2, a, b, c, d, i[ 1] + 0xf61e2562, 5);
699 MD5STEP(F2, d, a, b, c, i[ 6] + 0xc040b340, 9);
700 MD5STEP(F2, c, d, a, b, i[11] + 0x265e5a51, 14);
701 MD5STEP(F2, b, c, d, a, i[ 0] + 0xe9b6c7aa, 20);
702 MD5STEP(F2, a, b, c, d, i[ 5] + 0xd62f105d, 5);
703 MD5STEP(F2, d, a, b, c, i[10] + 0x02441453, 9);
704 MD5STEP(F2, c, d, a, b, i[15] + 0xd8a1e681, 14);
705 MD5STEP(F2, b, c, d, a, i[ 4] + 0xe7d3fbc8, 20);
706 MD5STEP(F2, a, b, c, d, i[ 9] + 0x21e1cde6, 5);
707 MD5STEP(F2, d, a, b, c, i[14] + 0xc33707d6, 9);
708 MD5STEP(F2, c, d, a, b, i[ 3] + 0xf4d50d87, 14);
709 MD5STEP(F2, b, c, d, a, i[ 8] + 0x455a14ed, 20);
710 MD5STEP(F2, a, b, c, d, i[13] + 0xa9e3e905, 5);
711 MD5STEP(F2, d, a, b, c, i[ 2] + 0xfcefa3f8, 9);
712 MD5STEP(F2, c, d, a, b, i[ 7] + 0x676f02d9, 14);
713 MD5STEP(F2, b, c, d, a, i[12] + 0x8d2a4c8a, 20);
715 MD5STEP(F3, a, b, c, d, i[ 5] + 0xfffa3942, 4);
716 MD5STEP(F3, d, a, b, c, i[ 8] + 0x8771f681, 11);
717 MD5STEP(F3, c, d, a, b, i[11] + 0x6d9d6122, 16);
718 MD5STEP(F3, b, c, d, a, i[14] + 0xfde5380c, 23);
719 MD5STEP(F3, a, b, c, d, i[ 1] + 0xa4beea44, 4);
720 MD5STEP(F3, d, a, b, c, i[ 4] + 0x4bdecfa9, 11);
721 MD5STEP(F3, c, d, a, b, i[ 7] + 0xf6bb4b60, 16);
722 MD5STEP(F3, b, c, d, a, i[10] + 0xbebfbc70, 23);
723 MD5STEP(F3, a, b, c, d, i[13] + 0x289b7ec6, 4);
724 MD5STEP(F3, d, a, b, c, i[ 0] + 0xeaa127fa, 11);
725 MD5STEP(F3, c, d, a, b, i[ 3] + 0xd4ef3085, 16);
726 MD5STEP(F3, b, c, d, a, i[ 6] + 0x04881d05, 23);
727 MD5STEP(F3, a, b, c, d, i[ 9] + 0xd9d4d039, 4);
728 MD5STEP(F3, d, a, b, c, i[12] + 0xe6db99e5, 11);
729 MD5STEP(F3, c, d, a, b, i[15] + 0x1fa27cf8, 16);
730 MD5STEP(F3, b, c, d, a, i[ 2] + 0xc4ac5665, 23);
732 MD5STEP(F4, a, b, c, d, i[ 0] + 0xf4292244, 6);
733 MD5STEP(F4, d, a, b, c, i[ 7] + 0x432aff97, 10);
734 MD5STEP(F4, c, d, a, b, i[14] + 0xab9423a7, 15);
735 MD5STEP(F4, b, c, d, a, i[ 5] + 0xfc93a039, 21);
736 MD5STEP(F4, a, b, c, d, i[12] + 0x655b59c3, 6);
737 MD5STEP(F4, d, a, b, c, i[ 3] + 0x8f0ccc92, 10);
738 MD5STEP(F4, c, d, a, b, i[10] + 0xffeff47d, 15);
739 MD5STEP(F4, b, c, d, a, i[ 1] + 0x85845dd1, 21);
740 MD5STEP(F4, a, b, c, d, i[ 8] + 0x6fa87e4f, 6);
741 MD5STEP(F4, d, a, b, c, i[15] + 0xfe2ce6e0, 10);
742 MD5STEP(F4, c, d, a, b, i[ 6] + 0xa3014314, 15);
743 MD5STEP(F4, b, c, d, a, i[13] + 0x4e0811a1, 21);
744 MD5STEP(F4, a, b, c, d, i[ 4] + 0xf7537e82, 6);
745 MD5STEP(F4, d, a, b, c, i[11] + 0xbd3af235, 10);
746 MD5STEP(F4, c, d, a, b, i[ 2] + 0x2ad7d2bb, 15);
747 MD5STEP(F4, b, c, d, a, i[ 9] + 0xeb86d391, 21);
749 hashBuf[0] += a;
750 hashBuf[1] += b;
751 hashBuf[2] += c;
752 hashBuf[3] += d;
753 }
759 //########################################################################
760 //########################################################################
761 //### T H R E A D
762 //########################################################################
763 //########################################################################
769 #ifdef __WIN32__
772 static DWORD WINAPI WinThreadFunction(LPVOID context)
773 {
774 Thread *thread = (Thread *)context;
775 thread->execute();
776 return 0;
777 }
780 void Thread::start()
781 {
782 DWORD dwThreadId;
783 HANDLE hThread = CreateThread(NULL, 0, WinThreadFunction,
784 (LPVOID)this, 0, &dwThreadId);
785 //Make sure the thread is started before 'this' is deallocated
786 while (!started)
787 sleep(10);
788 CloseHandle(hThread);
789 }
791 void Thread::sleep(unsigned long millis)
792 {
793 Sleep(millis);
794 }
796 #else /* UNIX */
799 void *PthreadThreadFunction(void *context)
800 {
801 Thread *thread = (Thread *)context;
802 thread->execute();
803 return NULL;
804 }
807 void Thread::start()
808 {
809 pthread_t thread;
811 int ret = pthread_create(&thread, NULL,
812 PthreadThreadFunction, (void *)this);
813 if (ret != 0)
814 printf("Thread::start: thread creation failed: %s\n", strerror(ret));
816 //Make sure the thread is started before 'this' is deallocated
817 while (!started)
818 sleep(10);
820 }
822 void Thread::sleep(unsigned long millis)
823 {
824 timespec requested;
825 requested.tv_sec = millis / 1000;
826 requested.tv_nsec = (millis % 1000 ) * 1000000L;
827 nanosleep(&requested, NULL);
828 }
830 #endif
839 //########################################################################
840 //########################################################################
841 //### S O C K E T
842 //########################################################################
843 //########################################################################
849 //#########################################################################
850 //# U T I L I T Y
851 //#########################################################################
853 static void mybzero(void *s, size_t n)
854 {
855 unsigned char *p = (unsigned char *)s;
856 while (n > 0)
857 {
858 *p++ = (unsigned char)0;
859 n--;
860 }
861 }
863 static void mybcopy(void *src, void *dest, size_t n)
864 {
865 unsigned char *p = (unsigned char *)dest;
866 unsigned char *q = (unsigned char *)src;
867 while (n > 0)
868 {
869 *p++ = *q++;
870 n--;
871 }
872 }
876 //#########################################################################
877 //# T C P C O N N E C T I O N
878 //#########################################################################
880 TcpSocket::TcpSocket()
881 {
882 init();
883 }
886 TcpSocket::TcpSocket(const std::string &hostnameArg, int port)
887 {
888 init();
889 hostname = hostnameArg;
890 portno = port;
891 }
896 #ifdef HAVE_SSL
898 static void cryptoLockCallback(int mode, int type, const char */*file*/, int /*line*/)
899 {
900 //printf("########### LOCK\n");
901 static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
902 const char *errstr = NULL;
904 int rw = mode & (CRYPTO_READ|CRYPTO_WRITE);
905 if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE)))
906 {
907 errstr = "invalid mode";
908 goto err;
909 }
911 if (type < 0 || type >= CRYPTO_NUM_LOCKS)
912 {
913 errstr = "type out of bounds";
914 goto err;
915 }
917 if (mode & CRYPTO_LOCK)
918 {
919 if (modes[type])
920 {
921 errstr = "already locked";
922 /* must not happen in a single-threaded program
923 * (would deadlock)
924 */
925 goto err;
926 }
928 modes[type] = rw;
929 }
930 else if (mode & CRYPTO_UNLOCK)
931 {
932 if (!modes[type])
933 {
934 errstr = "not locked";
935 goto err;
936 }
938 if (modes[type] != rw)
939 {
940 errstr = (rw == CRYPTO_READ) ?
941 "CRYPTO_r_unlock on write lock" :
942 "CRYPTO_w_unlock on read lock";
943 }
945 modes[type] = 0;
946 }
947 else
948 {
949 errstr = "invalid mode";
950 goto err;
951 }
953 err:
954 if (errstr)
955 {
956 //how do we pass a context pointer here?
957 //error("openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d",
958 // errstr, mode, type, file, line);
959 }
960 }
962 static unsigned long cryptoIdCallback()
963 {
964 #ifdef __WIN32__
965 unsigned long ret = (unsigned long) GetCurrentThreadId();
966 #else
967 unsigned long ret = (unsigned long) pthread_self();
968 #endif
969 return ret;
970 }
972 #endif
975 TcpSocket::TcpSocket(const TcpSocket &other)
976 {
977 init();
978 sock = other.sock;
979 hostname = other.hostname;
980 portno = other.portno;
981 }
984 void TcpSocket::error(const char *fmt, ...)
985 {
986 static char buf[256];
987 lastError = "TcpSocket err: ";
988 va_list args;
989 va_start(args, fmt);
990 vsnprintf(buf, 255, fmt, args);
991 va_end(args);
992 lastError.append(buf);
993 fprintf(stderr, "%s\n", lastError.c_str());
994 }
997 DOMString &TcpSocket::getLastError()
998 {
999 return lastError;
1000 }
1004 static bool tcp_socket_inited = false;
1006 void TcpSocket::init()
1007 {
1008 if (!tcp_socket_inited)
1009 {
1010 #ifdef __WIN32__
1011 WORD wVersionRequested = MAKEWORD( 2, 2 );
1012 WSADATA wsaData;
1013 WSAStartup( wVersionRequested, &wsaData );
1014 #endif
1015 #ifdef HAVE_SSL
1016 if (libssl_is_present)
1017 {
1018 sslStream = NULL;
1019 sslContext = NULL;
1020 CRYPTO_set_locking_callback(cryptoLockCallback);
1021 CRYPTO_set_id_callback(cryptoIdCallback);
1022 SSL_library_init();
1023 SSL_load_error_strings();
1024 }
1025 #endif
1026 tcp_socket_inited = true;
1027 }
1028 sock = -1;
1029 connected = false;
1030 hostname = "";
1031 portno = -1;
1032 sslEnabled = false;
1033 receiveTimeout = 0;
1034 }
1036 TcpSocket::~TcpSocket()
1037 {
1038 disconnect();
1039 }
1041 bool TcpSocket::isConnected()
1042 {
1043 if (!connected || sock < 0)
1044 return false;
1045 return true;
1046 }
1048 bool TcpSocket::getHaveSSL()
1049 {
1050 #ifdef HAVE_SSL
1051 if (libssl_is_present)
1052 {
1053 return true;
1054 } else {
1055 return false;
1056 }
1057 #else
1058 return false;
1059 #endif
1060 }
1062 void TcpSocket::enableSSL(bool val)
1063 {
1064 sslEnabled = val;
1065 }
1067 bool TcpSocket::getEnableSSL()
1068 {
1069 return sslEnabled;
1070 }
1074 bool TcpSocket::connect(const std::string &hostnameArg, int portnoArg)
1075 {
1076 hostname = hostnameArg;
1077 portno = portnoArg;
1078 return connect();
1079 }
1083 #ifdef HAVE_SSL
1084 /*
1085 static int password_cb(char *buf, int bufLen, int rwflag, void *userdata)
1086 {
1087 char *password = "password";
1088 if (bufLen < (int)(strlen(password)+1))
1089 return 0;
1091 strcpy(buf,password);
1092 int ret = strlen(password);
1093 return ret;
1094 }
1096 static void infoCallback(const SSL *ssl, int where, int ret)
1097 {
1098 switch (where)
1099 {
1100 case SSL_CB_ALERT:
1101 {
1102 printf("## %d SSL ALERT: %s\n", where, SSL_alert_desc_string_long(ret));
1103 break;
1104 }
1105 default:
1106 {
1107 printf("## %d SSL: %s\n", where, SSL_state_string_long(ssl));
1108 break;
1109 }
1110 }
1111 }
1112 */
1113 #endif
1116 bool TcpSocket::startTls()
1117 {
1118 #ifndef HAVE_SSL
1119 error("SSL starttls() error: client not compiled with SSL enabled");
1120 return false;
1121 #else /*HAVE_SSL*/
1122 if (!libssl_is_present)
1123 {
1124 error("SSL starttls() error: the correct version of libssl was not found");
1125 return false;
1126 }
1128 sslStream = NULL;
1129 sslContext = NULL;
1131 //SSL_METHOD *meth = SSLv23_method();
1132 //SSL_METHOD *meth = SSLv3_client_method();
1133 SSL_METHOD *meth = TLSv1_client_method();
1134 sslContext = SSL_CTX_new(meth);
1135 //SSL_CTX_set_info_callback(sslContext, infoCallback);
1137 /**
1138 * For now, let's accept all connections. Ignore this
1139 * block of code
1140 *
1141 char *keyFile = "client.pem";
1142 char *caList = "root.pem";
1143 //# Load our keys and certificates
1144 if (!(SSL_CTX_use_certificate_chain_file(sslContext, keyFile)))
1145 {
1146 fprintf(stderr, "Can't read certificate file\n");
1147 disconnect();
1148 return false;
1149 }
1151 SSL_CTX_set_default_passwd_cb(sslContext, password_cb);
1153 if (!(SSL_CTX_use_PrivateKey_file(sslContext, keyFile, SSL_FILETYPE_PEM)))
1154 {
1155 fprintf(stderr, "Can't read key file\n");
1156 disconnect();
1157 return false;
1158 }
1160 //## Load the CAs we trust
1161 if (!(SSL_CTX_load_verify_locations(sslContext, caList, 0)))
1162 {
1163 fprintf(stderr, "Can't read CA list\n");
1164 disconnect();
1165 return false;
1166 }
1167 */
1169 /* Connect the SSL socket */
1170 sslStream = SSL_new(sslContext);
1171 SSL_set_fd(sslStream, sock);
1173 int ret = SSL_connect(sslStream);
1174 if (ret == 0)
1175 {
1176 error("SSL connection not successful");
1177 disconnect();
1178 return false;
1179 }
1180 else if (ret < 0)
1181 {
1182 int err = SSL_get_error(sslStream, ret);
1183 error("SSL connect error %d", err);
1184 disconnect();
1185 return false;
1186 }
1188 sslEnabled = true;
1189 return true;
1190 #endif /* HAVE_SSL */
1191 }
1194 bool TcpSocket::connect()
1195 {
1196 if (hostname.size()<1)
1197 {
1198 error("open: null hostname");
1199 return false;
1200 }
1202 if (portno<1)
1203 {
1204 error("open: bad port number");
1205 return false;
1206 }
1208 sock = socket(PF_INET, SOCK_STREAM, 0);
1209 if (sock < 0)
1210 {
1211 error("open: error creating socket");
1212 return false;
1213 }
1215 char *c_hostname = (char *)hostname.c_str();
1216 struct hostent *server = gethostbyname(c_hostname);
1217 if (!server)
1218 {
1219 error("open: could not locate host '%s'", c_hostname);
1220 return false;
1221 }
1223 struct sockaddr_in serv_addr;
1224 mybzero((char *) &serv_addr, sizeof(serv_addr));
1225 serv_addr.sin_family = AF_INET;
1226 mybcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr,
1227 server->h_length);
1228 serv_addr.sin_port = htons(portno);
1230 int ret = ::connect(sock, (const sockaddr *)&serv_addr, sizeof(serv_addr));
1231 if (ret < 0)
1232 {
1233 error("open: could not connect to host '%s'", c_hostname);
1234 return false;
1235 }
1237 if (sslEnabled)
1238 {
1239 if (!startTls())
1240 return false;
1241 }
1242 connected = true;
1243 return true;
1244 }
1246 bool TcpSocket::disconnect()
1247 {
1248 bool ret = true;
1249 connected = false;
1250 #ifdef HAVE_SSL
1251 if (libssl_is_present)
1252 {
1253 if (sslEnabled)
1254 {
1255 if (sslStream)
1256 {
1257 int r = SSL_shutdown(sslStream);
1258 switch(r)
1259 {
1260 case 1:
1261 break; /* Success */
1262 case 0:
1263 case -1:
1264 default:
1265 error("Shutdown failed");
1266 ret = false;
1267 }
1268 SSL_free(sslStream);
1269 }
1270 if (sslContext)
1271 SSL_CTX_free(sslContext);
1272 }
1273 sslStream = NULL;
1274 sslContext = NULL;
1275 }
1276 #endif /*HAVE_SSL*/
1278 #ifdef __WIN32__
1279 closesocket(sock);
1280 #else
1281 ::close(sock);
1282 #endif
1283 sock = -1;
1284 sslEnabled = false;
1286 return ret;
1287 }
1291 bool TcpSocket::setReceiveTimeout(unsigned long millis)
1292 {
1293 receiveTimeout = millis;
1294 return true;
1295 }
1297 /**
1298 * For normal sockets, return the number of bytes waiting to be received.
1299 * For SSL, just return >0 when something is ready to be read.
1300 */
1301 long TcpSocket::available()
1302 {
1303 if (!isConnected())
1304 return -1;
1306 long count = 0;
1307 #ifdef __WIN32__
1308 if (ioctlsocket(sock, FIONREAD, (unsigned long *)&count) != 0)
1309 return -1;
1310 #else
1311 if (ioctl(sock, FIONREAD, &count) != 0)
1312 return -1;
1313 #endif
1314 if (count<=0 && sslEnabled)
1315 {
1316 #ifdef HAVE_SSL
1317 if (libssl_is_present)
1318 {
1319 return SSL_pending(sslStream);
1320 }
1321 #endif
1322 }
1323 return count;
1324 }
1328 bool TcpSocket::write(int ch)
1329 {
1330 if (!isConnected())
1331 {
1332 error("write: socket closed");
1333 return false;
1334 }
1335 unsigned char c = (unsigned char)ch;
1337 if (sslEnabled)
1338 {
1339 #ifdef HAVE_SSL
1340 if (libssl_is_present)
1341 {
1342 int r = SSL_write(sslStream, &c, 1);
1343 if (r<=0)
1344 {
1345 switch(SSL_get_error(sslStream, r))
1346 {
1347 default:
1348 error("SSL write problem");
1349 return -1;
1350 }
1351 }
1352 }
1353 #endif
1354 }
1355 else
1356 {
1357 if (send(sock, (const char *)&c, 1, 0) < 0)
1358 //if (send(sock, &c, 1, 0) < 0)
1359 {
1360 error("write: could not send data");
1361 return false;
1362 }
1363 }
1364 return true;
1365 }
1367 bool TcpSocket::write(char *str)
1368 {
1369 if (!isConnected())
1370 {
1371 error("write(str): socket closed");
1372 return false;
1373 }
1374 int len = strlen(str);
1376 if (sslEnabled)
1377 {
1378 #ifdef HAVE_SSL
1379 if (libssl_is_present)
1380 {
1381 int r = SSL_write(sslStream, (unsigned char *)str, len);
1382 if (r<=0)
1383 {
1384 switch(SSL_get_error(sslStream, r))
1385 {
1386 default:
1387 error("SSL write problem");
1388 return -1;
1389 }
1390 }
1391 }
1392 #endif
1393 }
1394 else
1395 {
1396 if (send(sock, str, len, 0) < 0)
1397 //if (send(sock, &c, 1, 0) < 0)
1398 {
1399 error("write: could not send data");
1400 return false;
1401 }
1402 }
1403 return true;
1404 }
1406 bool TcpSocket::write(const std::string &str)
1407 {
1408 return write((char *)str.c_str());
1409 }
1411 int TcpSocket::read()
1412 {
1413 if (!isConnected())
1414 return -1;
1416 //We'll use this loop for timeouts, so that SSL and plain sockets
1417 //will behave the same way
1418 if (receiveTimeout > 0)
1419 {
1420 unsigned long tim = 0;
1421 while (true)
1422 {
1423 int avail = available();
1424 if (avail > 0)
1425 break;
1426 if (tim >= receiveTimeout)
1427 return -2;
1428 Thread::sleep(20);
1429 tim += 20;
1430 }
1431 }
1433 //check again
1434 if (!isConnected())
1435 return -1;
1437 unsigned char ch;
1438 if (sslEnabled)
1439 {
1440 #ifdef HAVE_SSL
1441 if (libssl_is_present)
1442 {
1443 if (!sslStream)
1444 return -1;
1445 int r = SSL_read(sslStream, &ch, 1);
1446 unsigned long err = SSL_get_error(sslStream, r);
1447 switch (err)
1448 {
1449 case SSL_ERROR_NONE:
1450 break;
1451 case SSL_ERROR_ZERO_RETURN:
1452 return -1;
1453 case SSL_ERROR_SYSCALL:
1454 error("SSL read problem(syscall) %s",
1455 ERR_error_string(ERR_get_error(), NULL));
1456 return -1;
1457 default:
1458 error("SSL read problem %s",
1459 ERR_error_string(ERR_get_error(), NULL));
1460 return -1;
1461 }
1462 }
1463 #endif
1464 }
1465 else
1466 {
1467 if (recv(sock, (char *)&ch, 1, 0) <= 0)
1468 {
1469 error("read: could not receive data");
1470 disconnect();
1471 return -1;
1472 }
1473 }
1474 return (int)ch;
1475 }
1477 std::string TcpSocket::readLine()
1478 {
1479 std::string ret;
1481 while (isConnected())
1482 {
1483 int ch = read();
1484 if (ch<0)
1485 return ret;
1486 if (ch=='\r' || ch=='\n')
1487 return ret;
1488 ret.push_back((char)ch);
1489 }
1491 return ret;
1492 }
1502 } //namespace Pedro
1503 //########################################################################
1504 //# E N D O F F I L E
1505 //########################################################################