e08bed0a6062a8ea31db59cdac65005c16d7e5f4
1 /*
2 * Support classes for the Pedro mini-XMPP client
3 *
4 * Authors:
5 * Bob Jamison
6 *
7 * Copyright (C) 2005-2006 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 */
53 namespace Pedro
54 {
60 //########################################################################
61 //########################################################################
62 //# B A S E 6 4
63 //########################################################################
64 //########################################################################
67 //#################
68 //# ENCODER
69 //#################
72 static char *base64encode =
73 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
77 /**
78 * Writes the specified byte to the output buffer
79 */
80 void Base64Encoder::append(int ch)
81 {
82 outBuf <<= 8;
83 outBuf |= (ch & 0xff);
84 bitCount += 8;
85 if (bitCount >= 24)
86 {
87 int indx = (int)((outBuf & 0x00fc0000L) >> 18);
88 int obyte = (int)base64encode[indx & 63];
89 buf.push_back(obyte);
91 indx = (int)((outBuf & 0x0003f000L) >> 12);
92 obyte = (int)base64encode[indx & 63];
93 buf.push_back(obyte);
95 indx = (int)((outBuf & 0x00000fc0L) >> 6);
96 obyte = (int)base64encode[indx & 63];
97 buf.push_back(obyte);
99 indx = (int)((outBuf & 0x0000003fL) );
100 obyte = (int)base64encode[indx & 63];
101 buf.push_back(obyte);
103 bitCount = 0;
104 outBuf = 0L;
105 }
106 }
108 /**
109 * Writes the specified string to the output buffer
110 */
111 void Base64Encoder::append(char *str)
112 {
113 while (*str)
114 append((int)*str++);
115 }
117 /**
118 * Writes the specified string to the output buffer
119 */
120 void Base64Encoder::append(unsigned char *str, int len)
121 {
122 while (len>0)
123 {
124 append((int)*str++);
125 len--;
126 }
127 }
129 /**
130 * Writes the specified string to the output buffer
131 */
132 void Base64Encoder::append(const DOMString &str)
133 {
134 append((char *)str.c_str());
135 }
137 /**
138 * Closes this output stream and releases any system resources
139 * associated with this stream.
140 */
141 DOMString Base64Encoder::finish()
142 {
143 //get any last bytes (1 or 2) out of the buffer
144 if (bitCount == 16)
145 {
146 outBuf <<= 2; //pad to make 18 bits
148 int indx = (int)((outBuf & 0x0003f000L) >> 12);
149 int obyte = (int)base64encode[indx & 63];
150 buf.push_back(obyte);
152 indx = (int)((outBuf & 0x00000fc0L) >> 6);
153 obyte = (int)base64encode[indx & 63];
154 buf.push_back(obyte);
156 indx = (int)((outBuf & 0x0000003fL) );
157 obyte = (int)base64encode[indx & 63];
158 buf.push_back(obyte);
160 buf.push_back('=');
161 }
162 else if (bitCount == 8)
163 {
164 outBuf <<= 4; //pad to make 12 bits
166 int indx = (int)((outBuf & 0x00000fc0L) >> 6);
167 int obyte = (int)base64encode[indx & 63];
168 buf.push_back(obyte);
170 indx = (int)((outBuf & 0x0000003fL) );
171 obyte = (int)base64encode[indx & 63];
172 buf.push_back(obyte);
174 buf.push_back('=');
175 buf.push_back('=');
176 }
178 DOMString ret = buf;
179 reset();
180 return ret;
181 }
184 DOMString Base64Encoder::encode(const DOMString &str)
185 {
186 Base64Encoder encoder;
187 encoder.append(str);
188 DOMString ret = encoder.finish();
189 return ret;
190 }
194 //#################
195 //# DECODER
196 //#################
198 static int base64decode[] =
199 {
200 /*00*/ -1, -1, -1, -1, -1, -1, -1, -1,
201 /*08*/ -1, -1, -1, -1, -1, -1, -1, -1,
202 /*10*/ -1, -1, -1, -1, -1, -1, -1, -1,
203 /*18*/ -1, -1, -1, -1, -1, -1, -1, -1,
204 /*20*/ -1, -1, -1, -1, -1, -1, -1, -1,
205 /*28*/ -1, -1, -1, 62, -1, -1, -1, 63,
206 /*30*/ 52, 53, 54, 55, 56, 57, 58, 59,
207 /*38*/ 60, 61, -1, -1, -1, -1, -1, -1,
208 /*40*/ -1, 0, 1, 2, 3, 4, 5, 6,
209 /*48*/ 7, 8, 9, 10, 11, 12, 13, 14,
210 /*50*/ 15, 16, 17, 18, 19, 20, 21, 22,
211 /*58*/ 23, 24, 25, -1, -1, -1, -1, -1,
212 /*60*/ -1, 26, 27, 28, 29, 30, 31, 32,
213 /*68*/ 33, 34, 35, 36, 37, 38, 39, 40,
214 /*70*/ 41, 42, 43, 44, 45, 46, 47, 48,
215 /*78*/ 49, 50, 51, -1, -1, -1, -1, -1
216 };
220 /**
221 * Appends one char to the decoder
222 */
223 void Base64Decoder::append(int ch)
224 {
225 if (isspace(ch))
226 return;
227 else if (ch == '=') //padding
228 {
229 inBytes[inCount++] = 0;
230 }
231 else
232 {
233 int byteVal = base64decode[ch & 0x7f];
234 //printf("char:%c %d\n", ch, byteVal);
235 if (byteVal < 0)
236 {
237 //Bad lookup value
238 }
239 inBytes[inCount++] = byteVal;
240 }
242 if (inCount >=4 )
243 {
244 unsigned char b0 = ((inBytes[0]<<2) & 0xfc) | ((inBytes[1]>>4) & 0x03);
245 unsigned char b1 = ((inBytes[1]<<4) & 0xf0) | ((inBytes[2]>>2) & 0x0f);
246 unsigned char b2 = ((inBytes[2]<<6) & 0xc0) | ((inBytes[3] ) & 0x3f);
247 buf.push_back(b0);
248 buf.push_back(b1);
249 buf.push_back(b2);
250 inCount = 0;
251 }
253 }
255 void Base64Decoder::append(char *str)
256 {
257 while (*str)
258 append((int)*str++);
259 }
261 void Base64Decoder::append(const DOMString &str)
262 {
263 append((char *)str.c_str());
264 }
266 std::vector<unsigned char> Base64Decoder::finish()
267 {
268 std::vector<unsigned char> ret = buf;
269 reset();
270 return ret;
271 }
273 std::vector<unsigned char> Base64Decoder::decode(const DOMString &str)
274 {
275 Base64Decoder decoder;
276 decoder.append(str);
277 std::vector<unsigned char> ret = decoder.finish();
278 return ret;
279 }
281 DOMString Base64Decoder::decodeToString(const DOMString &str)
282 {
283 Base64Decoder decoder;
284 decoder.append(str);
285 std::vector<unsigned char> ret = decoder.finish();
286 DOMString buf;
287 for (unsigned int i=0 ; i<ret.size() ; i++)
288 buf.push_back(ret[i]);
289 return buf;
290 }
298 //########################################################################
299 //########################################################################
300 //### S H A 1 H A S H I N G
301 //########################################################################
302 //########################################################################
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 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 void Sha1::init()
332 {
334 lenW = 0;
335 sizeHi = 0;
336 sizeLo = 0;
338 // Initialize H with the magic constants (see FIPS180 for constants)
339 H[0] = 0x67452301L;
340 H[1] = 0xefcdab89L;
341 H[2] = 0x98badcfeL;
342 H[3] = 0x10325476L;
343 H[4] = 0xc3d2e1f0L;
345 for (int i = 0; i < 80; i++)
346 W[i] = 0;
347 }
350 void Sha1::append(unsigned char *dataIn, int len)
351 {
352 // Read the data into W and process blocks as they get full
353 for (int i = 0; i < len; i++)
354 {
355 W[lenW / 4] <<= 8;
356 W[lenW / 4] |= (unsigned long)dataIn[i];
357 if ((++lenW) % 64 == 0)
358 {
359 hashblock();
360 lenW = 0;
361 }
362 sizeLo += 8;
363 sizeHi += (sizeLo < 8);
364 }
365 }
368 void Sha1::finish(unsigned char hashout[20])
369 {
370 unsigned char pad0x80 = 0x80;
371 unsigned char pad0x00 = 0x00;
372 unsigned char padlen[8];
374 // Pad with a binary 1 (e.g. 0x80), then zeroes, then length
375 padlen[0] = (unsigned char)((sizeHi >> 24) & 255);
376 padlen[1] = (unsigned char)((sizeHi >> 16) & 255);
377 padlen[2] = (unsigned char)((sizeHi >> 8) & 255);
378 padlen[3] = (unsigned char)((sizeHi >> 0) & 255);
379 padlen[4] = (unsigned char)((sizeLo >> 24) & 255);
380 padlen[5] = (unsigned char)((sizeLo >> 16) & 255);
381 padlen[6] = (unsigned char)((sizeLo >> 8) & 255);
382 padlen[7] = (unsigned char)((sizeLo >> 0) & 255);
384 append(&pad0x80, 1);
386 while (lenW != 56)
387 append(&pad0x00, 1);
388 append(padlen, 8);
390 // Output hash
391 for (int i = 0; i < 20; i++)
392 {
393 hashout[i] = (unsigned char)(H[i / 4] >> 24);
394 H[i / 4] <<= 8;
395 }
397 // Re-initialize the context (also zeroizes contents)
398 init();
399 }
402 #define SHA_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xffffffffL)
404 void Sha1::hashblock()
405 {
407 for (int t = 16; t <= 79; t++)
408 W[t] = SHA_ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
410 unsigned long A = H[0];
411 unsigned long B = H[1];
412 unsigned long C = H[2];
413 unsigned long D = H[3];
414 unsigned long E = H[4];
416 unsigned long TEMP;
418 for (int t = 0; t <= 19; t++)
419 {
420 TEMP = (SHA_ROTL(A,5) + (((C^D)&B)^D) +
421 E + W[t] + 0x5a827999L) & 0xffffffffL;
422 E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
423 }
424 for (int t = 20; t <= 39; t++)
425 {
426 TEMP = (SHA_ROTL(A,5) + (B^C^D) +
427 E + W[t] + 0x6ed9eba1L) & 0xffffffffL;
428 E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
429 }
430 for (int t = 40; t <= 59; t++)
431 {
432 TEMP = (SHA_ROTL(A,5) + ((B&C)|(D&(B|C))) +
433 E + W[t] + 0x8f1bbcdcL) & 0xffffffffL;
434 E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
435 }
436 for (int t = 60; t <= 79; t++)
437 {
438 TEMP = (SHA_ROTL(A,5) + (B^C^D) +
439 E + W[t] + 0xca62c1d6L) & 0xffffffffL;
440 E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
441 }
443 H[0] += A;
444 H[1] += B;
445 H[2] += C;
446 H[3] += D;
447 H[4] += E;
448 }
455 //########################################################################
456 //########################################################################
457 //### M D 5 H A S H I N G
458 //########################################################################
459 //########################################################################
465 void Md5::hash(unsigned char *dataIn, unsigned long len, unsigned char *digest)
466 {
467 Md5 md5;
468 md5.append(dataIn, len);
469 md5.finish(digest);
470 }
472 DOMString Md5::hashHex(unsigned char *dataIn, unsigned long len)
473 {
474 Md5 md5;
475 md5.append(dataIn, len);
476 DOMString ret = md5.finishHex();
477 return ret;
478 }
482 /*
483 * Note: this code is harmless on little-endian machines.
484 */
485 /*
486 static void byteReverse(unsigned char *buf, unsigned long longs)
487 {
488 do
489 {
490 unsigned long t = (unsigned long)
491 ((unsigned) buf[3] << 8 | buf[2]) << 16 |
492 ((unsigned) buf[1] << 8 | buf[0]);
493 *(unsigned long *) buf = t;
494 buf += 4;
495 } while (--longs);
496 }
497 */
499 static void md5_memcpy(void *dest, void *src, int n)
500 {
501 unsigned char *s1 = (unsigned char *)dest;
502 unsigned char *s2 = (unsigned char *)src;
503 while (n--)
504 *s1++ = *s2++;
505 }
507 static void md5_memset(void *dest, char v, int n)
508 {
509 unsigned char *s = (unsigned char *)dest;
510 while (n--)
511 *s++ = v;
512 }
514 /**
515 * Initialize MD5 polynomials and storage
516 */
517 void Md5::init()
518 {
519 buf[0] = 0x67452301;
520 buf[1] = 0xefcdab89;
521 buf[2] = 0x98badcfe;
522 buf[3] = 0x10325476;
524 bits[0] = 0;
525 bits[1] = 0;
526 }
528 /*
529 * Update context to reflect the concatenation of another buffer full
530 * of bytes.
531 */
532 void Md5::append(unsigned char *source, unsigned long len)
533 {
535 // Update bitcount
536 unsigned long t = bits[0];
537 if ((bits[0] = t + ((unsigned long) len << 3)) < t)
538 bits[1]++;// Carry from low to high
539 bits[1] += len >> 29;
541 //Bytes already in shsInfo->data
542 t = (t >> 3) & 0x3f;
545 // Handle any leading odd-sized chunks
546 if (t)
547 {
548 unsigned char *p = (unsigned char *) in + t;
549 t = 64 - t;
550 if (len < t)
551 {
552 md5_memcpy(p, source, len);
553 return;
554 }
555 md5_memcpy(p, source, t);
556 //byteReverse(in, 16);
557 transform(buf, (unsigned long *) in);
558 source += t;
559 len -= t;
560 }
562 // Process data in 64-byte chunks
563 while (len >= 64)
564 {
565 md5_memcpy(in, source, 64);
566 //byteReverse(in, 16);
567 transform(buf, (unsigned long *) in);
568 source += 64;
569 len -= 64;
570 }
572 // Handle any remaining bytes of data.
573 md5_memcpy(in, source, len);
574 }
576 /*
577 * Update context to reflect the concatenation of another string
578 */
579 void Md5::append(const DOMString &str)
580 {
581 append((unsigned char *)str.c_str(), str.size());
582 }
584 /*
585 * Update context to reflect the concatenation of a single character
586 */
587 void Md5::append(unsigned char ch)
588 {
589 append(&ch, 1);
590 }
592 /*
593 * Final wrapup - pad to 64-byte boundary with the bit pattern
594 * 1 0* (64-bit count of bits processed, MSB-first)
595 */
596 void Md5::finish(unsigned char *digest)
597 {
598 // Compute number of bytes mod 64
599 unsigned int count = (bits[0] >> 3) & 0x3F;
601 // Set the first char of padding to 0x80.
602 // This is safe since there is always at least one byte free
603 unsigned char *p = in + count;
604 *p++ = 0x80;
606 // Bytes of padding needed to make 64 bytes
607 count = 64 - 1 - count;
609 // Pad out to 56 mod 64
610 if (count < 8)
611 {
612 // Two lots of padding: Pad the first block to 64 bytes
613 md5_memset(p, 0, count);
614 //byteReverse(in, 16);
615 transform(buf, (unsigned long *) in);
617 // Now fill the next block with 56 bytes
618 md5_memset(in, 0, 56);
619 }
620 else
621 {
622 // Pad block to 56 bytes
623 md5_memset(p, 0, count - 8);
624 }
625 //byteReverse(in, 14);
627 // Append length in bits and transform
628 ((unsigned long *) in)[14] = bits[0];
629 ((unsigned long *) in)[15] = bits[1];
631 transform(buf, (unsigned long *) in);
632 //byteReverse((unsigned char *) buf, 4);
633 md5_memcpy(digest, buf, 16);
634 init(); // Security! ;-)
635 }
637 static char *md5hex = "0123456789abcdef";
639 DOMString Md5::finishHex()
640 {
641 unsigned char hashout[16];
642 finish(hashout);
643 DOMString ret;
644 for (int i=0 ; i<16 ; i++)
645 {
646 unsigned char ch = hashout[i];
647 ret.push_back(md5hex[ (ch>>4) & 15 ]);
648 ret.push_back(md5hex[ ch & 15 ]);
649 }
650 return ret;
651 }
655 //# The four core functions - F1 is optimized somewhat
657 // #define F1(x, y, z) (x & y | ~x & z)
658 #define F1(x, y, z) (z ^ (x & (y ^ z)))
659 #define F2(x, y, z) F1(z, x, y)
660 #define F3(x, y, z) (x ^ y ^ z)
661 #define F4(x, y, z) (y ^ (x | ~z))
663 // ## This is the central step in the MD5 algorithm.
664 #define MD5STEP(f, w, x, y, z, data, s) \
665 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
667 /*
668 * The core of the MD5 algorithm, this alters an existing MD5 hash to
669 * reflect the addition of 16 longwords of new data. MD5Update blocks
670 * the data and converts bytes into longwords for this routine.
671 * @parm buf points to an array of 4 unsigned longs
672 * @parm in points to an array of 16 unsigned longs
673 */
674 void Md5::transform(unsigned long *buf, unsigned long *in)
675 {
676 unsigned long a = buf[0];
677 unsigned long b = buf[1];
678 unsigned long c = buf[2];
679 unsigned long d = buf[3];
681 MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7);
682 MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
683 MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
684 MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
685 MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7);
686 MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
687 MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
688 MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
689 MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7);
690 MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
691 MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
692 MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
693 MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
694 MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
695 MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
696 MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
698 MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5);
699 MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9);
700 MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
701 MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
702 MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5);
703 MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
704 MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
705 MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
706 MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5);
707 MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
708 MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
709 MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
710 MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
711 MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9);
712 MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
713 MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
715 MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4);
716 MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
717 MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
718 MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
719 MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4);
720 MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
721 MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
722 MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
723 MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
724 MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
725 MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
726 MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
727 MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4);
728 MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
729 MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
730 MD5STEP(F3, b, c, d, a, in[ 2] + 0xc4ac5665, 23);
732 MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6);
733 MD5STEP(F4, d, a, b, c, in[ 7] + 0x432aff97, 10);
734 MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
735 MD5STEP(F4, b, c, d, a, in[ 5] + 0xfc93a039, 21);
736 MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
737 MD5STEP(F4, d, a, b, c, in[ 3] + 0x8f0ccc92, 10);
738 MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
739 MD5STEP(F4, b, c, d, a, in[ 1] + 0x85845dd1, 21);
740 MD5STEP(F4, a, b, c, d, in[ 8] + 0x6fa87e4f, 6);
741 MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
742 MD5STEP(F4, c, d, a, b, in[ 6] + 0xa3014314, 15);
743 MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
744 MD5STEP(F4, a, b, c, d, in[ 4] + 0xf7537e82, 6);
745 MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
746 MD5STEP(F4, c, d, a, b, in[ 2] + 0x2ad7d2bb, 15);
747 MD5STEP(F4, b, c, d, a, in[ 9] + 0xeb86d391, 21);
749 buf[0] += a;
750 buf[1] += b;
751 buf[2] += c;
752 buf[3] += d;
753 }
764 //########################################################################
765 //########################################################################
766 //### T H R E A D
767 //########################################################################
768 //########################################################################
774 #ifdef __WIN32__
777 static DWORD WINAPI WinThreadFunction(LPVOID context)
778 {
779 Thread *thread = (Thread *)context;
780 thread->execute();
781 return 0;
782 }
785 void Thread::start()
786 {
787 DWORD dwThreadId;
788 HANDLE hThread = CreateThread(NULL, 0, WinThreadFunction,
789 (LPVOID)this, 0, &dwThreadId);
790 //Make sure the thread is started before 'this' is deallocated
791 while (!started)
792 sleep(10);
793 CloseHandle(hThread);
794 }
796 void Thread::sleep(unsigned long millis)
797 {
798 Sleep(millis);
799 }
801 #else /* UNIX */
804 void *PthreadThreadFunction(void *context)
805 {
806 Thread *thread = (Thread *)context;
807 thread->execute();
808 return NULL;
809 }
812 void Thread::start()
813 {
814 pthread_t thread;
816 int ret = pthread_create(&thread, NULL,
817 PthreadThreadFunction, (void *)this);
818 if (ret != 0)
819 printf("Thread::start: thread creation failed: %s\n", strerror(ret));
821 //Make sure the thread is started before 'this' is deallocated
822 while (!started)
823 sleep(10);
825 }
827 void Thread::sleep(unsigned long millis)
828 {
829 timespec requested;
830 requested.tv_sec = millis / 1000;
831 requested.tv_nsec = (millis % 1000 ) * 1000000L;
832 nanosleep(&requested, NULL);
833 }
835 #endif
844 //########################################################################
845 //########################################################################
846 //### S O C K E T
847 //########################################################################
848 //########################################################################
854 //#########################################################################
855 //# U T I L I T Y
856 //#########################################################################
858 static void mybzero(void *s, size_t n)
859 {
860 unsigned char *p = (unsigned char *)s;
861 while (n > 0)
862 {
863 *p++ = (unsigned char)0;
864 n--;
865 }
866 }
868 static void mybcopy(void *src, void *dest, size_t n)
869 {
870 unsigned char *p = (unsigned char *)dest;
871 unsigned char *q = (unsigned char *)src;
872 while (n > 0)
873 {
874 *p++ = *q++;
875 n--;
876 }
877 }
881 //#########################################################################
882 //# T C P C O N N E C T I O N
883 //#########################################################################
885 TcpSocket::TcpSocket()
886 {
887 init();
888 }
891 TcpSocket::TcpSocket(const std::string &hostnameArg, int port)
892 {
893 init();
894 hostname = hostnameArg;
895 portno = port;
896 }
899 #ifdef HAVE_SSL
901 static void cryptoLockCallback(int mode, int type, const char *file, int line)
902 {
903 //printf("########### LOCK\n");
904 static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
905 const char *errstr = NULL;
907 int rw = mode & (CRYPTO_READ|CRYPTO_WRITE);
908 if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE)))
909 {
910 errstr = "invalid mode";
911 goto err;
912 }
914 if (type < 0 || type >= CRYPTO_NUM_LOCKS)
915 {
916 errstr = "type out of bounds";
917 goto err;
918 }
920 if (mode & CRYPTO_LOCK)
921 {
922 if (modes[type])
923 {
924 errstr = "already locked";
925 /* must not happen in a single-threaded program
926 * (would deadlock)
927 */
928 goto err;
929 }
931 modes[type] = rw;
932 }
933 else if (mode & CRYPTO_UNLOCK)
934 {
935 if (!modes[type])
936 {
937 errstr = "not locked";
938 goto err;
939 }
941 if (modes[type] != rw)
942 {
943 errstr = (rw == CRYPTO_READ) ?
944 "CRYPTO_r_unlock on write lock" :
945 "CRYPTO_w_unlock on read lock";
946 }
948 modes[type] = 0;
949 }
950 else
951 {
952 errstr = "invalid mode";
953 goto err;
954 }
956 err:
957 if (errstr)
958 {
959 /* we cannot use bio_err here */
960 fprintf(stderr, "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n",
961 errstr, mode, type, file, line);
962 }
963 }
965 static unsigned long cryptoIdCallback()
966 {
967 #ifdef __WIN32__
968 unsigned long ret = (unsigned long) GetCurrentThreadId();
969 #else
970 unsigned long ret = (unsigned long) pthread_self();
971 #endif
972 return ret;
973 }
975 #endif
978 TcpSocket::TcpSocket(const TcpSocket &other)
979 {
980 init();
981 sock = other.sock;
982 hostname = other.hostname;
983 portno = other.portno;
984 }
986 static bool tcp_socket_inited = false;
988 void TcpSocket::init()
989 {
990 if (!tcp_socket_inited)
991 {
992 #ifdef __WIN32__
993 WORD wVersionRequested = MAKEWORD( 2, 2 );
994 WSADATA wsaData;
995 WSAStartup( wVersionRequested, &wsaData );
996 #endif
997 #ifdef HAVE_SSL
998 sslStream = NULL;
999 sslContext = NULL;
1000 CRYPTO_set_locking_callback(cryptoLockCallback);
1001 CRYPTO_set_id_callback(cryptoIdCallback);
1002 SSL_library_init();
1003 SSL_load_error_strings();
1004 #endif
1005 tcp_socket_inited = true;
1006 }
1007 sock = -1;
1008 connected = false;
1009 hostname = "";
1010 portno = -1;
1011 sslEnabled = false;
1012 receiveTimeout = 0;
1013 }
1015 TcpSocket::~TcpSocket()
1016 {
1017 disconnect();
1018 }
1020 bool TcpSocket::isConnected()
1021 {
1022 if (!connected || sock < 0)
1023 return false;
1024 return true;
1025 }
1027 bool TcpSocket::getHaveSSL()
1028 {
1029 #ifdef HAVE_SSL
1030 return true;
1031 #else
1032 return false;
1033 #endif
1034 }
1036 void TcpSocket::enableSSL(bool val)
1037 {
1038 sslEnabled = val;
1039 }
1041 bool TcpSocket::getEnableSSL()
1042 {
1043 return sslEnabled;
1044 }
1048 bool TcpSocket::connect(const std::string &hostnameArg, int portnoArg)
1049 {
1050 hostname = hostnameArg;
1051 portno = portnoArg;
1052 return connect();
1053 }
1057 #ifdef HAVE_SSL
1058 /*
1059 static int password_cb(char *buf, int bufLen, int rwflag, void *userdata)
1060 {
1061 char *password = "password";
1062 if (bufLen < (int)(strlen(password)+1))
1063 return 0;
1065 strcpy(buf,password);
1066 int ret = strlen(password);
1067 return ret;
1068 }
1070 static void infoCallback(const SSL *ssl, int where, int ret)
1071 {
1072 switch (where)
1073 {
1074 case SSL_CB_ALERT:
1075 {
1076 printf("## %d SSL ALERT: %s\n", where, SSL_alert_desc_string_long(ret));
1077 break;
1078 }
1079 default:
1080 {
1081 printf("## %d SSL: %s\n", where, SSL_state_string_long(ssl));
1082 break;
1083 }
1084 }
1085 }
1086 */
1087 #endif
1090 bool TcpSocket::startTls()
1091 {
1092 #ifndef HAVE_SSL
1093 fprintf(stderr,
1094 "SSL starttls() error: client not compiled with SSL enabled\n");
1095 return false;
1096 #else /*HAVE_SSL*/
1098 sslStream = NULL;
1099 sslContext = NULL;
1101 //SSL_METHOD *meth = SSLv23_method();
1102 //SSL_METHOD *meth = SSLv3_client_method();
1103 SSL_METHOD *meth = TLSv1_client_method();
1104 sslContext = SSL_CTX_new(meth);
1105 //SSL_CTX_set_info_callback(sslContext, infoCallback);
1107 /**
1108 * For now, let's accept all connections. Ignore this
1109 * block of code
1110 *
1111 char *keyFile = "client.pem";
1112 char *caList = "root.pem";
1113 //# Load our keys and certificates
1114 if (!(SSL_CTX_use_certificate_chain_file(sslContext, keyFile)))
1115 {
1116 fprintf(stderr, "Can't read certificate file\n");
1117 disconnect();
1118 return false;
1119 }
1121 SSL_CTX_set_default_passwd_cb(sslContext, password_cb);
1123 if (!(SSL_CTX_use_PrivateKey_file(sslContext, keyFile, SSL_FILETYPE_PEM)))
1124 {
1125 fprintf(stderr, "Can't read key file\n");
1126 disconnect();
1127 return false;
1128 }
1130 //## Load the CAs we trust
1131 if (!(SSL_CTX_load_verify_locations(sslContext, caList, 0)))
1132 {
1133 fprintf(stderr, "Can't read CA list\n");
1134 disconnect();
1135 return false;
1136 }
1137 */
1139 /* Connect the SSL socket */
1140 sslStream = SSL_new(sslContext);
1141 SSL_set_fd(sslStream, sock);
1143 int ret = SSL_connect(sslStream);
1144 if (ret == 0)
1145 {
1146 fprintf(stderr, "SSL connection not successful\n");
1147 disconnect();
1148 return false;
1149 }
1150 else if (ret < 0)
1151 {
1152 int err = SSL_get_error(sslStream, ret);
1153 fprintf(stderr, "SSL connect error %d\n", err);
1154 disconnect();
1155 return false;
1156 }
1158 sslEnabled = true;
1159 return true;
1160 #endif /* HAVE_SSL */
1161 }
1164 bool TcpSocket::connect()
1165 {
1166 if (hostname.size()<1)
1167 {
1168 fprintf(stderr, "open: null hostname\n");
1169 return false;
1170 }
1172 if (portno<1)
1173 {
1174 fprintf(stderr, "open: bad port number\n");
1175 return false;
1176 }
1178 sock = socket(PF_INET, SOCK_STREAM, 0);
1179 if (sock < 0)
1180 {
1181 fprintf(stderr, "open: error creating socket\n");
1182 return false;
1183 }
1185 char *c_hostname = (char *)hostname.c_str();
1186 struct hostent *server = gethostbyname(c_hostname);
1187 if (!server)
1188 {
1189 fprintf(stderr, "open: could not locate host '%s'\n", c_hostname);
1190 return false;
1191 }
1193 struct sockaddr_in serv_addr;
1194 mybzero((char *) &serv_addr, sizeof(serv_addr));
1195 serv_addr.sin_family = AF_INET;
1196 mybcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr,
1197 server->h_length);
1198 serv_addr.sin_port = htons(portno);
1200 int ret = ::connect(sock, (const sockaddr *)&serv_addr, sizeof(serv_addr));
1201 if (ret < 0)
1202 {
1203 fprintf(stderr, "open: could not connect to host '%s'\n", c_hostname);
1204 return false;
1205 }
1207 if (sslEnabled)
1208 {
1209 if (!startTls())
1210 return false;
1211 }
1212 connected = true;
1213 return true;
1214 }
1216 bool TcpSocket::disconnect()
1217 {
1218 bool ret = true;
1219 connected = false;
1220 #ifdef HAVE_SSL
1221 if (sslEnabled)
1222 {
1223 if (sslStream)
1224 {
1225 int r = SSL_shutdown(sslStream);
1226 switch(r)
1227 {
1228 case 1:
1229 break; /* Success */
1230 case 0:
1231 case -1:
1232 default:
1233 //printf("Shutdown failed");
1234 ret = false;
1235 }
1236 SSL_free(sslStream);
1237 }
1238 if (sslContext)
1239 SSL_CTX_free(sslContext);
1240 }
1241 sslStream = NULL;
1242 sslContext = NULL;
1243 #endif /*HAVE_SSL*/
1245 #ifdef __WIN32__
1246 closesocket(sock);
1247 #else
1248 ::close(sock);
1249 #endif
1250 sock = -1;
1251 sslEnabled = false;
1253 return ret;
1254 }
1258 bool TcpSocket::setReceiveTimeout(unsigned long millis)
1259 {
1260 receiveTimeout = millis;
1261 return true;
1262 }
1264 /**
1265 * For normal sockets, return the number of bytes waiting to be received.
1266 * For SSL, just return >0 when something is ready to be read.
1267 */
1268 long TcpSocket::available()
1269 {
1270 if (!isConnected())
1271 return -1;
1273 long count = 0;
1274 #ifdef __WIN32__
1275 if (ioctlsocket(sock, FIONREAD, (unsigned long *)&count) != 0)
1276 return -1;
1277 #else
1278 if (ioctl(sock, FIONREAD, &count) != 0)
1279 return -1;
1280 #endif
1281 if (count<=0 && sslEnabled)
1282 {
1283 #ifdef HAVE_SSL
1284 return SSL_pending(sslStream);
1285 #endif
1286 }
1287 return count;
1288 }
1292 bool TcpSocket::write(int ch)
1293 {
1294 if (!isConnected())
1295 {
1296 fprintf(stderr, "write: socket closed\n");
1297 return false;
1298 }
1299 unsigned char c = (unsigned char)ch;
1301 if (sslEnabled)
1302 {
1303 #ifdef HAVE_SSL
1304 int r = SSL_write(sslStream, &c, 1);
1305 if (r<=0)
1306 {
1307 switch(SSL_get_error(sslStream, r))
1308 {
1309 default:
1310 fprintf(stderr, "SSL write problem");
1311 return -1;
1312 }
1313 }
1314 #endif
1315 }
1316 else
1317 {
1318 if (send(sock, (const char *)&c, 1, 0) < 0)
1319 //if (send(sock, &c, 1, 0) < 0)
1320 {
1321 fprintf(stderr, "write: could not send data\n");
1322 return false;
1323 }
1324 }
1325 return true;
1326 }
1328 bool TcpSocket::write(char *str)
1329 {
1330 if (!isConnected())
1331 {
1332 fprintf(stderr, "write(str): socket closed\n");
1333 return false;
1334 }
1335 int len = strlen(str);
1337 if (sslEnabled)
1338 {
1339 #ifdef HAVE_SSL
1340 int r = SSL_write(sslStream, (unsigned char *)str, len);
1341 if (r<=0)
1342 {
1343 switch(SSL_get_error(sslStream, r))
1344 {
1345 default:
1346 fprintf(stderr, "SSL write problem");
1347 return -1;
1348 }
1349 }
1350 #endif
1351 }
1352 else
1353 {
1354 if (send(sock, str, len, 0) < 0)
1355 //if (send(sock, &c, 1, 0) < 0)
1356 {
1357 fprintf(stderr, "write: could not send data\n");
1358 return false;
1359 }
1360 }
1361 return true;
1362 }
1364 bool TcpSocket::write(const std::string &str)
1365 {
1366 return write((char *)str.c_str());
1367 }
1369 int TcpSocket::read()
1370 {
1371 if (!isConnected())
1372 return -1;
1374 //We'll use this loop for timeouts, so that SSL and plain sockets
1375 //will behave the same way
1376 if (receiveTimeout > 0)
1377 {
1378 unsigned long tim = 0;
1379 while (true)
1380 {
1381 int avail = available();
1382 if (avail > 0)
1383 break;
1384 if (tim >= receiveTimeout)
1385 return -2;
1386 Thread::sleep(20);
1387 tim += 20;
1388 }
1389 }
1391 //check again
1392 if (!isConnected())
1393 return -1;
1395 unsigned char ch;
1396 if (sslEnabled)
1397 {
1398 #ifdef HAVE_SSL
1399 if (!sslStream)
1400 return -1;
1401 int r = SSL_read(sslStream, &ch, 1);
1402 unsigned long err = SSL_get_error(sslStream, r);
1403 switch (err)
1404 {
1405 case SSL_ERROR_NONE:
1406 break;
1407 case SSL_ERROR_ZERO_RETURN:
1408 return -1;
1409 case SSL_ERROR_SYSCALL:
1410 fprintf(stderr, "SSL read problem(syscall) %s\n",
1411 ERR_error_string(ERR_get_error(), NULL));
1412 return -1;
1413 default:
1414 fprintf(stderr, "SSL read problem %s\n",
1415 ERR_error_string(ERR_get_error(), NULL));
1416 return -1;
1417 }
1418 #endif
1419 }
1420 else
1421 {
1422 if (recv(sock, (char *)&ch, 1, 0) <= 0)
1423 {
1424 fprintf(stderr, "read: could not receive data\n");
1425 disconnect();
1426 return -1;
1427 }
1428 }
1429 return (int)ch;
1430 }
1432 std::string TcpSocket::readLine()
1433 {
1434 std::string ret;
1436 while (isConnected())
1437 {
1438 int ch = read();
1439 if (ch<0)
1440 return ret;
1441 if (ch=='\r' || ch=='\n')
1442 return ret;
1443 ret.push_back((char)ch);
1444 }
1446 return ret;
1447 }
1457 } //namespace Pedro
1458 //########################################################################
1459 //# E N D O F F I L E
1460 //########################################################################