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
00169 #define SAFE_COPY(d, s) safe_copy((d), (s), sizeof(d));
00170 #define SAFE_APPEND(d, s) safe_append((d), (s), sizeof(d));
00171
00172 void safe_copy(char *dst, const char *src, int size)
00173 {
00174 int len = strlen(src);
00175 if (len < size)
00176 strcpy(dst, src);
00177 else {
00178 strncpy(dst, src, size - 1);
00179 dst[size-1] = 0;
00180 }
00181 }
00182
00183 void safe_append(char *dst, const char *src, int size)
00184 {
00185 int dlen = strlen(dst);
00186 int slen = strlen(src);
00187 int avail = size - dlen;
00188 if (avail < 1)
00189 return;
00190
00191 if (slen < avail)
00192 strcpy(dst+dlen, src);
00193 else {
00194 strncpy(dst+dlen, src, avail - 1);
00195 dst[size-1] = 0;
00196 }
00197 }
00198
00199
00200 static void AddRecvParam(TCLinkCon *c, const char *name, const char *value)
00201 {
00202 param *p;
00203
00204 if (name[0] == 0 || value[0] == 0)
00205 return;
00206
00207 p = (param *)malloc(sizeof(param));
00208 p->name = strdup(name);
00209 p->value = strdup(value);
00210 p->next = c->recv_param_list;
00211 c->recv_param_list = p;
00212 }
00213
00214
00215 static int AddRecvString(TCLinkCon *c, char *string)
00216 {
00217 char *ptr = strchr(string, '=');
00218 if (ptr == NULL)
00219 return 0;
00220
00221 *ptr = 0;
00222 AddRecvParam(c, string, ptr+1);
00223
00224 return 1;
00225 }
00226
00227
00228 static void ClearSendList(TCLinkCon *c)
00229 {
00230 param *p, *next;
00231 for (p = c->send_param_list; p; p = next)
00232 {
00233 next = p->next;
00234 free(p->name);
00235 free(p->value);
00236 free(p);
00237 }
00238
00239 c->send_param_list = c->send_param_tail = NULL;
00240 }
00241
00242
00243 static void ClearRecvList(TCLinkCon *c)
00244 {
00245 param *p, *next;
00246 for (p = c->recv_param_list; p; p = next)
00247 {
00248 next = p->next;
00249 free(p->name);
00250 free(p->value);
00251 free(p);
00252 }
00253
00254 c->recv_param_list = NULL;
00255 }
00256
00257
00258
00259
00260
00261
00262
00263 static int BeginConnection(TCLinkCon *c, int host_ip)
00264 {
00265 struct sockaddr_in sa;
00266 int sd;
00267
00268 sd = socket(AF_INET, SOCK_STREAM, 0);
00269 if (sd < 0)
00270 return -1;
00271
00272 #ifdef WIN32
00273 u_long param = 1;
00274 ioctlsocket(sd, FIONBIO, ¶m);
00275 #else
00276 fcntl(sd, F_SETFL, O_NONBLOCK);
00277 #endif
00278
00279 memset(&sa, 0, sizeof(sa));
00280 sa.sin_family = AF_INET;
00281 sa.sin_addr.s_addr = host_ip;
00282 sa.sin_port = htons(tclink_port);
00283
00284 connect(sd, (struct sockaddr *) &sa, sizeof(sa));
00285
00286 return sd;
00287 }
00288
00289
00290
00291
00292
00293
00294 static int FinishConnection(TCLinkCon *c, int sd)
00295 {
00296 int ssl_connected, is_error, errcode, res;
00297 X509 *server_cert;
00298 time_t start, remaining;
00299 fd_set in, out, err;
00300 struct timeval tv;
00301
00302
00303 int val;
00304 int size = 4;
00305 getsockopt(sd, SOL_SOCKET, SO_ERROR, (char*)&val, &size);
00306 if (val != 0)
00307 return 0;
00308
00309 c->ssl = SSL_new(c->ctx);
00310 if (!c->ssl)
00311 return 0;
00312
00313 FD_ZERO(&in); FD_SET((unsigned)sd, &in);
00314 FD_ZERO(&out); FD_SET((unsigned)sd, &out);
00315 FD_ZERO(&err); FD_SET((unsigned)sd, &err);
00316
00317 SSL_set_fd(c->ssl, sd);
00318
00319 ssl_connected = 0;
00320 is_error = 0;
00321 start = time(0);
00322
00323 while (!ssl_connected && !is_error)
00324 {
00325 remaining = 5 - (time(0) - start);
00326 if (remaining <= 0) {
00327 is_error = 1;
00328 break;
00329 }
00330
00331 res = SSL_connect(c->ssl);
00332
00333 ssl_connected = ((res == 1) && SSL_is_init_finished(c->ssl));
00334
00335 if (!ssl_connected)
00336 {
00337 errcode = SSL_get_error(c->ssl, res);
00338 switch (errcode)
00339 {
00340 case SSL_ERROR_NONE:
00341
00342 break;
00343
00344 case SSL_ERROR_WANT_READ:
00345 case SSL_ERROR_WANT_WRITE:
00346
00347 tv.tv_sec = remaining; tv.tv_usec = 0;
00348 if (select(sd+1, &in, &out, &err, &tv) < 0)
00349 is_error = 1;
00350 break;
00351
00352 case SSL_ERROR_ZERO_RETURN:
00353 case SSL_ERROR_SSL:
00354 default:
00355 is_error = 1;
00356 }
00357 }
00358 }
00359
00360 if (is_error) {
00361 SSL_free(c->ssl);
00362 return 0;
00363 }
00364
00365
00366 #ifdef WIN32
00367 u_long param = 0;
00368 ioctlsocket(sd, FIONBIO, ¶m);
00369 #else
00370 fcntl(sd, F_SETFL, 0);
00371 #endif
00372
00373
00374 server_cert = SSL_get_peer_certificate(c->ssl);
00375 if (!server_cert || (X509_cmp(server_cert, c->tc_cert) != 0)) {
00376 SSL_free(c->ssl);
00377 return 0;
00378 }
00379
00380 X509_free(server_cert);
00381
00382 return 1;
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392 static int CheckConnection(TCLinkCon *c, int *sd, int num_sd)
00393 {
00394 fd_set wr_set, err_set;
00395 struct timeval tv;
00396 int max_sd = -1, i;
00397
00398 tv.tv_sec = 3;
00399 tv.tv_usec = 0;
00400
00401
00402 FD_ZERO(&wr_set);
00403 FD_ZERO(&err_set);
00404 for (i = 0; i < num_sd; i++)
00405 {
00406 if (sd[i] < 0) continue;
00407 FD_SET(sd[i], &wr_set);
00408 FD_SET(sd[i], &err_set);
00409 if (sd[i] > max_sd)
00410 max_sd = sd[i];
00411 }
00412
00413
00414 if (select(max_sd + 1, NULL, &wr_set, &err_set, &tv) < 1)
00415 return -1;
00416
00417 for (i = 0; i < num_sd; i++)
00418 if (sd[i] >= 0)
00419 {
00420 if (FD_ISSET(sd[i], &err_set))
00421 {
00422
00423 close(sd[i]);
00424 sd[i] = -1;
00425 }
00426 else if (FD_ISSET(sd[i], &wr_set))
00427 {
00428
00429 if (FinishConnection(c, sd[i])) {
00430
00431 c->sd = sd[i];
00432 return i;
00433 }
00434 else {
00435
00436 close(sd[i]);
00437 sd[i] = -1;
00438 }
00439 }
00440 }
00441
00442
00443 return -1;
00444 }
00445
00446 void do_SSL_randomize()
00447 {
00448 enum { RAND_VALS = 32 };
00449 int randbuf[RAND_VALS];
00450 char fname[512];
00451 int use_rand_file;
00452 time_t t;
00453 int i, c;
00454
00455
00456 if (RAND_status() != 0)
00457 return;
00458
00459 t = time(0);
00460 RAND_seed((char *)&t, sizeof(time_t));
00461
00462
00463 use_rand_file = RAND_file_name(fname, sizeof(fname)) ? 1 : 0;
00464 if (use_rand_file)
00465 RAND_load_file(fname, 4096);
00466
00467
00468 for (i = 0; i < 256 && RAND_status() == 0; i++)
00469 {
00470 for (c = 0; c < RAND_VALS; c++)
00471 randbuf[c] = rand();
00472 RAND_seed((char *)randbuf, sizeof(int) * RAND_VALS);
00473 }
00474 }
00475
00476
00477 static int Connect(TCLinkCon *c, int host_hash)
00478 {
00479 struct hostent default_he;
00480 char *addr_list[4]; int addr[3];
00481 struct hostent *he;
00482 unsigned int **gw;
00483
00484 enum { MAX_HOSTS = 32 };
00485 time_t last_connect[MAX_HOSTS];
00486 int sd[MAX_HOSTS];
00487 int num_sd = 0;
00488 int host;
00489
00490 int i, j, sort, sort_val;
00491
00492 unsigned char *cert_data_ptr = cert_data;
00493
00494 c->sd = -1;
00495 c->is_error = 0;
00496
00497 srand(time(0));
00498
00499
00500 addr[0] = inet_addr("216.34.199.222");
00501 addr[1] = inet_addr("216.120.83.124");
00502 addr[2] = inet_addr("64.14.242.58");
00503 addr_list[0] = (char *)&addr[0];
00504 addr_list[1] = (char *)&addr[1];
00505 addr_list[2] = (char *)&addr[2];
00506 addr_list[3] = 0;
00507 default_he.h_addr_list = addr_list;
00508
00509
00510 if (!c->ip)
00511 {
00512 he = gethostbyname(tclink_host);
00513 if (he)
00514 c->dns = 1;
00515 else {
00516
00517 c->dns = 0;
00518 he = &default_he;
00519 }
00520
00521 for (c->num_ips = 0; he->h_addr_list[c->num_ips]; c->num_ips++)
00522 ;
00523
00524 c->ip = (int *)malloc(c->num_ips * sizeof(int));
00525 gw = (int unsigned **)he->h_addr_list;
00526
00527
00528 for (i = 0; i < c->num_ips; i++)
00529 {
00530 sort = 0; sort_val = *gw[0];
00531 for (j = 1; j < c->num_ips; j++)
00532 if (*gw[j] > sort_val)
00533 {
00534 sort = j;
00535 sort_val = *gw[j];
00536 }
00537
00538 c->ip[i] = sort_val;
00539 *gw[sort] = 0;
00540 }
00541 }
00542
00543
00544 if (!c->meth)
00545 {
00546 do_SSL_randomize();
00547 SSLeay_add_ssl_algorithms();
00548 c->meth = SSLv3_client_method();
00549 }
00550
00551 if (!c->ctx)
00552 {
00553 c->ctx = SSL_CTX_new(c->meth);
00554 if (!c->ctx) return 0;
00555 }
00556
00557
00558 if (c->tc_cert == NULL) {
00559 c->tc_cert = d2i_X509(NULL, &cert_data_ptr, TC_CERT_SIZE);
00560 if (!c->tc_cert) return 0;
00561 }
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 c->start_time = time(0);
00576 c->pass = 1;
00577 memset(last_connect, 0, MAX_HOSTS * sizeof(time_t));
00578 host = host_hash % c->num_ips;
00579
00580 for ( ; time(0) < (c->start_time + TIMEOUT); c->pass++)
00581 {
00582
00583 if (c->pass > 2) host += 1;
00584 if (host >= c->num_ips) host = 0;
00585
00586
00587
00588 if (last_connect[host] == 0 ||
00589 (time(0) - last_connect[host]) >= number(TIMEOUT / 4, TIMEOUT))
00590 {
00591 if (num_sd < MAX_HOSTS)
00592 {
00593
00594 if (c->pass != 1)
00595 last_connect[host] = time(0);
00596
00597 sd[num_sd] = BeginConnection(c, c->ip[host]);
00598 if (sd[num_sd] >= 0)
00599 num_sd++;
00600 }
00601
00602
00603
00604
00605 if (num_sd > 0)
00606 if (CheckConnection(c, sd, num_sd) >= 0)
00607 {
00608
00609 for (i = 0; i < num_sd; i++)
00610 if (sd[i] >= 0 && sd[i] != c->sd)
00611 close(sd[i]);
00612
00613 return 1;
00614 }
00615 }
00616 }
00617
00618 return 0;
00619 }
00620
00621
00622 static int Send(TCLinkCon *c, const char *string)
00623 {
00624 if (SSL_write(c->ssl, string, strlen(string)) < 0)
00625 return 0;
00626
00627 return 1;
00628 }
00629
00630
00631
00632
00633
00634
00635 static int ReadLine(TCLinkCon *c, char *buffer, char *destbuf)
00636 {
00637 struct timeval tv;
00638 fd_set read;
00639 fd_set error;
00640
00641 while (1)
00642 {
00643 char *eol = strchr(buffer, '\n');
00644 if (eol != NULL)
00645 {
00646
00647 *eol++ = 0;
00648 safe_copy(destbuf, buffer, TC_LINE_MAX);
00649 memmove(buffer, eol, strlen(eol)+1);
00650 return strlen(destbuf);
00651 }
00652 else
00653 {
00654 if (c->is_error == 1)
00655 return -1;
00656
00657
00658 FD_ZERO(&read); FD_SET(c->sd, &read);
00659 FD_ZERO(&error); FD_SET(c->sd, &error);
00660 tv.tv_sec = TIMEOUT;
00661 tv.tv_usec = 0;
00662
00663 if (select(c->sd + 1, &read, NULL, &error, &tv) < 1)
00664 c->is_error = 1;
00665 else if (FD_ISSET(c->sd, &error))
00666 c->is_error = 1;
00667 else if (FD_ISSET(c->sd, &read))
00668 {
00669 int buffer_end = strlen(buffer);
00670 int size = SSL_read(c->ssl, buffer + buffer_end, TC_BUFF_MAX-1 - buffer_end);
00671 if (size < 0)
00672 c->is_error = 1;
00673 else
00674 buffer[buffer_end + size] = 0;
00675 }
00676 }
00677 }
00678 }
00679
00680
00681
00682
00683
00684 static int Close(TCLinkCon *c)
00685 {
00686 if (c->ssl) SSL_shutdown(c->ssl);
00687
00688 if (c->sd >= 0) {
00689 close(c->sd);
00690 c->sd = -1;
00691 }
00692
00693 if (c->ssl) {
00694 SSL_free(c->ssl);
00695 c->ssl = NULL;
00696 }
00697
00698 if (c->ctx) {
00699 SSL_CTX_free(c->ctx);
00700 c->ctx = NULL;
00701 }
00702
00703
00704
00705
00706 return 1;
00707 }
00708
00709
00710
00711
00712
00713 TCLinkHandle TCLinkCreate()
00714 {
00715 TCLinkCon *c = (TCLinkCon *)malloc(sizeof(TCLinkCon));
00716
00717 c->ip = NULL;
00718 c->num_ips = 0;
00719 c->sd = -1;
00720
00721 c->tc_cert = NULL;
00722 c->meth = NULL;
00723 c->ctx = NULL;
00724 c->ssl = NULL;
00725
00726 c->send_param_list = NULL;
00727 c->send_param_tail = NULL;
00728 c->recv_param_list = NULL;
00729
00730 c->is_error = 0;
00731 c->pass = 0;
00732 c->start_time = 0;
00733 c->dns = -1;
00734
00735 return (TCLinkHandle)c;
00736 }
00737
00738 void TCLinkPushParam(TCLinkHandle handle, const char *name, const char *value)
00739 {
00740 param *p;
00741 char *ch;
00742
00743 TCLinkCon *c = (TCLinkCon *)handle;
00744
00745 if (name && value)
00746 {
00747 p = (param *)malloc(sizeof(param));
00748 p->name = strdup(name);
00749 p->value = strdup(value);
00750 p->next = NULL;
00751 if (c->send_param_tail)
00752 c->send_param_tail->next = p;
00753 else
00754 c->send_param_list = p;
00755 c->send_param_tail = p;
00756
00757
00758 for (ch = p->name; *ch; ch++)
00759 if (*ch == '=' || *ch == '\n') *ch = ' ';
00760
00761
00762 for (ch = p->value; *ch; ch++)
00763 if (*ch == '\n') *ch = ' ';
00764 }
00765 }
00766
00767 void TCLinkSend(TCLinkHandle handle)
00768 {
00769 param *p, *next;
00770 char buf[TC_BUFF_MAX], destbuf[TC_LINE_MAX];
00771 char buf2[1024];
00772 int host_hash = 1;
00773 int retval = 0;
00774
00775 TCLinkCon *c = (TCLinkCon *)handle;
00776
00777 ClearRecvList(c);
00778
00779
00780 sprintf(buf, "BEGIN\nversion=%s\n", tclink_version);
00781
00782 for (p = c->send_param_list; p; p = next)
00783 {
00784 next = p->next;
00785 SAFE_COPY(buf2, p->name);
00786 SAFE_APPEND(buf2, "=");
00787 SAFE_APPEND(buf2, p->value);
00788 SAFE_APPEND(buf2, "\n");
00789 SAFE_APPEND(buf, buf2);
00790 if (!strcasecmp(p->name, "custid")) {
00791 host_hash = atoi(p->value);
00792 host_hash = (host_hash / 100) + (host_hash % 100);
00793 }
00794 free(p->name);
00795 free(p->value);
00796 free(p);
00797 }
00798
00799 c->send_param_list = c->send_param_tail = NULL;
00800
00801
00802 if (!Connect(c, host_hash))
00803 {
00804 Close(c);
00805 AddRecvParam(c, "status", "error");
00806 AddRecvParam(c, "errortype", "cantconnect");
00807 return;
00808 }
00809
00810
00811 sprintf(buf+strlen(buf), "pass=%d\ntime=%ld\n", c->pass, time(0) - c->start_time);
00812 if (c->dns != 1) SAFE_APPEND(buf, "dns=n\n");
00813 SAFE_APPEND(buf, "END\n");
00814
00815
00816 if (Send(c, buf))
00817 {
00818 int state = 0;
00819 buf[0] = destbuf[0] = 0;
00820 c->is_error = 0;
00821 while (1)
00822 {
00823 int len = ReadLine(c, buf, destbuf);
00824 if (len == 0) continue;
00825 if (len < 0) break;
00826 if (strcasecmp(destbuf, "BEGIN") == 0)
00827 {
00828 if (state != 0)
00829 { state = -1; break; }
00830 state = 1;
00831 }
00832 else if (strcasecmp(destbuf, "END") == 0)
00833 {
00834 if (state != 1)
00835 state = -1;
00836 else
00837 state = 2;
00838 break;
00839 }
00840 else
00841 {
00842 if (state != 1 || !AddRecvString(c, destbuf))
00843 { state = -1; break; }
00844 }
00845 }
00846 if (state == 2)
00847 retval = 1;
00848 }
00849
00850 Close(c);
00851
00852 if (!retval)
00853 {
00854 ClearRecvList(c);
00855 AddRecvParam(c, "status", "error");
00856 AddRecvParam(c, "errortype", "linkfailure");
00857 }
00858 }
00859
00860 char *TCLinkGetResponse(TCLinkHandle handle, const char *name, char *value)
00861 {
00862 param *p;
00863 TCLinkCon *c = (TCLinkCon *)handle;
00864
00865 for (p = c->recv_param_list; p; p = p->next)
00866 if (strcasecmp(name, p->name) == 0)
00867 {
00868 safe_copy(value, p->value, PARAM_MAX_LEN);
00869 return value;
00870 }
00871
00872 return NULL;
00873 }
00874
00875 static void stuff_string(char *buf, int *len, int size, const char *add)
00876 {
00877 int newlen = strlen(add);
00878 if ((*len + newlen) >= size)
00879 newlen = size - *len - 1;
00880 if (newlen < 1) return;
00881 strncpy(buf + *len, add, newlen);
00882 *len += newlen;
00883 buf[*len] = 0;
00884 }
00885
00886 char *TCLinkGetEntireResponse(TCLinkHandle handle, char *buf, int size)
00887 {
00888 param *p;
00889 int len = 0;
00890 TCLinkCon *c = (TCLinkCon *)handle;
00891
00892 for (p = c->recv_param_list; p; p = p->next) {
00893 stuff_string(buf, &len, size, p->name);
00894 stuff_string(buf, &len, size, "=");
00895 stuff_string(buf, &len, size, p->value);
00896 stuff_string(buf, &len, size, "\n");
00897 }
00898
00899 return buf;
00900 }
00901
00902 void TCLinkDestroy(TCLinkHandle handle)
00903 {
00904 TCLinkCon *c = (TCLinkCon *)handle;
00905 if (!c) return;
00906
00907 ClearSendList(c);
00908 ClearRecvList(c);
00909 Close(c);
00910
00911 if (c->ip)
00912 free(c->ip);
00913
00914 if (c->tc_cert)
00915 X509_free(c->tc_cert);
00916
00917 free(c);
00918 }
00919
00920 char *TCLinkGetVersion(char *buf)
00921 {
00922 strcpy(buf, tclink_version);
00923 return buf;
00924 }
00925