00001
00002
00003
00004 #include "tclink.h"
00005
00006 #include <stdio.h>
00007 #include <memory.h>
00008 #include <errno.h>
00009 #include <string.h>
00010
00011 #ifdef WIN32
00012 #include <io.h>
00013 #include <winsock2.h>
00014 #else
00015 #include <strings.h>
00016 #include <sys/time.h>
00017 #include <sys/types.h>
00018 #include <sys/socket.h>
00019 #include <netinet/in.h>
00020 #include <arpa/inet.h>
00021 #include <netdb.h>
00022 #include <unistd.h>
00023 #endif
00024
00025 #include <sys/types.h>
00026 #include <stdlib.h>
00027 #include <fcntl.h>
00028 #include <signal.h>
00029
00030 #define OPENSSL_NO_KRB5 1
00031
00032 #include <openssl/crypto.h>
00033 #include <openssl/x509.h>
00034 #include <openssl/pem.h>
00035 #include <openssl/ssl.h>
00036 #include <openssl/err.h>
00037 #include <openssl/rand.h>
00038
00039 #ifdef WIN32
00040 #define strcasecmp(x,y) stricmp(x,y)
00041 #else
00042 #define closesocket(x) close(x)
00043 #endif
00044
00045 #define DEFAULT_HOST "gateway2048.trustcommerce.com"
00046 #define TIMEOUT 40
00047
00048 #define TC_BUFF_MAX 16000
00049 #define TC_LINE_MAX ((PARAM_MAX_LEN * 2) + 2)
00050
00051 char *tclink_version = TCLINK_VERSION;
00052 char *tclink_host = DEFAULT_HOST;
00053 int tclink_port = 443;
00054
00055
00056
00057
00058
00059
00060
00061 typedef struct param_data
00062 {
00063 char *name;
00064 char *value;
00065 struct param_data *next;
00066 } param;
00067
00068 typedef struct _TCLinkCon
00069 {
00070
00071 int *ip;
00072 int num_ips;
00073 int sd;
00074
00075
00076 X509 *tc_cert;
00077 SSL_METHOD *meth;
00078 SSL_CTX *ctx;
00079 SSL *ssl;
00080
00081
00082 param *send_param_list, *send_param_tail;
00083 param *recv_param_list;
00084
00085
00086 int is_error;
00087 int pass;
00088 time_t start_time;
00089 int dns;
00090
00091 } TCLinkCon;
00092
00093
00094 enum { TC_CERT_SIZE = 952 };
00095 unsigned char cert_data[TC_CERT_SIZE]={
00096 0x30,0x82,0x03,0xb4,0x30,0x82,0x02,0x9c,0x02,0x01,0x00,0x30,0x0d,0x06,0x09,0x2a,
00097 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x81,0x9f,0x31,0x0b,0x30,
00098 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,
00099 0x55,0x04,0x08,0x13,0x0a,0x43,0x61,0x6c,0x69,0x66,0x6f,0x72,0x6e,0x69,0x61,0x31,
00100 0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4c,0x6f,0x73,0x20,0x41,0x6e,
00101 0x67,0x65,0x6c,0x65,0x73,0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x0a,0x13,0x0d,
00102 0x54,0x72,0x75,0x73,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x72,0x63,0x65,0x31,0x26,0x30,
00103 0x24,0x06,0x03,0x55,0x04,0x03,0x13,0x1d,0x67,0x61,0x74,0x65,0x77,0x61,0x79,0x32,
00104 0x30,0x34,0x38,0x2e,0x74,0x72,0x75,0x73,0x74,0x63,0x6f,0x6d,0x6d,0x65,0x72,0x63,
00105 0x65,0x2e,0x63,0x6f,0x6d,0x31,0x25,0x30,0x23,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
00106 0x0d,0x01,0x09,0x01,0x16,0x16,0x69,0x6e,0x66,0x6f,0x40,0x74,0x72,0x75,0x73,0x74,
00107 0x63,0x6f,0x6d,0x6d,0x65,0x72,0x63,0x65,0x2e,0x63,0x6f,0x6d,0x30,0x1e,0x17,0x0d,
00108 0x30,0x33,0x30,0x33,0x31,0x32,0x30,0x30,0x35,0x35,0x35,0x37,0x5a,0x17,0x0d,0x30,
00109 0x33,0x30,0x34,0x31,0x31,0x30,0x30,0x35,0x35,0x35,0x37,0x5a,0x30,0x81,0x9f,0x31,
00110 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,
00111 0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x43,0x61,0x6c,0x69,0x66,0x6f,0x72,0x6e,0x69,
00112 0x61,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4c,0x6f,0x73,0x20,
00113 0x41,0x6e,0x67,0x65,0x6c,0x65,0x73,0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x0a,
00114 0x13,0x0d,0x54,0x72,0x75,0x73,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x72,0x63,0x65,0x31,
00115 0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x13,0x1d,0x67,0x61,0x74,0x65,0x77,0x61,
00116 0x79,0x32,0x30,0x34,0x38,0x2e,0x74,0x72,0x75,0x73,0x74,0x63,0x6f,0x6d,0x6d,0x65,
00117 0x72,0x63,0x65,0x2e,0x63,0x6f,0x6d,0x31,0x25,0x30,0x23,0x06,0x09,0x2a,0x86,0x48,
00118 0x86,0xf7,0x0d,0x01,0x09,0x01,0x16,0x16,0x69,0x6e,0x66,0x6f,0x40,0x74,0x72,0x75,
00119 0x73,0x74,0x63,0x6f,0x6d,0x6d,0x65,0x72,0x63,0x65,0x2e,0x63,0x6f,0x6d,0x30,0x82,
00120 0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,
00121 0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xb7,
00122 0x9e,0x49,0xa6,0xf2,0x34,0xc2,0x1c,0xbc,0x23,0xee,0x66,0x52,0x10,0x8a,0xba,0xf6,
00123 0x6c,0x31,0x78,0x58,0x4e,0x44,0xce,0x40,0x0f,0x90,0x52,0x66,0x3e,0xa7,0x34,0xef,
00124 0x31,0x24,0x13,0x73,0x20,0x33,0x4b,0xe2,0x3a,0x4d,0x4c,0xdd,0x48,0x8b,0xf4,0xb9,
00125 0xdd,0x4e,0x54,0xc8,0x79,0xd3,0x13,0xac,0x73,0x93,0x3d,0x47,0x99,0x1a,0x5c,0x4a,
00126 0xdb,0x0f,0x2d,0xf9,0xb5,0x5d,0x3e,0x91,0x15,0x4e,0x7d,0x7e,0x21,0x47,0xf2,0xb3,
00127 0xcc,0xd3,0x7c,0xc4,0x2f,0x9e,0xfe,0xec,0xd5,0x0f,0xe7,0xc8,0x7e,0x7f,0xf6,0x32,
00128 0xb8,0xac,0xff,0xac,0x8e,0xbf,0xb2,0xc1,0xaa,0xf3,0x66,0x4d,0x86,0x9a,0xd9,0xd4,
00129 0x04,0x97,0x5a,0xc3,0xa3,0x33,0xc8,0x2e,0x4f,0x07,0xca,0x6f,0x1c,0x58,0xbd,0x00,
00130 0x9e,0xe9,0xd8,0x3c,0xe2,0x87,0x80,0xb5,0x99,0x40,0x37,0x2f,0x24,0x05,0x4b,0xc2,
00131 0xf9,0xe7,0x25,0x8e,0xfc,0x76,0xb1,0x76,0xde,0xf2,0xe6,0x5f,0x06,0x44,0x31,0x59,
00132 0x1c,0xed,0x8b,0x1c,0x1c,0xb1,0x2f,0x48,0xf7,0xeb,0x78,0x73,0xa5,0x57,0xac,0xf0,
00133 0x30,0x7f,0xdd,0x09,0xa8,0x7b,0xb5,0xc5,0x30,0x2c,0xcc,0x6a,0xaf,0x6e,0x98,0x6d,
00134 0xa3,0x08,0xf8,0x94,0x0e,0x7a,0xad,0xe6,0xe5,0x27,0x01,0xc8,0x2f,0x01,0x0f,0x59,
00135 0x87,0x3f,0x5f,0x6f,0x5f,0x2c,0x27,0x3d,0xe8,0x33,0x2e,0xc1,0x69,0xbb,0xe9,0xa0,
00136 0xea,0xea,0x19,0x8b,0x9d,0x0f,0xa0,0x88,0x51,0x53,0xc1,0xf9,0x3d,0x41,0x9f,0xe2,
00137 0xa8,0x66,0x0c,0xb3,0x21,0x64,0xd3,0x4b,0x81,0x91,0xd7,0x7d,0xce,0xc7,0xb5,0x02,
00138 0x03,0x01,0x00,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
00139 0x04,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x12,0x8d,0xa7,0x9b,0x9f,0x0b,0x8e,0x26,
00140 0x8f,0xf2,0xf5,0x77,0xe2,0x71,0x85,0xd0,0x82,0x30,0x3f,0x44,0x68,0x6e,0xc6,0x4a,
00141 0xe2,0x19,0x35,0x00,0x5e,0x6b,0xb1,0xd1,0xd4,0xd4,0x62,0x92,0xbe,0xc2,0x10,0x07,
00142 0xbe,0x86,0x7b,0x8a,0xa5,0xe6,0xef,0x2b,0x6c,0x86,0x4d,0xc3,0x72,0x73,0xbf,0x68,
00143 0x2a,0xaf,0xee,0x7d,0x97,0xad,0x20,0x3c,0xef,0x5c,0x83,0x78,0x01,0xf5,0xe5,0x08,
00144 0x4f,0x33,0x52,0xaa,0xe6,0xb9,0x57,0xc9,0x26,0x48,0x59,0x20,0xe2,0x8b,0xdf,0xce,
00145 0x49,0x6f,0x2f,0x7c,0x66,0x03,0x75,0x62,0x97,0x35,0xdf,0x23,0x8d,0x81,0xde,0x85,
00146 0x9b,0x21,0x28,0x8b,0x74,0x35,0xa8,0x24,0x64,0x26,0x73,0xae,0xda,0xbd,0x81,0x2c,
00147 0x87,0x97,0xd4,0xe6,0x0b,0x7e,0xcc,0x1b,0x1f,0xa9,0x6c,0x6a,0x70,0xbd,0x7f,0x1e,
00148 0x9c,0x2d,0x7c,0xcc,0x62,0x7f,0x1a,0x93,0x12,0xaf,0xd9,0xd5,0xd8,0xe6,0x94,0xb7,
00149 0x64,0x09,0x2c,0xc2,0xc5,0x5b,0x73,0x8f,0x4c,0x58,0x1b,0xbc,0x37,0x42,0x3c,0x4c,
00150 0x37,0x7e,0x9e,0x79,0x1f,0xd1,0x0c,0xfe,0x54,0xc7,0x82,0x8f,0xde,0x87,0xf0,0xe2,
00151 0x40,0x68,0x4f,0x47,0x03,0x0d,0x23,0x46,0xf2,0x67,0xb9,0x30,0x3b,0x42,0xe3,0x77,
00152 0x40,0xa6,0xc2,0x9e,0x28,0xdf,0x28,0xda,0xfc,0xec,0xd0,0xc0,0x6a,0xd9,0x80,0x41,
00153 0x60,0x5a,0xfb,0x24,0x23,0x2e,0x4d,0x50,0xb1,0xec,0xfb,0xb3,0x97,0xe2,0x4a,0x5a,
00154 0xc7,0xda,0x12,0xbb,0x2a,0x6b,0x04,0xd6,0x90,0x91,0xe9,0xf7,0x5d,0x42,0x98,0xd7,
00155 0x81,0x8a,0xd3,0x70,0x31,0xbd,0x11,0x4a};
00156
00157
00158
00159
00160
00161
00162
00163 static int number(int min, int max)
00164 {
00165 return (rand() % (max - min + 1)) + min;
00166 }
00167
00168 static void LOG_TIME(const char *msg)
00169 {
00170 static char buf[512], buf2[64];
00171 struct timeval tv;
00172
00173 FILE *fp = fopen("/tmp/tclink.log", "a");
00174 if (!fp)
00175 return;
00176
00177 gettimeofday(&tv, 0);
00178 strftime(buf2, sizeof(buf2)-1, "%F %T", localtime(&tv.tv_sec));
00179 sprintf(buf, "[%s %03dms] %s\n", buf2, (int)tv.tv_usec / 1000, msg);
00180 fputs(buf, fp);
00181 fclose(fp);
00182 }
00183
00184
00185 #define SAFE_COPY(d, s) safe_copy((d), (s), sizeof(d));
00186 #define SAFE_APPEND(d, s) safe_append((d), (s), sizeof(d));
00187
00188 static void safe_copy(char *dst, const char *src, int size)
00189 {
00190 int len = strlen(src);
00191 if (len < size)
00192 strcpy(dst, src);
00193 else {
00194 strncpy(dst, src, size - 1);
00195 dst[size-1] = 0;
00196 }
00197 }
00198
00199 static void safe_append(char *dst, const char *src, int size)
00200 {
00201 int dlen = strlen(dst);
00202 int slen = strlen(src);
00203 int avail = size - dlen;
00204 if (avail < 1)
00205 return;
00206
00207 if (slen < avail)
00208 strcpy(dst+dlen, src);
00209 else {
00210 strncpy(dst+dlen, src, avail - 1);
00211 dst[size-1] = 0;
00212 }
00213 }
00214
00215
00216 static void AddRecvParam(TCLinkCon *c, const char *name, const char *value)
00217 {
00218 param *p;
00219
00220 if (name[0] == 0 || value[0] == 0)
00221 return;
00222
00223 p = (param *)malloc(sizeof(param));
00224 p->name = strdup(name);
00225 p->value = strdup(value);
00226 p->next = c->recv_param_list;
00227 c->recv_param_list = p;
00228 }
00229
00230
00231 static int AddRecvString(TCLinkCon *c, char *string)
00232 {
00233 char *ptr = strchr(string, '=');
00234 if (ptr == NULL)
00235 return 0;
00236
00237 *ptr = 0;
00238 AddRecvParam(c, string, ptr+1);
00239
00240 return 1;
00241 }
00242
00243
00244 static void ClearSendList(TCLinkCon *c)
00245 {
00246 param *p, *next;
00247 for (p = c->send_param_list; p; p = next)
00248 {
00249 next = p->next;
00250 free(p->name);
00251 free(p->value);
00252 free(p);
00253 }
00254
00255 c->send_param_list = c->send_param_tail = NULL;
00256 }
00257
00258
00259 static void ClearRecvList(TCLinkCon *c)
00260 {
00261 param *p, *next;
00262 for (p = c->recv_param_list; p; p = next)
00263 {
00264 next = p->next;
00265 free(p->name);
00266 free(p->value);
00267 free(p);
00268 }
00269
00270 c->recv_param_list = NULL;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279 static int BeginConnection(TCLinkCon *c, int host_ip)
00280 {
00281 struct sockaddr_in sa;
00282 int sd;
00283
00284 LOG_TIME("BeginConnection() start");
00285
00286 sd = socket(AF_INET, SOCK_STREAM, 0);
00287 if (sd < 0)
00288 return -1;
00289
00290 #ifdef WIN32
00291 u_long param = 1;
00292 ioctlsocket(sd, FIONBIO, ¶m);
00293 #else
00294 fcntl(sd, F_SETFL, O_NONBLOCK);
00295 #endif
00296
00297 memset(&sa, 0, sizeof(sa));
00298 sa.sin_family = AF_INET;
00299 sa.sin_addr.s_addr = host_ip;
00300 sa.sin_port = htons(tclink_port);
00301
00302 connect(sd, (struct sockaddr *) &sa, sizeof(sa));
00303
00304 LOG_TIME("BeginConnection() finish");
00305 return sd;
00306 }
00307
00308
00309
00310
00311
00312
00313 static int FinishConnection(TCLinkCon *c, int sd)
00314 {
00315 int ssl_connected, is_error, errcode, res;
00316 X509 *server_cert;
00317 time_t start, remaining;
00318 fd_set in, out, err;
00319 struct timeval tv;
00320
00321
00322 int val;
00323 int size = 4;
00324 LOG_TIME("FinishConnection() begin");
00325 getsockopt(sd, SOL_SOCKET, SO_ERROR, (char*)&val, &size);
00326 if (val != 0)
00327 return 0;
00328
00329 c->ssl = SSL_new(c->ctx);
00330 if (!c->ssl)
00331 return 0;
00332
00333 FD_ZERO(&in); FD_SET((unsigned)sd, &in);
00334 FD_ZERO(&out); FD_SET((unsigned)sd, &out);
00335 FD_ZERO(&err); FD_SET((unsigned)sd, &err);
00336
00337 SSL_set_fd(c->ssl, sd);
00338
00339 ssl_connected = 0;
00340 is_error = 0;
00341 start = time(0);
00342
00343 while (!ssl_connected && !is_error)
00344 {
00345 remaining = 5 - (time(0) - start);
00346 if (remaining <= 0) {
00347 is_error = 1;
00348 break;
00349 }
00350
00351 res = SSL_connect(c->ssl);
00352
00353 ssl_connected = ((res == 1) && SSL_is_init_finished(c->ssl));
00354
00355 if (!ssl_connected)
00356 {
00357 errcode = SSL_get_error(c->ssl, res);
00358 switch (errcode)
00359 {
00360 case SSL_ERROR_NONE:
00361
00362 break;
00363
00364 case SSL_ERROR_WANT_READ:
00365 case SSL_ERROR_WANT_WRITE:
00366
00367 tv.tv_sec = remaining; tv.tv_usec = 0;
00368 if (select(sd+1, &in, &out, &err, &tv) < 0)
00369 is_error = 1;
00370 break;
00371
00372 case SSL_ERROR_ZERO_RETURN:
00373 case SSL_ERROR_SSL:
00374 default:
00375 is_error = 1;
00376 }
00377 }
00378 }
00379
00380 if (is_error) {
00381 SSL_free(c->ssl);
00382 LOG_TIME("FinishConnection() finish (error)");
00383 return 0;
00384 }
00385
00386
00387 #ifdef WIN32
00388 u_long param = 0;
00389 ioctlsocket(sd, FIONBIO, ¶m);
00390 #else
00391 fcntl(sd, F_SETFL, 0);
00392 #endif
00393
00394
00395 server_cert = SSL_get_peer_certificate(c->ssl);
00396 if (!server_cert || (X509_cmp(server_cert, c->tc_cert) != 0)) {
00397 LOG_TIME("FinishConnection() finish (error, bad cert)");
00398 SSL_free(c->ssl);
00399 return 0;
00400 }
00401
00402 X509_free(server_cert);
00403
00404 LOG_TIME("FinishConnection() finish (success)");
00405 return 1;
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415 static int CheckConnection(TCLinkCon *c, int *sd, int num_sd)
00416 {
00417 fd_set wr_set, err_set;
00418 struct timeval tv;
00419 int max_sd = -1, i;
00420
00421 LOG_TIME("CheckConnection() start");
00422
00423 tv.tv_sec = 3;
00424 tv.tv_usec = 0;
00425
00426
00427 FD_ZERO(&wr_set);
00428 FD_ZERO(&err_set);
00429 for (i = 0; i < num_sd; i++)
00430 {
00431 if (sd[i] < 0) continue;
00432 FD_SET(sd[i], &wr_set);
00433 FD_SET(sd[i], &err_set);
00434 if (sd[i] > max_sd)
00435 max_sd = sd[i];
00436 }
00437
00438 LOG_TIME("select() start");
00439
00440 if (select(max_sd + 1, NULL, &wr_set, &err_set, &tv) < 1)
00441 return -1;
00442 LOG_TIME("select() end");
00443
00444 for (i = 0; i < num_sd; i++)
00445 if (sd[i] >= 0)
00446 {
00447 if (FD_ISSET(sd[i], &err_set))
00448 {
00449
00450 close(sd[i]);
00451 sd[i] = -1;
00452 }
00453 else if (FD_ISSET(sd[i], &wr_set))
00454 {
00455
00456 if (FinishConnection(c, sd[i])) {
00457
00458 c->sd = sd[i];
00459 LOG_TIME("CheckConnection() finish (success)");
00460 return i;
00461 }
00462 else {
00463
00464 close(sd[i]);
00465 sd[i] = -1;
00466 }
00467 }
00468 }
00469
00470 LOG_TIME("CheckConnection() finish (failure)");
00471
00472
00473 return -1;
00474 }
00475
00476 void do_SSL_randomize()
00477 {
00478 enum { RAND_VALS = 32 };
00479 int randbuf[RAND_VALS];
00480 char fname[512];
00481 int use_rand_file;
00482 time_t t;
00483 int i, c;
00484
00485 LOG_TIME("ssl randomize");
00486
00487
00488 if (RAND_status() != 0)
00489 return;
00490
00491 t = time(0);
00492 RAND_seed((char *)&t, sizeof(time_t));
00493
00494
00495 use_rand_file = RAND_file_name(fname, sizeof(fname)) ? 1 : 0;
00496 if (use_rand_file)
00497 RAND_load_file(fname, 4096);
00498
00499
00500 for (i = 0; i < 256 && RAND_status() == 0; i++)
00501 {
00502 for (c = 0; c < RAND_VALS; c++)
00503 randbuf[c] = rand();
00504 RAND_seed((char *)randbuf, sizeof(int) * RAND_VALS);
00505 }
00506
00507 LOG_TIME("ssl randomize finish");
00508 }
00509
00510
00511 static int Connect(TCLinkCon *c, int host_hash)
00512 {
00513 struct hostent default_he;
00514 char *addr_list[4]; int addr[3];
00515 struct hostent *he;
00516 unsigned int **gw;
00517
00518 enum { MAX_HOSTS = 32 };
00519 time_t last_connect[MAX_HOSTS];
00520 int sd[MAX_HOSTS];
00521 int num_sd = 0;
00522 int host;
00523
00524 int i, j, sort, sort_val;
00525
00526 unsigned char *cert_data_ptr = cert_data;
00527
00528 c->sd = -1;
00529 c->is_error = 0;
00530
00531 srand(time(0));
00532
00533
00534 addr[0] = inet_addr("216.34.199.222");
00535 addr[1] = inet_addr("216.120.83.124");
00536 addr[2] = inet_addr("64.14.242.58");
00537 addr_list[0] = (char *)&addr[0];
00538 addr_list[1] = (char *)&addr[1];
00539 addr_list[2] = (char *)&addr[2];
00540 addr_list[3] = 0;
00541 default_he.h_addr_list = addr_list;
00542
00543 LOG_TIME("starting hostname lookup");
00544
00545
00546 if (!c->ip)
00547 {
00548 LOG_TIME("gethostbyname begin");
00549 he = gethostbyname(tclink_host);
00550 LOG_TIME("gethostbyname end");
00551 if (he)
00552 c->dns = 1;
00553 else {
00554
00555 c->dns = 0;
00556 he = &default_he;
00557 }
00558
00559 for (c->num_ips = 0; he->h_addr_list[c->num_ips]; c->num_ips++)
00560 ;
00561
00562 LOG_TIME("sorting ips");
00563 c->ip = (int *)malloc(c->num_ips * sizeof(int));
00564 gw = (int unsigned **)he->h_addr_list;
00565
00566
00567 for (i = 0; i < c->num_ips; i++)
00568 {
00569 sort = 0; sort_val = *gw[0];
00570 for (j = 1; j < c->num_ips; j++)
00571 if (*gw[j] > sort_val)
00572 {
00573 sort = j;
00574 sort_val = *gw[j];
00575 }
00576
00577 c->ip[i] = sort_val;
00578 *gw[sort] = 0;
00579 }
00580 }
00581
00582 LOG_TIME("SSL init");
00583
00584
00585 if (!c->meth)
00586 {
00587 do_SSL_randomize();
00588 SSLeay_add_ssl_algorithms();
00589 c->meth = SSLv3_client_method();
00590 }
00591
00592 if (!c->ctx)
00593 {
00594 c->ctx = SSL_CTX_new(c->meth);
00595 if (!c->ctx) return 0;
00596 }
00597
00598 LOG_TIME("create certificate");
00599
00600
00601 if (c->tc_cert == NULL) {
00602 c->tc_cert = d2i_X509(NULL, &cert_data_ptr, TC_CERT_SIZE);
00603 if (!c->tc_cert) return 0;
00604 }
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618 c->start_time = time(0);
00619 c->pass = 1;
00620 memset(last_connect, 0, MAX_HOSTS * sizeof(time_t));
00621 host = host_hash % c->num_ips;
00622
00623 LOG_TIME("begin connect loop");
00624
00625 for ( ; time(0) < (c->start_time + TIMEOUT); c->pass++)
00626 {
00627
00628 if (c->pass > 2) host += 1;
00629 if (host >= c->num_ips) host = 0;
00630
00631
00632
00633 if (last_connect[host] == 0 ||
00634 (time(0) - last_connect[host]) >= number(TIMEOUT / 4, TIMEOUT))
00635 {
00636 if (num_sd < MAX_HOSTS)
00637 {
00638
00639 if (c->pass != 1)
00640 last_connect[host] = time(0);
00641
00642 sd[num_sd] = BeginConnection(c, c->ip[host]);
00643 if (sd[num_sd] >= 0)
00644 num_sd++;
00645 }
00646
00647
00648
00649
00650 if (num_sd > 0)
00651 if (CheckConnection(c, sd, num_sd) >= 0)
00652 {
00653
00654 for (i = 0; i < num_sd; i++)
00655 if (sd[i] >= 0 && sd[i] != c->sd)
00656 close(sd[i]);
00657
00658 return 1;
00659 }
00660 }
00661 }
00662
00663 return 0;
00664 }
00665
00666
00667 static int Send(TCLinkCon *c, const char *string)
00668 {
00669 if (SSL_write(c->ssl, string, strlen(string)) < 0)
00670 return 0;
00671
00672 return 1;
00673 }
00674
00675
00676
00677
00678
00679
00680 static int ReadLine(TCLinkCon *c, char *buffer, char *destbuf)
00681 {
00682 struct timeval tv;
00683 fd_set read;
00684 fd_set error;
00685
00686 while (1)
00687 {
00688 char *eol = strchr(buffer, '\n');
00689 if (eol != NULL)
00690 {
00691
00692 *eol++ = 0;
00693 safe_copy(destbuf, buffer, TC_LINE_MAX);
00694 memmove(buffer, eol, strlen(eol)+1);
00695 return strlen(destbuf);
00696 }
00697 else
00698 {
00699 if (c->is_error == 1)
00700 return -1;
00701
00702
00703 FD_ZERO(&read); FD_SET(c->sd, &read);
00704 FD_ZERO(&error); FD_SET(c->sd, &error);
00705 tv.tv_sec = TIMEOUT;
00706 tv.tv_usec = 0;
00707
00708 if (select(c->sd + 1, &read, NULL, &error, &tv) < 1)
00709 c->is_error = 1;
00710 else if (FD_ISSET(c->sd, &error))
00711 c->is_error = 1;
00712 else if (FD_ISSET(c->sd, &read))
00713 {
00714 int buffer_end = strlen(buffer);
00715 int size = SSL_read(c->ssl, buffer + buffer_end, TC_BUFF_MAX-1 - buffer_end);
00716 if (size < 0)
00717 c->is_error = 1;
00718 else
00719 buffer[buffer_end + size] = 0;
00720 }
00721 }
00722 }
00723 }
00724
00725
00726
00727
00728
00729 static int Close(TCLinkCon *c)
00730 {
00731 if (c->ssl) SSL_shutdown(c->ssl);
00732
00733 if (c->sd >= 0) {
00734 close(c->sd);
00735 c->sd = -1;
00736 }
00737
00738 if (c->ssl) {
00739 SSL_free(c->ssl);
00740 c->ssl = NULL;
00741 }
00742
00743 if (c->ctx) {
00744 SSL_CTX_free(c->ctx);
00745 c->ctx = NULL;
00746 }
00747
00748
00749
00750
00751 return 1;
00752 }
00753
00754
00755
00756
00757
00758 TCLinkHandle TCLinkCreate()
00759 {
00760 TCLinkCon *c = (TCLinkCon *)malloc(sizeof(TCLinkCon));
00761
00762 c->ip = NULL;
00763 c->num_ips = 0;
00764 c->sd = -1;
00765
00766 c->tc_cert = NULL;
00767 c->meth = NULL;
00768 c->ctx = NULL;
00769 c->ssl = NULL;
00770
00771 c->send_param_list = NULL;
00772 c->send_param_tail = NULL;
00773 c->recv_param_list = NULL;
00774
00775 c->is_error = 0;
00776 c->pass = 0;
00777 c->start_time = 0;
00778 c->dns = -1;
00779
00780 return (TCLinkHandle)c;
00781 }
00782
00783 void TCLinkPushParam(TCLinkHandle handle, const char *name, const char *value)
00784 {
00785 param *p;
00786 char *ch;
00787
00788 TCLinkCon *c = (TCLinkCon *)handle;
00789
00790 if (name && value)
00791 {
00792 p = (param *)malloc(sizeof(param));
00793 p->name = strdup(name);
00794 p->value = strdup(value);
00795 p->next = NULL;
00796 if (c->send_param_tail)
00797 c->send_param_tail->next = p;
00798 else
00799 c->send_param_list = p;
00800 c->send_param_tail = p;
00801
00802
00803 for (ch = p->name; *ch; ch++)
00804 if (*ch == '=' || *ch == '\n') *ch = ' ';
00805
00806
00807 for (ch = p->value; *ch; ch++)
00808 if (*ch == '\n') *ch = ' ';
00809 }
00810 }
00811
00812 void TCLinkSend(TCLinkHandle handle)
00813 {
00814 param *p, *next;
00815 char buf[TC_BUFF_MAX], destbuf[TC_LINE_MAX];
00816 char buf2[1024];
00817 int host_hash = 1;
00818 int retval = 0;
00819
00820 TCLinkCon *c = (TCLinkCon *)handle;
00821
00822 LOG_TIME("------------ Transaction Start -----------");
00823
00824 ClearRecvList(c);
00825
00826
00827 sprintf(buf, "BEGIN\nversion=%s\n", tclink_version);
00828
00829 for (p = c->send_param_list; p; p = next)
00830 {
00831 next = p->next;
00832 SAFE_COPY(buf2, p->name);
00833 SAFE_APPEND(buf2, "=");
00834 SAFE_APPEND(buf2, p->value);
00835 SAFE_APPEND(buf2, "\n");
00836 SAFE_APPEND(buf, buf2);
00837 if (!strcasecmp(p->name, "custid")) {
00838 host_hash = atoi(p->value);
00839 host_hash = (host_hash / 100) + (host_hash % 100);
00840 }
00841 free(p->name);
00842 free(p->value);
00843 free(p);
00844 }
00845
00846 c->send_param_list = c->send_param_tail = NULL;
00847
00848
00849 if (!Connect(c, host_hash))
00850 {
00851 Close(c);
00852 AddRecvParam(c, "status", "error");
00853 AddRecvParam(c, "errortype", "cantconnect");
00854 LOG_TIME("------------ Transaction End (error) -----------\n");
00855 return;
00856 }
00857
00858 LOG_TIME("connection established, sending data");
00859
00860
00861 sprintf(buf+strlen(buf), "pass=%d\ntime=%ld\n", c->pass, time(0) - c->start_time);
00862 if (c->dns != 1) SAFE_APPEND(buf, "dns=n\n");
00863 SAFE_APPEND(buf, "END\n");
00864
00865
00866 if (Send(c, buf))
00867 {
00868 LOG_TIME("send complete, waiting for response");
00869
00870 int state = 0;
00871 buf[0] = destbuf[0] = 0;
00872 c->is_error = 0;
00873 while (1)
00874 {
00875 int len = ReadLine(c, buf, destbuf);
00876 if (len == 0) continue;
00877 if (len < 0) break;
00878 if (strcasecmp(destbuf, "BEGIN") == 0)
00879 {
00880 if (state != 0)
00881 { state = -1; break; }
00882 state = 1;
00883 }
00884 else if (strcasecmp(destbuf, "END") == 0)
00885 {
00886 if (state != 1)
00887 state = -1;
00888 else
00889 state = 2;
00890 break;
00891 }
00892 else
00893 {
00894 if (state != 1 || !AddRecvString(c, destbuf))
00895 { state = -1; break; }
00896 }
00897 }
00898 if (state == 2)
00899 retval = 1;
00900 }
00901
00902 LOG_TIME("transaction send/result complete, closing connection");
00903
00904 Close(c);
00905
00906 if (!retval)
00907 {
00908 ClearRecvList(c);
00909 AddRecvParam(c, "status", "error");
00910 AddRecvParam(c, "errortype", "linkfailure");
00911 }
00912
00913 LOG_TIME("------------ Transaction End -----------\n");
00914 }
00915
00916 char *TCLinkGetResponse(TCLinkHandle handle, const char *name, char *value)
00917 {
00918 param *p;
00919 TCLinkCon *c = (TCLinkCon *)handle;
00920
00921 for (p = c->recv_param_list; p; p = p->next)
00922 if (strcasecmp(name, p->name) == 0)
00923 {
00924 safe_copy(value, p->value, PARAM_MAX_LEN);
00925 return value;
00926 }
00927
00928 return NULL;
00929 }
00930
00931 static void stuff_string(char *buf, int *len, int size, const char *add)
00932 {
00933 int newlen = strlen(add);
00934 if ((*len + newlen) >= size)
00935 newlen = size - *len - 1;
00936 if (newlen < 1) return;
00937 strncpy(buf + *len, add, newlen);
00938 *len += newlen;
00939 buf[*len] = 0;
00940 }
00941
00942 char *TCLinkGetEntireResponse(TCLinkHandle handle, char *buf, int size)
00943 {
00944 param *p;
00945 int len = 0;
00946 TCLinkCon *c = (TCLinkCon *)handle;
00947
00948 for (p = c->recv_param_list; p; p = p->next) {
00949 stuff_string(buf, &len, size, p->name);
00950 stuff_string(buf, &len, size, "=");
00951 stuff_string(buf, &len, size, p->value);
00952 stuff_string(buf, &len, size, "\n");
00953 }
00954
00955 return buf;
00956 }
00957
00958 void TCLinkDestroy(TCLinkHandle handle)
00959 {
00960 TCLinkCon *c = (TCLinkCon *)handle;
00961 if (!c) return;
00962
00963 ClearSendList(c);
00964 ClearRecvList(c);
00965 Close(c);
00966
00967 if (c->ip)
00968 free(c->ip);
00969
00970 if (c->tc_cert)
00971 X509_free(c->tc_cert);
00972
00973 free(c);
00974 }
00975
00976 char *TCLinkGetVersion(char *buf)
00977 {
00978 strcpy(buf, tclink_version);
00979 return buf;
00980 }
00981