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>
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 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 //########################################################################
310 void Sha1::hash(unsigned char *dataIn, int len, unsigned char *digest)
311 {
312 Sha1 sha1;
313 sha1.append(dataIn, len);
314 sha1.finish(digest);
315 }
317 static char *sha1hex = "0123456789abcdef";
319 DOMString Sha1::hashHex(unsigned char *dataIn, int len)
320 {
321 unsigned char hashout[20];
322 hash(dataIn, len, hashout);
323 DOMString ret;
324 for (int i=0 ; i<20 ; i++)
325 {
326 unsigned char ch = hashout[i];
327 ret.push_back(sha1hex[ (ch>>4) & 15 ]);
328 ret.push_back(sha1hex[ ch & 15 ]);
329 }
330 return ret;
331 }
334 void Sha1::init()
335 {
337 lenW = 0;
338 sizeHi = 0;
339 sizeLo = 0;
341 // Initialize H with the magic constants (see FIPS180 for constants)
342 H[0] = 0x67452301L;
343 H[1] = 0xefcdab89L;
344 H[2] = 0x98badcfeL;
345 H[3] = 0x10325476L;
346 H[4] = 0xc3d2e1f0L;
348 for (int i = 0; i < 80; i++)
349 W[i] = 0;
350 }
353 void Sha1::append(unsigned char *dataIn, int len)
354 {
355 // Read the data into W and process blocks as they get full
356 for (int i = 0; i < len; i++)
357 {
358 W[lenW / 4] <<= 8;
359 W[lenW / 4] |= (unsigned long)dataIn[i];
360 if ((++lenW) % 64 == 0)
361 {
362 hashblock();
363 lenW = 0;
364 }
365 sizeLo += 8;
366 sizeHi += (sizeLo < 8);
367 }
368 }
371 void Sha1::finish(unsigned char hashout[20])
372 {
373 unsigned char pad0x80 = 0x80;
374 unsigned char pad0x00 = 0x00;
375 unsigned char padlen[8];
377 // Pad with a binary 1 (e.g. 0x80), then zeroes, then length
378 padlen[0] = (unsigned char)((sizeHi >> 24) & 255);
379 padlen[1] = (unsigned char)((sizeHi >> 16) & 255);
380 padlen[2] = (unsigned char)((sizeHi >> 8) & 255);
381 padlen[3] = (unsigned char)((sizeHi >> 0) & 255);
382 padlen[4] = (unsigned char)((sizeLo >> 24) & 255);
383 padlen[5] = (unsigned char)((sizeLo >> 16) & 255);
384 padlen[6] = (unsigned char)((sizeLo >> 8) & 255);
385 padlen[7] = (unsigned char)((sizeLo >> 0) & 255);
387 append(&pad0x80, 1);
389 while (lenW != 56)
390 append(&pad0x00, 1);
391 append(padlen, 8);
393 // Output hash
394 for (int i = 0; i < 20; i++)
395 {
396 hashout[i] = (unsigned char)(H[i / 4] >> 24);
397 H[i / 4] <<= 8;
398 }
400 // Re-initialize the context (also zeroizes contents)
401 init();
402 }
405 #define SHA_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xffffffffL)
407 void Sha1::hashblock()
408 {
410 for (int t = 16; t <= 79; t++)
411 W[t] = SHA_ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
413 unsigned long A = H[0];
414 unsigned long B = H[1];
415 unsigned long C = H[2];
416 unsigned long D = H[3];
417 unsigned long E = H[4];
419 unsigned long TEMP;
421 for (int t = 0; t <= 19; t++)
422 {
423 TEMP = (SHA_ROTL(A,5) + (((C^D)&B)^D) +
424 E + W[t] + 0x5a827999L) & 0xffffffffL;
425 E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
426 }
427 for (int t = 20; t <= 39; t++)
428 {
429 TEMP = (SHA_ROTL(A,5) + (B^C^D) +
430 E + W[t] + 0x6ed9eba1L) & 0xffffffffL;
431 E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
432 }
433 for (int t = 40; t <= 59; t++)
434 {
435 TEMP = (SHA_ROTL(A,5) + ((B&C)|(D&(B|C))) +
436 E + W[t] + 0x8f1bbcdcL) & 0xffffffffL;
437 E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
438 }
439 for (int t = 60; t <= 79; t++)
440 {
441 TEMP = (SHA_ROTL(A,5) + (B^C^D) +
442 E + W[t] + 0xca62c1d6L) & 0xffffffffL;
443 E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
444 }
446 H[0] += A;
447 H[1] += B;
448 H[2] += C;
449 H[3] += D;
450 H[4] += E;
451 }
458 //########################################################################
459 //########################################################################
460 //### M D 5 H A S H I N G
461 //########################################################################
462 //########################################################################
468 void Md5::hash(unsigned char *dataIn, unsigned long len, unsigned char *digest)
469 {
470 Md5 md5;
471 md5.append(dataIn, len);
472 md5.finish(digest);
473 }
475 DOMString Md5::hashHex(unsigned char *dataIn, unsigned long len)
476 {
477 Md5 md5;
478 md5.append(dataIn, len);
479 DOMString ret = md5.finishHex();
480 return ret;
481 }
485 /*
486 * Note: this code is harmless on little-endian machines.
487 */
488 /*
489 static void byteReverse(unsigned char *buf, unsigned long longs)
490 {
491 do
492 {
493 unsigned long t = (unsigned long)
494 ((unsigned) buf[3] << 8 | buf[2]) << 16 |
495 ((unsigned) buf[1] << 8 | buf[0]);
496 *(unsigned long *) buf = t;
497 buf += 4;
498 } while (--longs);
499 }
500 */
502 static void md5_memcpy(void *dest, void *src, int n)
503 {
504 unsigned char *s1 = (unsigned char *)dest;
505 unsigned char *s2 = (unsigned char *)src;
506 while (n--)
507 *s1++ = *s2++;
508 }
510 static void md5_memset(void *dest, char v, int n)
511 {
512 unsigned char *s = (unsigned char *)dest;
513 while (n--)
514 *s++ = v;
515 }
517 /**
518 * Initialize MD5 polynomials and storage
519 */
520 void Md5::init()
521 {
522 buf[0] = 0x67452301;
523 buf[1] = 0xefcdab89;
524 buf[2] = 0x98badcfe;
525 buf[3] = 0x10325476;
527 bits[0] = 0;
528 bits[1] = 0;
529 }
531 /*
532 * Update context to reflect the concatenation of another buffer full
533 * of bytes.
534 */
535 void Md5::append(unsigned char *source, unsigned long len)
536 {
538 // Update bitcount
539 unsigned long t = bits[0];
540 if ((bits[0] = t + ((unsigned long) len << 3)) < t)
541 bits[1]++;// Carry from low to high
542 bits[1] += len >> 29;
544 //Bytes already in shsInfo->data
545 t = (t >> 3) & 0x3f;
548 // Handle any leading odd-sized chunks
549 if (t)
550 {
551 unsigned char *p = (unsigned char *) in + t;
552 t = 64 - t;
553 if (len < t)
554 {
555 md5_memcpy(p, source, len);
556 return;
557 }
558 md5_memcpy(p, source, t);
559 //byteReverse(in, 16);
560 transform(buf, (unsigned long *) in);
561 source += t;
562 len -= t;
563 }
565 // Process data in 64-byte chunks
566 while (len >= 64)
567 {
568 md5_memcpy(in, source, 64);
569 //byteReverse(in, 16);
570 transform(buf, (unsigned long *) in);
571 source += 64;
572 len -= 64;
573 }
575 // Handle any remaining bytes of data.
576 md5_memcpy(in, source, len);
577 }
579 /*
580 * Update context to reflect the concatenation of another string
581 */
582 void Md5::append(const DOMString &str)
583 {
584 append((unsigned char *)str.c_str(), str.size());
585 }
587 /*
588 * Update context to reflect the concatenation of a single character
589 */
590 void Md5::append(unsigned char ch)
591 {
592 append(&ch, 1);
593 }
595 /*
596 * Final wrapup - pad to 64-byte boundary with the bit pattern
597 * 1 0* (64-bit count of bits processed, MSB-first)
598 */
599 void Md5::finish(unsigned char *digest)
600 {
601 // Compute number of bytes mod 64
602 unsigned int count = (bits[0] >> 3) & 0x3F;
604 // Set the first char of padding to 0x80.
605 // This is safe since there is always at least one byte free
606 unsigned char *p = in + count;
607 *p++ = 0x80;
609 // Bytes of padding needed to make 64 bytes
610 count = 64 - 1 - count;
612 // Pad out to 56 mod 64
613 if (count < 8)
614 {
615 // Two lots of padding: Pad the first block to 64 bytes
616 md5_memset(p, 0, count);
617 //byteReverse(in, 16);
618 transform(buf, (unsigned long *) in);
620 // Now fill the next block with 56 bytes
621 md5_memset(in, 0, 56);
622 }
623 else
624 {
625 // Pad block to 56 bytes
626 md5_memset(p, 0, count - 8);
627 }
628 //byteReverse(in, 14);
630 // Append length in bits and transform
631 ((unsigned long *) in)[14] = bits[0];
632 ((unsigned long *) in)[15] = bits[1];
634 transform(buf, (unsigned long *) in);
635 //byteReverse((unsigned char *) buf, 4);
636 md5_memcpy(digest, buf, 16);
637 init(); // Security! ;-)
638 }
640 static char *md5hex = "0123456789abcdef";
642 DOMString Md5::finishHex()
643 {
644 unsigned char hashout[16];
645 finish(hashout);
646 DOMString ret;
647 for (int i=0 ; i<16 ; i++)
648 {
649 unsigned char ch = hashout[i];
650 ret.push_back(md5hex[ (ch>>4) & 15 ]);
651 ret.push_back(md5hex[ ch & 15 ]);
652 }
653 return ret;
654 }
658 //# The four core functions - F1 is optimized somewhat
660 // #define F1(x, y, z) (x & y | ~x & z)
661 #define F1(x, y, z) (z ^ (x & (y ^ z)))
662 #define F2(x, y, z) F1(z, x, y)
663 #define F3(x, y, z) (x ^ y ^ z)
664 #define F4(x, y, z) (y ^ (x | ~z))
666 // ## This is the central step in the MD5 algorithm.
667 #define MD5STEP(f, w, x, y, z, data, s) \
668 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
670 /*
671 * The core of the MD5 algorithm, this alters an existing MD5 hash to
672 * reflect the addition of 16 longwords of new data. MD5Update blocks
673 * the data and converts bytes into longwords for this routine.
674 * @parm buf points to an array of 4 unsigned longs
675 * @parm in points to an array of 16 unsigned longs
676 */
677 void Md5::transform(unsigned long *buf, unsigned long *in)
678 {
679 unsigned long a = buf[0];
680 unsigned long b = buf[1];
681 unsigned long c = buf[2];
682 unsigned long d = buf[3];
684 MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7);
685 MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
686 MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
687 MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
688 MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7);
689 MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
690 MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
691 MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
692 MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7);
693 MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
694 MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
695 MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
696 MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
697 MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
698 MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
699 MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
701 MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5);
702 MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9);
703 MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
704 MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
705 MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5);
706 MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
707 MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
708 MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
709 MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5);
710 MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
711 MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
712 MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
713 MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
714 MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9);
715 MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
716 MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
718 MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4);
719 MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
720 MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
721 MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
722 MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4);
723 MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
724 MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
725 MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
726 MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
727 MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
728 MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
729 MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
730 MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4);
731 MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
732 MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
733 MD5STEP(F3, b, c, d, a, in[ 2] + 0xc4ac5665, 23);
735 MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6);
736 MD5STEP(F4, d, a, b, c, in[ 7] + 0x432aff97, 10);
737 MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
738 MD5STEP(F4, b, c, d, a, in[ 5] + 0xfc93a039, 21);
739 MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
740 MD5STEP(F4, d, a, b, c, in[ 3] + 0x8f0ccc92, 10);
741 MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
742 MD5STEP(F4, b, c, d, a, in[ 1] + 0x85845dd1, 21);
743 MD5STEP(F4, a, b, c, d, in[ 8] + 0x6fa87e4f, 6);
744 MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
745 MD5STEP(F4, c, d, a, b, in[ 6] + 0xa3014314, 15);
746 MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
747 MD5STEP(F4, a, b, c, d, in[ 4] + 0xf7537e82, 6);
748 MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
749 MD5STEP(F4, c, d, a, b, in[ 2] + 0x2ad7d2bb, 15);
750 MD5STEP(F4, b, c, d, a, in[ 9] + 0xeb86d391, 21);
752 buf[0] += a;
753 buf[1] += b;
754 buf[2] += c;
755 buf[3] += d;
756 }
767 //########################################################################
768 //########################################################################
769 //### T H R E A D
770 //########################################################################
771 //########################################################################
777 #ifdef __WIN32__
780 static DWORD WINAPI WinThreadFunction(LPVOID context)
781 {
782 Thread *thread = (Thread *)context;
783 thread->execute();
784 return 0;
785 }
788 void Thread::start()
789 {
790 DWORD dwThreadId;
791 HANDLE hThread = CreateThread(NULL, 0, WinThreadFunction,
792 (LPVOID)this, 0, &dwThreadId);
793 //Make sure the thread is started before 'this' is deallocated
794 while (!started)
795 sleep(10);
796 CloseHandle(hThread);
797 }
799 void Thread::sleep(unsigned long millis)
800 {
801 Sleep(millis);
802 }
804 #else /* UNIX */
807 void *PthreadThreadFunction(void *context)
808 {
809 Thread *thread = (Thread *)context;
810 thread->execute();
811 return NULL;
812 }
815 void Thread::start()
816 {
817 pthread_t thread;
819 int ret = pthread_create(&thread, NULL,
820 PthreadThreadFunction, (void *)this);
821 if (ret != 0)
822 printf("Thread::start: thread creation failed: %s\n", strerror(ret));
824 //Make sure the thread is started before 'this' is deallocated
825 while (!started)
826 sleep(10);
828 }
830 void Thread::sleep(unsigned long millis)
831 {
832 timespec requested;
833 requested.tv_sec = millis / 1000;
834 requested.tv_nsec = (millis % 1000 ) * 1000000L;
835 nanosleep(&requested, NULL);
836 }
838 #endif
847 //########################################################################
848 //########################################################################
849 //### S O C K E T
850 //########################################################################
851 //########################################################################
857 //#########################################################################
858 //# U T I L I T Y
859 //#########################################################################
861 static void mybzero(void *s, size_t n)
862 {
863 unsigned char *p = (unsigned char *)s;
864 while (n > 0)
865 {
866 *p++ = (unsigned char)0;
867 n--;
868 }
869 }
871 static void mybcopy(void *src, void *dest, size_t n)
872 {
873 unsigned char *p = (unsigned char *)dest;
874 unsigned char *q = (unsigned char *)src;
875 while (n > 0)
876 {
877 *p++ = *q++;
878 n--;
879 }
880 }
884 //#########################################################################
885 //# T C P C O N N E C T I O N
886 //#########################################################################
888 TcpSocket::TcpSocket()
889 {
890 init();
891 }
894 TcpSocket::TcpSocket(const std::string &hostnameArg, int port)
895 {
896 init();
897 hostname = hostnameArg;
898 portno = port;
899 }
902 #ifdef HAVE_SSL
904 static void cryptoLockCallback(int mode, int type, const char *file, int line)
905 {
906 //printf("########### LOCK\n");
907 static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
908 const char *errstr = NULL;
910 int rw = mode & (CRYPTO_READ|CRYPTO_WRITE);
911 if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE)))
912 {
913 errstr = "invalid mode";
914 goto err;
915 }
917 if (type < 0 || type >= CRYPTO_NUM_LOCKS)
918 {
919 errstr = "type out of bounds";
920 goto err;
921 }
923 if (mode & CRYPTO_LOCK)
924 {
925 if (modes[type])
926 {
927 errstr = "already locked";
928 /* must not happen in a single-threaded program
929 * (would deadlock)
930 */
931 goto err;
932 }
934 modes[type] = rw;
935 }
936 else if (mode & CRYPTO_UNLOCK)
937 {
938 if (!modes[type])
939 {
940 errstr = "not locked";
941 goto err;
942 }
944 if (modes[type] != rw)
945 {
946 errstr = (rw == CRYPTO_READ) ?
947 "CRYPTO_r_unlock on write lock" :
948 "CRYPTO_w_unlock on read lock";
949 }
951 modes[type] = 0;
952 }
953 else
954 {
955 errstr = "invalid mode";
956 goto err;
957 }
959 err:
960 if (errstr)
961 {
962 /* we cannot use bio_err here */
963 fprintf(stderr, "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n",
964 errstr, mode, type, file, line);
965 }
966 }
968 static unsigned long cryptoIdCallback()
969 {
970 #ifdef __WIN32__
971 unsigned long ret = (unsigned long) GetCurrentThreadId();
972 #else
973 unsigned long ret = (unsigned long) pthread_self();
974 #endif
975 return ret;
976 }
978 #endif
981 TcpSocket::TcpSocket(const TcpSocket &other)
982 {
983 init();
984 sock = other.sock;
985 hostname = other.hostname;
986 portno = other.portno;
987 }
989 static bool tcp_socket_inited = false;
991 void TcpSocket::init()
992 {
993 if (!tcp_socket_inited)
994 {
995 #ifdef __WIN32__
996 WORD wVersionRequested = MAKEWORD( 2, 2 );
997 WSADATA wsaData;
998 WSAStartup( wVersionRequested, &wsaData );
999 #endif
1000 #ifdef HAVE_SSL
1001 if (libssl_is_present)
1002 {
1003 sslStream = NULL;
1004 sslContext = NULL;
1005 CRYPTO_set_locking_callback(cryptoLockCallback);
1006 CRYPTO_set_id_callback(cryptoIdCallback);
1007 SSL_library_init();
1008 SSL_load_error_strings();
1009 }
1010 #endif
1011 tcp_socket_inited = true;
1012 }
1013 sock = -1;
1014 connected = false;
1015 hostname = "";
1016 portno = -1;
1017 sslEnabled = false;
1018 receiveTimeout = 0;
1019 }
1021 TcpSocket::~TcpSocket()
1022 {
1023 disconnect();
1024 }
1026 bool TcpSocket::isConnected()
1027 {
1028 if (!connected || sock < 0)
1029 return false;
1030 return true;
1031 }
1033 bool TcpSocket::getHaveSSL()
1034 {
1035 #ifdef HAVE_SSL
1036 if (libssl_is_present)
1037 {
1038 return true;
1039 } else {
1040 return false;
1041 }
1042 #else
1043 return false;
1044 #endif
1045 }
1047 void TcpSocket::enableSSL(bool val)
1048 {
1049 sslEnabled = val;
1050 }
1052 bool TcpSocket::getEnableSSL()
1053 {
1054 return sslEnabled;
1055 }
1059 bool TcpSocket::connect(const std::string &hostnameArg, int portnoArg)
1060 {
1061 hostname = hostnameArg;
1062 portno = portnoArg;
1063 return connect();
1064 }
1068 #ifdef HAVE_SSL
1069 /*
1070 static int password_cb(char *buf, int bufLen, int rwflag, void *userdata)
1071 {
1072 char *password = "password";
1073 if (bufLen < (int)(strlen(password)+1))
1074 return 0;
1076 strcpy(buf,password);
1077 int ret = strlen(password);
1078 return ret;
1079 }
1081 static void infoCallback(const SSL *ssl, int where, int ret)
1082 {
1083 switch (where)
1084 {
1085 case SSL_CB_ALERT:
1086 {
1087 printf("## %d SSL ALERT: %s\n", where, SSL_alert_desc_string_long(ret));
1088 break;
1089 }
1090 default:
1091 {
1092 printf("## %d SSL: %s\n", where, SSL_state_string_long(ssl));
1093 break;
1094 }
1095 }
1096 }
1097 */
1098 #endif
1101 bool TcpSocket::startTls()
1102 {
1103 #ifndef HAVE_SSL
1104 fprintf(stderr,
1105 "SSL starttls() error: client not compiled with SSL enabled\n");
1106 return false;
1107 #else /*HAVE_SSL*/
1108 if (!libssl_is_present)
1109 {
1110 fprintf(stderr,
1111 "SSL starttls() error: the correct version of libssl was not found \n");
1112 return false;
1113 } else {
1115 sslStream = NULL;
1116 sslContext = NULL;
1118 //SSL_METHOD *meth = SSLv23_method();
1119 //SSL_METHOD *meth = SSLv3_client_method();
1120 SSL_METHOD *meth = TLSv1_client_method();
1121 sslContext = SSL_CTX_new(meth);
1122 //SSL_CTX_set_info_callback(sslContext, infoCallback);
1124 /**
1125 * For now, let's accept all connections. Ignore this
1126 * block of code
1127 *
1128 char *keyFile = "client.pem";
1129 char *caList = "root.pem";
1130 //# Load our keys and certificates
1131 if (!(SSL_CTX_use_certificate_chain_file(sslContext, keyFile)))
1132 {
1133 fprintf(stderr, "Can't read certificate file\n");
1134 disconnect();
1135 return false;
1136 }
1138 SSL_CTX_set_default_passwd_cb(sslContext, password_cb);
1140 if (!(SSL_CTX_use_PrivateKey_file(sslContext, keyFile, SSL_FILETYPE_PEM)))
1141 {
1142 fprintf(stderr, "Can't read key file\n");
1143 disconnect();
1144 return false;
1145 }
1147 //## Load the CAs we trust
1148 if (!(SSL_CTX_load_verify_locations(sslContext, caList, 0)))
1149 {
1150 fprintf(stderr, "Can't read CA list\n");
1151 disconnect();
1152 return false;
1153 }
1154 */
1156 /* Connect the SSL socket */
1157 sslStream = SSL_new(sslContext);
1158 SSL_set_fd(sslStream, sock);
1160 int ret = SSL_connect(sslStream);
1161 if (ret == 0)
1162 {
1163 fprintf(stderr, "SSL connection not successful\n");
1164 disconnect();
1165 return false;
1166 }
1167 else if (ret < 0)
1168 {
1169 int err = SSL_get_error(sslStream, ret);
1170 fprintf(stderr, "SSL connect error %d\n", err);
1171 disconnect();
1172 return false;
1173 }
1175 sslEnabled = true;
1176 return true;
1177 }
1178 #endif /* HAVE_SSL */
1179 }
1182 bool TcpSocket::connect()
1183 {
1184 if (hostname.size()<1)
1185 {
1186 fprintf(stderr, "open: null hostname\n");
1187 return false;
1188 }
1190 if (portno<1)
1191 {
1192 fprintf(stderr, "open: bad port number\n");
1193 return false;
1194 }
1196 sock = socket(PF_INET, SOCK_STREAM, 0);
1197 if (sock < 0)
1198 {
1199 fprintf(stderr, "open: error creating socket\n");
1200 return false;
1201 }
1203 char *c_hostname = (char *)hostname.c_str();
1204 struct hostent *server = gethostbyname(c_hostname);
1205 if (!server)
1206 {
1207 fprintf(stderr, "open: could not locate host '%s'\n", c_hostname);
1208 return false;
1209 }
1211 struct sockaddr_in serv_addr;
1212 mybzero((char *) &serv_addr, sizeof(serv_addr));
1213 serv_addr.sin_family = AF_INET;
1214 mybcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr,
1215 server->h_length);
1216 serv_addr.sin_port = htons(portno);
1218 int ret = ::connect(sock, (const sockaddr *)&serv_addr, sizeof(serv_addr));
1219 if (ret < 0)
1220 {
1221 fprintf(stderr, "open: could not connect to host '%s'\n", c_hostname);
1222 return false;
1223 }
1225 if (sslEnabled)
1226 {
1227 if (!startTls())
1228 return false;
1229 }
1230 connected = true;
1231 return true;
1232 }
1234 bool TcpSocket::disconnect()
1235 {
1236 bool ret = true;
1237 connected = false;
1238 #ifdef HAVE_SSL
1239 if (libssl_is_present)
1240 {
1241 if (sslEnabled)
1242 {
1243 if (sslStream)
1244 {
1245 int r = SSL_shutdown(sslStream);
1246 switch(r)
1247 {
1248 case 1:
1249 break; /* Success */
1250 case 0:
1251 case -1:
1252 default:
1253 //printf("Shutdown failed");
1254 ret = false;
1255 }
1256 SSL_free(sslStream);
1257 }
1258 if (sslContext)
1259 SSL_CTX_free(sslContext);
1260 }
1261 sslStream = NULL;
1262 sslContext = NULL;
1263 }
1264 #endif /*HAVE_SSL*/
1266 #ifdef __WIN32__
1267 closesocket(sock);
1268 #else
1269 ::close(sock);
1270 #endif
1271 sock = -1;
1272 sslEnabled = false;
1274 return ret;
1275 }
1279 bool TcpSocket::setReceiveTimeout(unsigned long millis)
1280 {
1281 receiveTimeout = millis;
1282 return true;
1283 }
1285 /**
1286 * For normal sockets, return the number of bytes waiting to be received.
1287 * For SSL, just return >0 when something is ready to be read.
1288 */
1289 long TcpSocket::available()
1290 {
1291 if (!isConnected())
1292 return -1;
1294 long count = 0;
1295 #ifdef __WIN32__
1296 if (ioctlsocket(sock, FIONREAD, (unsigned long *)&count) != 0)
1297 return -1;
1298 #else
1299 if (ioctl(sock, FIONREAD, &count) != 0)
1300 return -1;
1301 #endif
1302 if (count<=0 && sslEnabled)
1303 {
1304 #ifdef HAVE_SSL
1305 if (libssl_is_present)
1306 {
1307 return SSL_pending(sslStream);
1308 }
1309 #endif
1310 }
1311 return count;
1312 }
1316 bool TcpSocket::write(int ch)
1317 {
1318 if (!isConnected())
1319 {
1320 fprintf(stderr, "write: socket closed\n");
1321 return false;
1322 }
1323 unsigned char c = (unsigned char)ch;
1325 if (sslEnabled)
1326 {
1327 #ifdef HAVE_SSL
1328 if (libssl_is_present)
1329 {
1330 int r = SSL_write(sslStream, &c, 1);
1331 if (r<=0)
1332 {
1333 switch(SSL_get_error(sslStream, r))
1334 {
1335 default:
1336 fprintf(stderr, "SSL write problem");
1337 return -1;
1338 }
1339 }
1340 }
1341 #endif
1342 }
1343 else
1344 {
1345 if (send(sock, (const char *)&c, 1, 0) < 0)
1346 //if (send(sock, &c, 1, 0) < 0)
1347 {
1348 fprintf(stderr, "write: could not send data\n");
1349 return false;
1350 }
1351 }
1352 return true;
1353 }
1355 bool TcpSocket::write(char *str)
1356 {
1357 if (!isConnected())
1358 {
1359 fprintf(stderr, "write(str): socket closed\n");
1360 return false;
1361 }
1362 int len = strlen(str);
1364 if (sslEnabled)
1365 {
1366 #ifdef HAVE_SSL
1367 if (libssl_is_present)
1368 {
1369 int r = SSL_write(sslStream, (unsigned char *)str, len);
1370 if (r<=0)
1371 {
1372 switch(SSL_get_error(sslStream, r))
1373 {
1374 default:
1375 fprintf(stderr, "SSL write problem");
1376 return -1;
1377 }
1378 }
1379 }
1380 #endif
1381 }
1382 else
1383 {
1384 if (send(sock, str, len, 0) < 0)
1385 //if (send(sock, &c, 1, 0) < 0)
1386 {
1387 fprintf(stderr, "write: could not send data\n");
1388 return false;
1389 }
1390 }
1391 return true;
1392 }
1394 bool TcpSocket::write(const std::string &str)
1395 {
1396 return write((char *)str.c_str());
1397 }
1399 int TcpSocket::read()
1400 {
1401 if (!isConnected())
1402 return -1;
1404 //We'll use this loop for timeouts, so that SSL and plain sockets
1405 //will behave the same way
1406 if (receiveTimeout > 0)
1407 {
1408 unsigned long tim = 0;
1409 while (true)
1410 {
1411 int avail = available();
1412 if (avail > 0)
1413 break;
1414 if (tim >= receiveTimeout)
1415 return -2;
1416 Thread::sleep(20);
1417 tim += 20;
1418 }
1419 }
1421 //check again
1422 if (!isConnected())
1423 return -1;
1425 unsigned char ch;
1426 if (sslEnabled)
1427 {
1428 #ifdef HAVE_SSL
1429 if (libssl_is_present)
1430 {
1431 if (!sslStream)
1432 return -1;
1433 int r = SSL_read(sslStream, &ch, 1);
1434 unsigned long err = SSL_get_error(sslStream, r);
1435 switch (err)
1436 {
1437 case SSL_ERROR_NONE:
1438 break;
1439 case SSL_ERROR_ZERO_RETURN:
1440 return -1;
1441 case SSL_ERROR_SYSCALL:
1442 fprintf(stderr, "SSL read problem(syscall) %s\n",
1443 ERR_error_string(ERR_get_error(), NULL));
1444 return -1;
1445 default:
1446 fprintf(stderr, "SSL read problem %s\n",
1447 ERR_error_string(ERR_get_error(), NULL));
1448 return -1;
1449 }
1450 }
1451 #endif
1452 }
1453 else
1454 {
1455 if (recv(sock, (char *)&ch, 1, 0) <= 0)
1456 {
1457 fprintf(stderr, "read: could not receive data\n");
1458 disconnect();
1459 return -1;
1460 }
1461 }
1462 return (int)ch;
1463 }
1465 std::string TcpSocket::readLine()
1466 {
1467 std::string ret;
1469 while (isConnected())
1470 {
1471 int ch = read();
1472 if (ch<0)
1473 return ret;
1474 if (ch=='\r' || ch=='\n')
1475 return ret;
1476 ret.push_back((char)ch);
1477 }
1479 return ret;
1480 }
1490 } //namespace Pedro
1491 //########################################################################
1492 //# E N D O F F I L E
1493 //########################################################################