/home/dko/projects/mobilec/trunk/src/message.c

Go to the documentation of this file.
00001 /* SVN FILE INFO
00002  * $Revision: 174 $ : Last Committed Revision
00003  * $Date: 2008年06月24日 10:50:29 -0700 (2008年6月24日) $ : Last Committed Date */
00004 /*[
00005  * Copyright (c) 2007 Integration Engineering Laboratory
00006  University of California, Davis
00007  *
00008  * Permission to use, copy, and distribute this software and its
00009  * documentation for any purpose with or without fee is hereby granted,
00010  * provided that the above copyright notice appear in all copies and
00011  * that both that copyright notice and this permission notice appear
00012  * in supporting documentation.
00013  *
00014  * Permission to modify the software is granted, but not the right to
00015  * distribute the complete modified source code. Modifications are to
00016  * be distributed as patches to the released version. Permission to
00017  * distribute binaries produced by compiling modified sources is granted,
00018  * provided you
00019  * 1. distribute the corresponding source modifications from the
00020  * released version in the form of a patch file along with the binaries,
00021  * 2. add special version identification to distinguish your version
00022  * in addition to the base release version number,
00023  * 3. provide your name and address as the primary contact for the
00024  * support of your modified version, and
00025  * 4. retain our contact information in regard to use of the base
00026  * software.
00027  * Permission to distribute the released version of the source code along
00028  * with corresponding source modifications in the form of a patch file is
00029  * granted with same provisions 2 through 4 for binary distributions.
00030  *
00031  * This software is provided "as is" without express or implied warranty
00032  * to the extent permitted by applicable law.
00033 ]*/
00034 
00035 #include <string.h>
00036 #ifndef _WIN32
00037 #include <sys/types.h>
00038 #include <sys/socket.h>
00039 #include <netinet/in.h>
00040 #include <arpa/inet.h>
00041 #include <unistd.h>
00042 #include <netdb.h>
00043 #else
00044 #include "winconfig.h"
00045 #endif
00046 #include <mxml.h>
00047 #include "include/libmc.h"
00048 #include "include/agent.h"
00049 #include "include/mc_platform.h"
00050 #include "include/message.h"
00051 #include "include/mtp_http.h"
00052 #include "include/xml_compose.h"
00053 #include "include/xml_helper.h"
00054 #include "include/xml_parser.h"
00055 
00056 #include "security/asm_node.h"
00057 
00058 #define SOCKET_INPUT_SIZE 4096
00059 
00060 #ifdef MC_SECURITY
00061 int message_Decrypt(message_p message, asm_node_p asm_node)
00062 {
00063 int i;
00064 mxml_node_t* message_node;
00065 mxml_node_t* encrypted_data_node;
00066 mxml_node_t* gaf_message_node;
00067 char* encrypted_hex_string;
00068 unsigned char* message_string;
00069 char buf[3];
00070 unsigned char iv[32];
00071 int tmp = 0;
00072 int decrypt_len;
00073 
00074 gaf_message_node = mxmlFindElement
00075 (
00076 message->xml_root,
00077 message->xml_root,
00078 "MOBILEC_MESSAGE",
00079 NULL,
00080 NULL,
00081 MXML_DESCEND
00082 );
00083 /* Find the message element */
00084 message_node = mxmlFindElement
00085 (
00086 message->xml_root,
00087 message->xml_root,
00088 "MESSAGE",
00089 NULL,
00090 NULL,
00091 MXML_DESCEND
00092 );
00093 if (message_node == NULL) return MC_ERR_PARSE;
00094 encrypted_data_node = mxmlFindElement
00095 (
00096 message->xml_root,
00097 message_node,
00098 "ENCRYPTED_DATA",
00099 NULL,
00100 NULL,
00101 MXML_DESCEND
00102 );
00103 if (encrypted_data_node == NULL) return MC_ERR_PARSE;
00104 encrypted_hex_string = xml_get_text(encrypted_data_node);
00105 
00106 /* Now we need to convert the hex string into an unsigned char str. */
00107 message_string = (unsigned char*)malloc
00108 (
00109 sizeof(char) * 
00110 ((strlen(encrypted_hex_string)/2) + 32)
00111 );
00112 CHECK_NULL(message_string, exit(0););
00113 buf[2] = '0円';
00114 for(i = 0; i < (int)strlen(encrypted_hex_string); i += 2)
00115 {
00116 buf[0] = encrypted_hex_string[i];
00117 buf[1] = encrypted_hex_string[i+1];
00118 sscanf(buf, "%x", &tmp);
00119 message_string[i/2] = (unsigned char) tmp; 
00120 }
00121 
00122 decrypt_len = 
00123 strlen(encrypted_hex_string)/2;
00124 memset(iv, 0, sizeof(iv));
00125 aes_cbc_decrypt
00126 (
00127 &(asm_node->data.dh_data->aes),
00128 iv,
00129 (unsigned char*)message_string,
00130 (unsigned char*)message_string,
00131 decrypt_len
00132 );
00133 /* now we delete the old message node and compose a new one */
00134 mxmlDelete(message_node);
00135 
00136 mxmlLoadString
00137 (
00138 gaf_message_node,
00139 (char*)message_string,
00140 MXML_NO_CALLBACK
00141 );
00142 
00143 /* Free all stuff */
00144 free(encrypted_hex_string);
00145 free(message_string);
00146 
00147 /* re-parse the message */
00148 return message_xml_parse(message);
00149 }
00150 
00151 int
00152 message_Encrypt(message_p message, asm_node_p asm_node)
00153 {
00154 int i;
00155 int encrypt_len;
00156 mxml_node_t* message_node;
00157 mxml_node_t* gaf_message_node;
00158 mxml_node_t* encrypted_data_node;
00159 char* message_str;
00160 int message_len;
00161 char* encrypted_message_str;
00162 unsigned char iv[32];
00163 char buf[4];
00164 
00165 /* First, check to see if the xml root exists. If not, we must create it */
00166 if (message->xml_root == NULL) {
00167 message->xml_root = mxmlLoadString
00168 (
00169 NULL,
00170 message->message_body,
00171 MXML_NO_CALLBACK
00172 );
00173 }
00174 
00175 /* Now we can get rid of the old unencrypted message body */
00176 if(message->message_body) {
00177 free(message->message_body);
00178 message->message_body = NULL;
00179 }
00180 
00181 message_node = mxmlFindElement
00182 (
00183 message->xml_root,
00184 message->xml_root,
00185 "MESSAGE",
00186 NULL,
00187 NULL,
00188 MXML_DESCEND
00189 );
00190 if (message_node == NULL) {
00191 return MC_ERR_PARSE;
00192 }
00193 message_str = mxmlSaveAllocString
00194 (
00195 message_node,
00196 MXML_NO_CALLBACK
00197 );
00198 message_len = strlen(message_str);
00199 message_str = realloc(message_str, message_len + 16);
00200 CHECK_NULL(message_str, exit(0););
00201 
00202 encrypt_len = message_len + (16 - message_len%16);
00203 memset(iv, 0, sizeof(iv));
00204 aes_cbc_encrypt
00205 (
00206 &(asm_node->data.dh_data->aes),
00207 iv,
00208 (unsigned char*) message_str,
00209 (unsigned char*) message_str,
00210 encrypt_len
00211 );
00212 encrypted_message_str = (char*) malloc
00213 (
00214 sizeof(char) * 
00215 (encrypt_len*2)+1
00216 );
00217 CHECK_NULL(encrypted_message_str, exit(0););
00218 
00219 
00220 encrypted_message_str[0] = '0円';
00221 buf[2] = '0円';
00222 for (i = 0; i < encrypt_len ; i++) 
00223 {
00224 sprintf(buf, "%02x", (unsigned char)message_str[i]);
00225 strcat(encrypted_message_str, buf);
00226 }
00227 
00228 /* Now we delete the old message node and replace it with a new one */
00229 mxmlDelete(message_node);
00230 gaf_message_node = mxmlFindElement
00231 (
00232 message->xml_root,
00233 message->xml_root,
00234 "MOBILEC_MESSAGE",
00235 NULL,
00236 NULL,
00237 MXML_DESCEND
00238 );
00239 
00240 message_node = mxmlNewElement
00241 (
00242 gaf_message_node,
00243 "MESSAGE"
00244 );
00245 mxmlElementSetAttr
00246 (
00247 message_node,
00248 "message",
00249 "ENCRYPTED_DATA"
00250 );
00251 mxmlElementSetAttr
00252 (
00253 message_node,
00254 "from",
00255 message->from_address
00256 );
00257 
00258 encrypted_data_node = mxmlNewElement
00259 (
00260 message_node,
00261 "ENCRYPTED_DATA"
00262 );
00263 
00264 xml_new_cdata
00265 (
00266 encrypted_data_node,
00267 encrypted_message_str
00268 );
00269 
00270 message->message_body = mxmlSaveAllocString
00271 (
00272 message->xml_root,
00273 MXML_NO_CALLBACK
00274 );
00275 
00276 free(message_str);
00277 free(encrypted_message_str);
00278 
00279 message->message_type = ENCRYPTED_DATA;
00280 
00281 return MC_SUCCESS;
00282 }
00283 #endif /*MC_SECURITY*/
00284 
00285 message_p
00286 message_New(void)
00287 {
00288 message_p message;
00289 message = (message_p)malloc(sizeof(message_t));
00290 CHECK_NULL(message, exit(0););
00291 message->addr = NULL;
00292 message->connect_id = 0;
00293 message->message_id = 0;
00294 message->isHTTP = 0;
00295 message->message_type = 0;
00296 message->http_type = 0;
00297 message->xml_root = NULL;
00298 message->xml_payload = NULL;
00299 message->message_body = NULL;
00300 message->update_name = NULL;
00301 message->update_num = 0;
00302 message->from_address = NULL;
00303 message->to_address = NULL;
00304 message->target = NULL;
00305 message->agent_xml_flag = 0;
00306 return message;
00307 }
00308 
00309 message_p
00310 message_Copy(message_p src)
00311 {
00312 fprintf(stderr, "FIXME: message_Copy() is not implemented yet. %s:%d\n",
00313 __FILE__, __LINE__);
00314 return NULL;
00315 }
00316 
00317 int
00318 message_InitializeFromAgent(
00319 mc_platform_p mc_platform,
00320 message_p message,
00321 agent_p agent)
00322 {
00323 struct hostent* host;
00324 
00325 char* buf;
00326 char* destination_host;
00327 char* destination_port_str;
00328 #ifndef _WIN32
00329 char* save_ptr; /* For re-entrant strtok_r */
00330 #endif
00331 int destination_port;
00332 
00333 message->message_id = rand();
00334 message->message_type = MOBILE_AGENT;
00335 
00336 message->xml_root = agent_xml_compose(agent);
00337 /* If agent_xml_compose fails, that is a fatal error, since
00338  * 'agent' is gauranteed to be a valid agent. */
00339 CHECK_NULL(message->xml_root, exit(0););
00340 message->message_body = mxmlSaveAllocString( 
00341 message->xml_root,
00342 MXML_NO_CALLBACK );
00343 
00344 message->update_name = NULL;
00345 
00346 message->from_address =
00347 (char*)malloc(sizeof(char) * (strlen(mc_platform->hostname) + 10));
00348 sprintf(
00349 message->from_address,
00350 "%s:%d",
00351 mc_platform->hostname,
00352 mc_platform->port );
00353 if (
00354 agent->datastate->task_progress >=
00355 agent->datastate->number_of_tasks
00356 )
00357 {
00358 message->to_address = 
00359 (char*)malloc
00360 (
00361 sizeof(char) * 
00362 (
00363 strlen(agent->home) + 1
00364 )
00365 );
00366 CHECK_NULL(message->to_address, exit(0););
00367 strcpy
00368 (
00369 message->to_address,
00370 agent->home
00371 );
00372 } else {
00373 message->to_address = 
00374 (char*) malloc
00375 ( 
00376 sizeof(char) * 
00377 (
00378 strlen
00379 (
00380 agent->datastate->tasks[ agent->datastate->task_progress ]
00381 ->server_name 
00382 )
00383 +1
00384 )
00385 );
00386 CHECK_NULL( message->to_address, mc_platform->err = MC_ERR_MEMORY; return MC_ERR_MEMORY;);
00387 strcpy(
00388 message->to_address,
00389 agent->datastate->tasks[ agent->datastate->task_progress ]->server_name 
00390 );
00391 }
00392 message->agent_xml_flag = 0;
00393 message->target = strdup("ams");
00394 /* Set up message->addr */
00395 buf = (char*)malloc
00396 (
00397 sizeof(char) * 
00398 (strlen(message->to_address)+1)
00399 );
00400 CHECK_NULL(buf, exit(0););
00401 strcpy(buf, message->to_address);
00402 destination_host = strtok_r(buf, ":", &save_ptr);
00403 destination_port_str = strtok_r(NULL, ":", &save_ptr);
00404 destination_port = atoi(destination_port_str);
00405 message->addr = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
00406 if ((host = gethostbyname(destination_host))) {
00407 memcpy(&(message->addr->sin_addr), host->h_addr, host->h_length);
00408 message->addr->sin_port = htons(destination_port);
00409 } else {
00410 WARN("Host not found.");
00411 }
00412 free(buf);
00413 return MC_SUCCESS;
00414 }
00415 
00416 int
00417 message_InitializeFromConnection(
00418 mc_platform_p mc_platform,
00419 message_p message,
00420 connection_p connection)
00421 {
00422 int i = 1;
00423 int n;
00424 char *message_string;
00425 char *buffer;
00426 
00427 message->addr = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
00428 CHECK_NULL(message->addr, exit(0););
00429 *(message->addr) = connection->addr;
00430 
00431 message->connect_id = connection->connect_id;
00432 
00433 message->message_id = rand();
00434 
00435 message->to_address = NULL;
00436 message->from_address = NULL;
00437 message->target = NULL;
00438 
00439 buffer = (char*) malloc(sizeof(char) * (SOCKET_INPUT_SIZE + 1));
00440 CHECK_NULL(buffer, exit(0););
00441 message_string = (char*) malloc(sizeof(char) * (SOCKET_INPUT_SIZE + 1));
00442 CHECK_NULL(message_string, exit(0););
00443 message_string[0] = '0円';
00444 buffer[0] = '0円';
00445 
00446 /* Receive the message */
00447 while(1) {
00448 #ifndef _WIN32
00449 n = recvfrom(connection->clientfd,
00450 (void *) buffer,
00451 (size_t) sizeof(char)*SOCKET_INPUT_SIZE,
00452 0,
00453 (struct sockaddr *) 0,
00454 (socklen_t *) 0);
00455 #else
00456 n = recvfrom(connection->clientfd,
00457 (void *) buffer,
00458 (size_t) sizeof(char)*SOCKET_INPUT_SIZE,
00459 0,
00460 (struct sockaddr *) 0,
00461 0);
00462 #endif
00463 if (n < 0) {
00464 free(buffer);
00465 return MC_ERR_CONNECT;
00466 } 
00467 else if (n == 0) {
00468 free(buffer);
00469 break;
00470 } else {
00471 buffer[n] = '0円';
00472 i++;
00473 strcat(message_string, buffer);
00474 message_string = realloc
00475 (
00476 message_string, 
00477 sizeof(char) * (SOCKET_INPUT_SIZE+1) * i
00478 );
00479 CHECK_NULL(message_string, exit(0););
00480 buffer[0] = '0円';
00481 }
00482 }
00483 message->message_body = (char*)malloc
00484 (
00485 sizeof(char) * 
00486 (strlen(message_string) + 1)
00487 );
00488 CHECK_NULL(message->message_body, exit(0););
00489 strcpy(message->message_body, message_string);
00490 free(message_string);
00491 message->xml_root = mxmlLoadString
00492 (
00493 NULL, 
00494 message->message_body,
00495 MXML_NO_CALLBACK
00496 );
00497 if (message_xml_parse(message)) {
00498 fprintf(stderr, "Error parsing message at %s:%d.\n",
00499 __FILE__, __LINE__);
00500 message_Destroy(message);
00501 return MC_ERR_PARSE;
00502 }
00503 return MC_SUCCESS; 
00504 }
00505 
00506 int http_to_hostport(const char* http_str, char** host, int* port, char** target)
00507 {
00508 /* We want to convert the string "http://somehost.com:5050/acc" to a 
00509  * host: somehost.com
00510  * port: 5050
00511  * target: acc */
00512 char* tmp;
00513 if(strncmp(http_str, "http://", 7)) {
00514 return MC_ERR_PARSE;
00515 }
00516 http_str += 7;
00517 tmp = strchr(http_str, (int)':');
00518 if (tmp == NULL) return MC_ERR_PARSE;
00519 
00520 /* Get the host */
00521 *host = (char*)malloc(sizeof(char) * 
00522 (tmp - http_str + 1) );
00523 strncpy(*host, http_str, tmp - http_str);
00524 (*host)[tmp-http_str] = '0円';
00525 
00526 /* Get the port */
00527 tmp++;
00528 sscanf(tmp, "%d", port);
00529 
00530 /* Get the target */
00531 tmp = strchr(tmp, (int)'/');
00532 tmp++;
00533 *target = (char*)malloc(sizeof(char) * 
00534 (strlen(tmp)+1) );
00535 strcpy(*target, tmp);
00536 
00537 return 0;
00538 }
00539 
00540 int
00541 message_InitializeFromString(
00542 mc_platform_p mc_platform,
00543 message_p message,
00544 const char* string,
00545 const char* destination_host,
00546 int destination_port,
00547 const char* target)
00548 {
00549 char* destination;
00550 struct hostent* host;
00551 
00552 message->connect_id = 0;
00553 message->message_id = rand();
00554 
00555 message->message_type = MOBILE_AGENT;
00556 
00557 message->xml_root = NULL;
00558 
00559 message->message_body = 
00560 (char*)malloc( sizeof(char) * (strlen(string)+1));
00561 CHECK_NULL(message->message_body, 
00562 mc_platform->err = MC_ERR_MEMORY;
00563 return MC_ERR_MEMORY; );
00564 strcpy(message->message_body, string);
00565 
00566 message->update_name = NULL;
00567 
00568 destination = malloc(sizeof(char)*(strlen(destination_host) + 10));
00569 CHECK_NULL(destination,
00570 mc_platform->err = MC_ERR_MEMORY;
00571 return MC_ERR_MEMORY; );
00572 sprintf(destination, "%s:%d", 
00573 destination_host,
00574 destination_port
00575 );
00576 
00577 message->to_address = destination;
00578 message->from_address = (char*)malloc(
00579 sizeof(char) * (strlen(mc_platform->hostname)+10));
00580 sprintf(message->from_address,
00581 "%s:%d",
00582 mc_platform->hostname,
00583 mc_platform->port );
00584 message->target = (char*)malloc(sizeof(char) * 
00585 (strlen(target)+1));
00586 strcpy(message->target, target);
00587 
00588 /* Set up message->addr */
00589 message->addr = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
00590 if (destination_host != NULL && strlen(destination_host)!= 0) {
00591 if((host = gethostbyname(destination_host)))
00592 {
00593 memcpy(&(message->addr->sin_addr), host->h_addr, host->h_length);
00594 message->addr->sin_port = htons(destination_port);
00595 } else {
00596 fprintf(stderr, "Warning: Host not found: %s:%d %s:%d",
00597 destination_host, destination_port, __FILE__, __LINE__ );
00598 }
00599 }
00600 
00601 return MC_SUCCESS;
00602 }
00603 
00604 int
00605 message_Destroy(message_p message)
00606 {
00607 if (message == NULL) {
00608 return MC_SUCCESS;
00609 }
00610 /* We may not want to delete this here,
00611  * in case an agent needs this data. */
00612 if(message->xml_root != NULL && message->agent_xml_flag == 0) {
00613 mxmlDelete(message->xml_root);
00614 }
00615 
00616 if(message->addr) {
00617 free(message->addr);
00618 message->addr = NULL;
00619 }
00620 if(message->message_body != NULL) {
00621 free(message->message_body);
00622 message->message_body = NULL;
00623 }
00624 if(message->update_name != NULL) {
00625 free(message->update_name);
00626 }
00627 if(message->from_address != NULL) {
00628 free(message->from_address);
00629 }
00630 if(message->to_address != NULL) {
00631 free(message->to_address);
00632 }
00633 if(message->target != NULL) {
00634 free(message->target);
00635 }
00636 
00637 free(message);
00638 message = NULL;
00639 return MC_SUCCESS;
00640 }
00641 
00642 int
00643 message_Send(message_p message)
00644 {
00645 char *buffer;
00646 mtp_http_t* mtp_http;
00647 int n;
00648 #ifndef _WIN32
00649 int skt;
00650 struct sockaddr_in sktin;
00651 #else
00652 SOCKET skt;
00653 SOCKADDR_IN sktin;
00654 #endif
00655 struct hostent *host;
00656 char *buf;
00657 char *hostname;
00658 #ifndef _WIN32
00659 char *saveptr; /* For reentrant strtok_r */
00660 #endif
00661 int port;
00662 
00663 /* Compose the http message */
00664 if (
00665 mtp_http_ComposeMessage(
00666 message
00667 )
00668 )
00669 {
00670 return MC_ERR;
00671 }
00672 
00673 /* We need to split up the address into a hostname and port. */
00674 buf = (char*)malloc(sizeof(char)*(strlen(message->to_address)+1));
00675 strcpy(buf, message->to_address);
00676 hostname = strtok_r(buf, ":", &saveptr);
00677 sscanf( strtok_r(NULL, ":", &saveptr), "%d", &port );
00678 
00679 if((skt = socket(PF_INET, SOCK_STREAM, 0)) < 0) 
00680 { 
00681 fprintf(stderr, "Error - can't create socket\n");
00682 return -1;
00683 }
00684 
00685 memset(&sktin, 0, sizeof(sktin));
00686 sktin.sin_family = PF_INET;
00687 sktin.sin_port = htons(port);
00688 
00689 if((host = gethostbyname(hostname))) 
00690 {
00691 memcpy(&sktin.sin_addr, host->h_addr, host->h_length);
00692 }
00693 else if((sktin.sin_addr.s_addr = inet_addr(hostname)) < 0) 
00694 {
00695 fprintf(stderr, "Error - can't get host entry for %s\n", hostname);
00696 free(buf);
00697 return -1;
00698 }
00699 
00700 if(connect(skt, (struct sockaddr *) &sktin, sizeof(sktin)) < 0) {
00701 fprintf(stderr, "Error - can't connect to %s:%d\n",
00702 hostname,
00703 port
00704 );
00705 free(buf);
00706 return MC_ERR_CONNECT;
00707 }
00708 /* now send the string */
00709 if(send(skt, message->message_body, strlen(message->message_body), 0) < 0) 
00710 {
00711 fprintf(stderr, "cannot write to socket %s:%d\n",
00712 __FILE__, __LINE__);
00713 #ifndef _WIN32
00714 close(skt);
00715 #else
00716 closesocket(skt);
00717 #endif
00718 free(buf);
00719 return MC_ERR_SEND;
00720 }
00721 /* Now we should receive an HTTP response */
00722 buffer = (char*) malloc(sizeof(char) * (SOCKET_INPUT_SIZE + 1));
00723 CHECK_NULL(buffer, exit(0););
00724 mtp_http = mtp_http_New();
00725 #ifndef _WIN32
00726 n = recvfrom(skt,
00727 (void *) buffer,
00728 (size_t) sizeof(char)*SOCKET_INPUT_SIZE,
00729 0,
00730 (struct sockaddr *) 0,
00731 (socklen_t *) 0);
00732 #else
00733 n = recvfrom(skt,
00734 (void *) buffer,
00735 (size_t) sizeof(char)*SOCKET_INPUT_SIZE,
00736 0,
00737 (struct sockaddr *) 0,
00738 0);
00739 #endif
00740 if( mtp_http_Parse(mtp_http, buffer) ) {
00741 fprintf(stderr, "http parsing error: Response expected. %s:%d\n",
00742 __FILE__, __LINE__);
00743 fprintf(stderr, "Received message was:\n%s\n", buffer);
00744 }
00745 if (mtp_http->response_code != 200) {
00746 fprintf(stderr, "Warning: remote http server responded: %d %s\n",
00747 mtp_http->response_code, mtp_http->response_string );
00748 }
00749 
00750 #ifndef _WIN32
00751 close(skt);
00752 #else
00753 closesocket(skt);
00754 #endif
00755 free(buf);
00756 return 0;
00757 }
00758 
00759 

Generated on Tue Oct 28 17:03:22 2008 for Mobile-C by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /