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

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

Generated on Fri May 16 14:49:54 2008 for Mobile-C by  doxygen 1.5.4