/home/dko/projects/mobilec/tags/MobileC-v1.10.2/MobileC-v1.10.2/src/message.c

Go to the documentation of this file.
00001 /* SVN FILE INFO
00002  * $Revision: 207 $ : Last Committed Revision
00003  * $Date: 2008-07-11 17:55:19 -0700 (Fri, 11 Jul 2008) $ : 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 Fri Jul 11 17:59:45 2008 for Mobile-C by  doxygen 1.5.4