00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "libjabber.h"
00024
00025
00026 #define STATE_EVT(arg) if(j->on_state) { (j->on_state)(j, (arg) ); }
00027
00028
00029 static void startElement(void *userdata, const char *name, const char **attribs);
00030 static void endElement(void *userdata, const char *name);
00031 static void charData(void *userdata, const char *s, int slen);
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 jabconn
00045 jab_new(char *user, char *pass)
00046 {
00047 xode_pool p;
00048 jabconn j;
00049
00050 if (!user)
00051 return (NULL);
00052
00053 p = xode_pool_new();
00054 if (!p)
00055 return (NULL);
00056 j = xode_pool_mallocx(p, sizeof(jabconn_struct), 0);
00057 if (!j)
00058 return (NULL);
00059 j->p = p;
00060
00061 j->user = jid_new(p, user);
00062 j->pass = xode_pool_strdup(p, pass);
00063 j->port = 5222;
00064
00065 j->state = JABCONN_STATE_OFF;
00066 j->id = 1;
00067 j->fd = -1;
00068 j->dumpfd = -1;
00069 j->dumpid = NULL;
00070 #ifdef USE_SSL
00071 j->ssl = NULL;
00072 j->ssl_ctx = NULL;
00073 j->sslfd = -1;
00074 #endif
00075
00076 return j;
00077 }
00078
00079
00080
00081
00082
00083
00084
00085
00086 void
00087 jab_delete(jabconn j)
00088 {
00089 if (!j)
00090 return;
00091
00092 jab_stop(j);
00093 xode_pool_free(j->p);
00094 }
00095
00096
00097
00098
00099
00100
00101
00102
00103 void
00104 jab_state_handler(jabconn j, jabconn_state_h h)
00105 {
00106 if (!j)
00107 return;
00108
00109 j->on_state = h;
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119 void
00120 jab_packet_handler(jabconn j, jabconn_packet_h h)
00121 {
00122 if (!j)
00123 return;
00124
00125 j->on_packet = h;
00126 }
00127
00128 #ifdef USE_SSL
00129 void
00130 init_prng()
00131 {
00132 if (RAND_status() == 0) {
00133 char rand_file[256];
00134 time_t t;
00135 pid_t pid;
00136 long l, seed;
00137
00138 t = time(NULL);
00139 pid = getpid();
00140 RAND_file_name((char *) &rand_file, 256);
00141 if (rand_file != NULL) {
00142 RAND_load_file(rand_file, 1024);
00143 }
00144 RAND_seed((unsigned char *) &t, sizeof(time_t));
00145 RAND_seed((unsigned char *) &pid, sizeof(pid_t));
00146 RAND_bytes((unsigned char *) &seed, sizeof(long));
00147 srand48(seed);
00148 while (RAND_status() == 0) {
00149 l = lrand48();
00150 RAND_seed((unsigned char *) &l, sizeof(long));
00151 }
00152 if (rand_file != NULL) {
00153 RAND_write_file(rand_file);
00154 }
00155 }
00156 return;
00157 }
00158 #endif
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 void
00169 jab_start(jabconn j, int ssl)
00170 {
00171 xode x;
00172 char *t, *t2;
00173
00174 if (!j || j->state != JABCONN_STATE_OFF)
00175 return;
00176
00177 j->parser = XML_ParserCreate(NULL);
00178 XML_SetUserData(j->parser, (void *) j);
00179 XML_SetElementHandler(j->parser, startElement, endElement);
00180 XML_SetCharacterDataHandler(j->parser, charData);
00181
00182 j->fd = make_netsocket(j->port, j->user->server, NETSOCKET_CLIENT);
00183 if (j->fd < 0) {
00184 STATE_EVT(JABCONN_STATE_OFF)
00185 return;
00186 }
00187
00188 #ifdef USE_SSL
00189 if (ssl && j->fd >= 0) {
00190 SSL_library_init();
00191 SSL_load_error_strings();
00192 j->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
00193 if (!j->ssl_ctx) {
00194 STATE_EVT(JABCONN_STATE_OFF)
00195 return;
00196 }
00197 j->ssl = (SSL *)SSL_new(j->ssl_ctx);
00198 if (!j->ssl) {
00199 STATE_EVT(JABCONN_STATE_OFF)
00200 return;
00201 }
00202 SSL_set_fd(j->ssl, j->fd);
00203 SSL_connect(j->ssl);
00204 j->sslfd = SSL_get_fd(j->ssl);
00205 if (j->sslfd < 0) {
00206 STATE_EVT(JABCONN_STATE_OFF)
00207 return;
00208 }
00209 }
00210 #endif
00211
00212 j->state = JABCONN_STATE_CONNECTED;
00213 STATE_EVT(JABCONN_STATE_CONNECTED)
00214
00215 x = jabutil_header(NS_CLIENT, j->user->server);
00216 t = xode_to_str(x);
00217
00218
00219
00220
00221
00222 t2 = strstr(t, "/>");
00223 *t2++ = '>';
00224 *t2 = '\0';
00225 jab_send_raw(j, "<?xml version='1.0'?>");
00226 jab_send_raw(j, t);
00227 xode_free(x);
00228
00229 jab_recv(j);
00230
00231 j->state = JABCONN_STATE_AUTH;
00232 STATE_EVT(JABCONN_STATE_AUTH);
00233 }
00234
00235 void
00236 jab_startup(jabconn j) {
00237 j->state = JABCONN_STATE_ON;
00238 STATE_EVT(JABCONN_STATE_ON);
00239 }
00240
00241
00242
00243
00244
00245
00246
00247 void
00248 jab_stop(jabconn j)
00249 {
00250 if (!j || j->state == JABCONN_STATE_OFF)
00251 return;
00252
00253 j->state = JABCONN_STATE_OFF;
00254 #ifdef USE_SSL
00255 SSL_CTX_free(j->ssl_ctx);
00256 SSL_free(j->ssl);
00257 j->ssl = NULL;
00258 j->sslfd = -1;
00259 #endif
00260 close(j->fd);
00261 j->fd = -1;
00262 j->dumpfd = -1;
00263 j->dumpid = NULL;
00264 XML_ParserFree(j->parser);
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 int
00277 jab_getfd(jabconn j)
00278 {
00279 if (j) {
00280 #ifdef USE_SSL
00281 if (j->sslfd != -1) {
00282 return j->sslfd;
00283 }
00284 else {
00285 #endif
00286 return j->fd;
00287 #ifdef USE_SSL
00288 }
00289 #endif
00290 }
00291 else {
00292 return -1;
00293 }
00294 }
00295
00296
00297
00298
00299
00300
00301
00302 jid
00303 jab_getjid(jabconn j)
00304 {
00305 if (j)
00306 return (j->user);
00307 else
00308 return NULL;
00309 }
00310
00311
00312
00313
00314
00315
00316
00317 char *
00318 jab_getsid(jabconn j)
00319 {
00320 if (j)
00321 return (j->sid);
00322 else
00323 return NULL;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332 char *
00333 jab_getid(jabconn j)
00334 {
00335 snprintf(j->idbuf, 8, "%d", j->id++);
00336 return &j->idbuf[0];
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346 void
00347 jab_send(jabconn j, xode x)
00348 {
00349 if (j && j->state != JABCONN_STATE_OFF) {
00350 char *buf = xode_to_str(x);
00351 #ifdef USE_SSL
00352 if (j->sslfd == -1) {
00353 #endif
00354 if (buf)
00355 write(j->fd, buf, strlen(buf));
00356 #ifdef USE_SSL
00357 }
00358 else {
00359 if (buf)
00360 SSL_write(j->ssl, buf, strlen(buf));
00361 }
00362 #endif
00363 dprintf(dJAB, "out: %s\n", buf);
00364 }
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374 void
00375 jab_send_raw(jabconn j, const char *str)
00376 {
00377 if (j && j->state != JABCONN_STATE_OFF)
00378 #ifdef USE_SSL
00379 if (j->sslfd == -1) {
00380 #endif
00381 write(j->fd, str, strlen(str));
00382 #ifdef USE_SSL
00383 }
00384 else {
00385 SSL_write(j->ssl, str, strlen(str));
00386 }
00387 #endif
00388 dprintf(dJAB, "out: %s\n", str);
00389 }
00390
00391
00392
00393
00394
00395
00396
00397 void
00398 jab_recv(jabconn j)
00399 {
00400 static char buf[4096];
00401 int len;
00402 int errcode;
00403
00404 if (!j || j->state == JABCONN_STATE_OFF)
00405 return;
00406
00407 #ifdef USE_SSL
00408 if (j->sslfd == -1) {
00409 #endif
00410 len = read(j->fd, buf, sizeof(buf) - 1);
00411 #ifdef USE_SSL
00412 }
00413 else {
00414 len = SSL_read(j->ssl, buf, sizeof(buf) - 1);
00415 }
00416 #endif
00417 if (len > 0) {
00418 buf[len] = '\0';
00419 dprintf(dJAB, " in: %s\n", buf);
00420 errcode = XML_Parse(j->parser, buf, len, 0);
00421 dprintf(dParser, "parser index %d, line %d, col %d\n", XML_GetCurrentByteIndex(j->parser), XML_GetCurrentLineNumber(j->parser), XML_GetCurrentColumnNumber(j->parser));
00422 if (errcode == 0) {
00423 dprintf(dParser, "parser error %d at byte %d: %s\n", XML_GetErrorCode(j->parser), XML_GetCurrentByteIndex(j->parser), XML_ErrorString(XML_GetErrorCode(j->parser)));
00424 }
00425 else {
00426 dprintf(dParser, "parser complete\n");
00427 }
00428 }
00429 else if (len < 0) {
00430 STATE_EVT(JABCONN_STATE_OFF);
00431 jab_stop(j);
00432 }
00433 }
00434
00435
00436
00437
00438
00439
00440
00441
00442 void
00443 jab_poll(jabconn j, int timeout)
00444 {
00445 fd_set fds;
00446 FILE *selfd;
00447 struct timeval tv;
00448
00449 if (!j || j->state == JABCONN_STATE_OFF)
00450 return;
00451
00452 FD_ZERO(&fds);
00453 #ifdef USE_SSL
00454 if (j->sslfd == -1) {
00455 #endif
00456 FD_SET(j->fd, &fds);
00457 selfd = (FILE *) j->fd;
00458 #ifdef USE_SSL
00459 }
00460 else {
00461 FD_SET(j->sslfd, &fds);
00462 selfd = (FILE *) j->sslfd;
00463 }
00464 #endif
00465
00466
00467 if (timeout < 0) {
00468 if (select((int) selfd + 1, &fds, NULL, NULL, NULL) > 0)
00469 jab_recv(j);
00470 }
00471 else {
00472 tv.tv_sec = 0;
00473 tv.tv_usec = timeout;
00474 if (select((int) selfd + 1, &fds, NULL, NULL, &tv) > 0)
00475 jab_recv(j);
00476 }
00477 }
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 char *
00489 jab_auth(jabconn j)
00490 {
00491 xode x, y, z;
00492 char *user, *id;
00493
00494 if (!j)
00495 return (NULL);
00496
00497 user = j->user->user;
00498 id = jab_getid(j);
00499
00500 x = jabutil_iqnew(JABPACKET__GET, NS_AUTH);
00501 xode_put_attrib(x, "id", "auth_1");
00502 xode_put_attrib(x, "to", j->user->server);
00503 y = xode_get_tag(x, "query");
00504
00505 if (user) {
00506 z = xode_insert_tag(y, "username");
00507 xode_insert_cdata(z, user, -1);
00508 }
00509
00510 jab_send(j, x);
00511 xode_free(x);
00512 jab_recv(j);
00513
00514 x = jabutil_iqnew(JABPACKET__SET, NS_AUTH);
00515 xode_put_attrib(x, "id", "auth_2");
00516 xode_put_attrib(x, "to", j->user->server);
00517 y = xode_get_tag(x, "query");
00518
00519 if (user) {
00520 dprintf(dExecution, "Got auth user %s...\n", user);
00521 z = xode_insert_tag(y, "username");
00522 xode_insert_cdata(z, user, -1);
00523 }
00524
00525 z = xode_insert_tag(y, "resource");
00526 xode_insert_cdata(z, j->user->resource, -1);
00527 dprintf(dExecution, "Got auth resource %s...\n", j->user->resource);
00528
00529 dprintf(dExecution, "Got auth password %s...\n", j->pass);
00530 if (j->sid && j->auth_digest) {
00531 char *hash;
00532
00533 dprintf(dExecution, "Got digest auth id %s...\n", j->sid);
00534 z = xode_insert_tag(y, "digest");
00535 hash = xode_pool_malloc(x->p,
00536 strlen(j->sid) + strlen(j->pass) + 1);
00537 strcpy(hash, j->sid);
00538 strcat(hash, j->pass);
00539 hash = (char *)j_shahash(hash);
00540 xode_insert_cdata(z, hash, 40);
00541 }
00542 else if (j->auth_password) {
00543 z = xode_insert_tag(y, "password");
00544 xode_insert_cdata(z, j->pass, -1);
00545 }
00546
00547 jab_send(j, x);
00548 xode_free(x);
00549 jab_recv(j);
00550
00551 return id;
00552 }
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 char *
00564 jab_reg(jabconn j)
00565 {
00566 xode x, y, z;
00567 char *user, *id;
00568
00569
00570 if (!j)
00571 return (NULL);
00572
00573 x = jabutil_iqnew(JABPACKET__SET, NS_REGISTER);
00574 id = jab_getid(j);
00575 xode_put_attrib(x, "id", id);
00576 y = xode_get_tag(x, "query");
00577
00578 user = j->user->user;
00579
00580 if (user) {
00581 z = xode_insert_tag(y, "username");
00582 xode_insert_cdata(z, user, -1);
00583 }
00584
00585 z = xode_insert_tag(y, "resource");
00586 xode_insert_cdata(z, j->user->resource, -1);
00587
00588 if (j->pass) {
00589 z = xode_insert_tag(y, "password");
00590 xode_insert_cdata(z, j->pass, -1);
00591 }
00592
00593 jab_send(j, x);
00594 xode_free(x);
00595
00596 j->state = JABCONN_STATE_AUTH;
00597 STATE_EVT(JABCONN_STATE_AUTH)
00598
00599 return id;
00600 }
00601
00602
00603
00604
00605 static void
00606 startElement(void *userdata, const char *name, const char **attribs)
00607 {
00608 xode x;
00609 jabconn j = (jabconn) userdata;
00610
00611 if (strcmp(name, "stream:stream") == 0) {
00612
00613
00614 x = xode_new(name);
00615 xode_put_expat_attribs(x, attribs);
00616 j->sid = xode_get_attrib(x, "id");
00617 xode_free(x);
00618 dprintf(dXML, "Got stream:stream, retrieved stream id %s.\n", j->sid);
00619 }
00620
00621 if (j->current) {
00622
00623 x = xode_insert_tag(j->current, name);
00624 xode_put_expat_attribs(x, attribs);
00625
00626 j->current = x;
00627 }
00628 else {
00629 x = xode_new(name);
00630 xode_put_expat_attribs(x, attribs);
00631 if (strcmp(name, "stream:stream") != 0) {
00632 j->current = x;
00633 }
00634 }
00635 }
00636
00637 static void
00638 endElement(void *userdata, const char *name)
00639 {
00640 jabconn j = (jabconn) userdata;
00641 xode x;
00642 jabpacket p;
00643
00644 if (j->current == NULL) {
00645
00646 STATE_EVT(JABCONN_STATE_OFF)
00647 return;
00648 }
00649
00650 x = xode_get_parent(j->current);
00651
00652 if (x == NULL) {
00653
00654 p = jabpacket_new(j->current);
00655
00656 if (j->on_packet)
00657 (j->on_packet) (j, p);
00658 xode_free(j->current);
00659 }
00660
00661 j->current = x;
00662 }
00663
00664 static void
00665 charData(void *userdata, const char *s, int slen)
00666 {
00667 jabconn j = (jabconn) userdata;
00668
00669 if (j->current)
00670 xode_insert_cdata(j->current, s, slen);
00671 }