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