Exemple #1
0
int parse_charset(Octstr *os)
{
    Octstr *charset = NULL;
    Octstr *number = NULL;
    int i, j, cut = 0, ret = 0;

    gw_assert(os != NULL);
    charset = octstr_duplicate(os);
    
    /* The charset might be in lower case, so... */
    octstr_convert_range(charset, 0, octstr_len(charset), toupper);

    /*
     * The character set is handled in two parts to make things easier. 
     * The cutting.
     */
    if ((cut = octstr_search_char(charset, '_', 0)) > 0) {
        number = octstr_copy(charset, cut + 1, (octstr_len(charset) - (cut + 1)));
        octstr_truncate(charset, cut);
    } 
    else if ((cut = octstr_search_char(charset, '-', 0)) > 0) {
        number = octstr_copy(charset, cut + 1, (octstr_len(charset) - (cut + 1)));
        octstr_truncate(charset, cut);
    }

    /* And table search. */
    for (i = 0; character_sets[i].charset != NULL; i++)
        if (octstr_str_compare(charset, character_sets[i].charset) == 0) {
            for (j = i; octstr_str_compare(charset, 
                                           character_sets[j].charset) == 0; j++)
                if (octstr_str_compare(number, character_sets[j].nro) == 0) {
                    ret = character_sets[j].MIBenum;
                    break;
                }
            break;
        }

    /* UTF-8 is the default value */
    if (character_sets[i].charset == NULL)
        ret = character_sets[i-1].MIBenum;

    octstr_destroy(number);
    octstr_destroy(charset);

    return ret;
}
Exemple #2
0
static void parse_value(Octstr *value)
{
    Octstr *temp;
    long len;
    int c;
    
    octstr_strip_blanks(value);

    len = octstr_len(value);
    if (octstr_get_char(value, 0) != '"' || 
        octstr_get_char(value, len - 1) != '"')
	return;

    octstr_delete(value, len - 1, 1);
    octstr_delete(value, 0, 1);

    temp = octstr_duplicate(value);
    octstr_truncate(value, 0);
    
    while (octstr_len(temp) > 0) {
	c = octstr_get_char(temp, 0);
	octstr_delete(temp, 0, 1);
	
    	if (c != '\\' || octstr_len(temp) == 0)
	    octstr_append_char(value, c);
	else {
	    c = octstr_get_char(temp, 0);
	    octstr_delete(temp, 0, 1);

	    switch (c) {
    	    case '\\':
    	    case '"':
	    	octstr_append_char(value, c);
	    	break;
		
    	    default:
	    	octstr_append_char(value, '\\');
	    	octstr_append_char(value, c);
		break;
	    }
	}
    }
    
    octstr_destroy(temp);
}
/* Pseudo Random Function (PRF) as described in WAP WTLS section 11.3.2 */
Octstr *wtls_calculate_prf(Octstr * secret, Octstr * label, Octstr * seed,
            int byteLength, WTLSMachine * wtls_machine)
{
   Octstr *returnOctstr;
    	Octstr *labelPlusSeed;

    	/* Create label + seed */
		labelPlusSeed = octstr_cat(label, seed);
		
		/* PRF(secret, label, seed) = P_hash(secret, label + seed) */
   returnOctstr = wtls_P_hash(secret, labelPlusSeed, byteLength,
               wtls_machine);
		
    	/* Return the first nbytes of the hashed data */
		octstr_truncate(returnOctstr, byteLength);
		 
   octstr_destroy(labelPlusSeed);
   return (returnOctstr);
}
Exemple #4
0
static void send_file(int udpsock, char *filename, Octstr *address) {
	Octstr *contents;

	contents = octstr_read_file(filename);
	if (contents == NULL) {
		info(0, "Skipping \"%s\".", filename);
		return;
	}

	info(0, "Sending \"%s\", %ld octets.", filename, octstr_len(contents));

	if (octstr_len(contents) > maxsize) {
		octstr_truncate(contents, maxsize);
		warning(0, "Truncating to %ld octets.", maxsize);
	}

	udp_sendto(udpsock, contents, address);

	octstr_destroy(contents);
}
/* Not to be confused with octstr_hash, this applies the currently set hashing
   algorithm from wtls_machine to the supplied input data, returning a hashed
   Octstr. If it fails, it will return a NULL pointer */
Octstr *wtls_hash(Octstr * inputData, WTLSMachine * wtls_machine)
{
        int inputDataLength;
        int outputDataLength;
   unsigned char *outputDataTemp;
   unsigned char *inputDataTemp;
   unsigned char *tempPointer = NULL;
   Octstr *outputData;

        inputDataLength = octstr_len(inputData);
        outputDataLength = hash_table[wtls_machine->mac_algorithm].key_size;
        inputDataTemp = gw_malloc(inputDataLength);
        outputDataTemp = gw_malloc(outputDataLength);

        /* Copy the contents of inputData into inputDataTemp, ready for hashing */
   tempPointer = (unsigned char *)octstr_get_cstr(inputData);
   memcpy((void *)inputDataTemp, (void *)tempPointer, inputDataLength);
        
        /* Hash away! */
        // Here's where we need to hash on the selected algorithm, not just the SHA-1 algorithm
		//debug("wtls", 0, "mac algo %d", wtls_machine->mac_algorithm);
        switch (wtls_machine->mac_algorithm) {
			case SHA_0:
      /* Do nothing */
				break;

			case SHA_40:
			case SHA_80:
			case SHA_NOLIMIT:
      tempPointer =
          SHA1(inputDataTemp, inputDataLength, outputDataTemp);
				break;

			case SHA_XOR_40:
				// dunno yet
				break;

			case MD5_40:
			case MD5_80:
			case MD5_NOLIMIT:
      tempPointer = MD5(inputDataTemp, inputDataLength,
              outputDataTemp);
				break;
		}
   if (!tempPointer) {
      if (wtls_machine->mac_algorithm != SHA_0)
         error(0, "wtls_hash: Failed to hash input");
      gw_free(outputDataTemp);
      gw_free(inputDataTemp);
      return (NULL);
        }

        /* Get our output data setup */
   outputData = octstr_create_from_data((char *)outputDataTemp,
                    outputDataLength);
        
		/* some algorithms don't use the full length of H */
   octstr_truncate(outputData,
         hash_table[wtls_machine->mac_algorithm].mac_size);
		
        /* Delete our allocated memory */
        gw_free(outputDataTemp);
        gw_free(inputDataTemp);
        
        /* Return the outputData */
   return (outputData);
}
Exemple #6
0
int create_web_data(char *p_pszFileName, char *p_pszMMSDir, const char *p_pszWebDir)
{
  int iRetVal = 0;
  MmsEnvelope *psoEnv;
  MmsMsg *psoMsg = NULL;
  List *psoHdrList = NULL;
  Octstr *psoHdrs = NULL, *psoHdrName = NULL, *psoHdrValue = NULL, *psoWebDir = NULL;
  MIMEEntity *psoMIME, *psoMIMETmp;
  int iMIMENum, iMIMEInd;
  int iFile = -1;

  gwlib_init();
  mms_strings_init();

  /* формируем имя директрии для вывода результатов */
  psoWebDir = octstr_create(p_pszWebDir);
  if('/' != octstr_get_char(psoWebDir, octstr_len(psoWebDir) - 1)) {
    octstr_append_char(psoWebDir, '/');
  }
  octstr_append_cstr(psoWebDir, p_pszFileName);

  /* создаем директорию */
  if(mkdir(octstr_get_cstr(psoWebDir), 0777)) {
    if(errno != EEXIST) {
      iRetVal = 2;
    }
    goto done;
  }

  psoEnv = default_qfuncs.mms_queue_readenvelope(p_pszFileName, p_pszMMSDir, 0);
  if(psoEnv) {
    psoMsg = default_qfuncs.mms_queue_getdata(psoEnv);
    default_qfuncs.mms_queue_free_env(psoEnv);
  } else {
    iRetVal = 3;
    goto done;
  }

  if(!psoMsg) {
    iRetVal = 4;
    goto done;
  }

  psoHdrs = octstr_create("");
  /* выбираем необходимые заголовки */
  psoHdrList = mms_message_headers(psoMsg);
  /* From */
  psoHdrName = octstr_create("From");
  psoHdrValue = http_header_value(psoHdrList, psoHdrName);
  octstr_format_append(psoHdrs, "%S/%S\r\n", psoHdrName, psoHdrValue);
  octstr_truncate(psoHdrName, 0);
  /* To */
  octstr_append_cstr(psoHdrName, "To");
  psoHdrValue = http_header_value(psoHdrList, psoHdrName);
  octstr_format_append(psoHdrs, "%S/%S\r\n", psoHdrName, psoHdrValue);
  octstr_truncate(psoHdrName, 0);
  /* Date */
  octstr_append_cstr(psoHdrName, "Date");
  psoHdrValue = http_header_value(psoHdrList, psoHdrName);
  octstr_format_append(psoHdrs, "%S/%S", psoHdrName, psoHdrValue);
  octstr_truncate(psoHdrName, 0);
  /**/

  psoMIME = mms_tomime(psoMsg, 1);
  iMIMENum = mime_entity_num_parts(psoMIME);
  if(psoMIME) {
    for(iMIMEInd = 0; iMIMEInd < iMIMENum; ++iMIMEInd) {
      psoMIMETmp = mime_entity_get_part(psoMIME, iMIMEInd);
      operate_single_mime(psoHdrs, psoMIMETmp, octstr_get_cstr(psoWebDir));
    }
  }

  /* формируем имя файла для вывода результатов, используем ту же переменную, что и для директории */
  if('/' != octstr_get_char(psoWebDir, octstr_len(psoWebDir) - 1)) {
    octstr_append_char(psoWebDir, '/');
  }
  octstr_append_cstr(psoWebDir, "common");
  /* создаем файл */
  iFile = open(octstr_get_cstr(psoWebDir), O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  if(0 < iFile) {
    if(octstr_len(psoHdrs) != write(iFile, octstr_get_cstr(psoHdrs), octstr_len(psoHdrs))) {
      iRetVal = 5;
    }
    close(iFile);
  } else {
    if(errno != EEXIST) {
      iRetVal = 6;
    }
  }

  done:
  if(psoHdrs) {
    octstr_destroy(psoHdrs);
  }
  if(psoHdrName) {
    octstr_destroy(psoHdrName);
  }
  if(psoWebDir) {
    octstr_destroy(psoWebDir);
  }

  mms_strings_shutdown();
  gwlib_shutdown();

  return iRetVal;
}
Exemple #7
0
int operate_single_mime(Octstr *p_psoHdrs, MIMEEntity *p_psoMIME, const char *p_pszWebDir)
{
  int iRetVal = 0;
  Octstr *psoHdrName = NULL, *psoHdrValue = NULL;
  Octstr *psoMIMEOStr = NULL, *psoFileName = NULL;
  List *psoHdrList = NULL;
  int iFile = -1;

  if(psoMIMEOStr) {
    octstr_destroy(psoMIMEOStr);
  }
  /* выбираем необходимые заголовки */
  psoHdrList = mime_entity_headers(p_psoMIME);
  /* Content-type */
  psoHdrName = octstr_create("Content-type");
  psoHdrValue = http_header_value(psoHdrList, psoHdrName);
  if(0 == strncasecmp("application/smil", octstr_get_cstr(psoHdrValue), 16)) {
    goto done;
  }
  octstr_format_append(p_psoHdrs, "\r\n");
  octstr_format_append(p_psoHdrs, "\r\n%S;%S", psoHdrName, psoHdrValue);
  octstr_truncate(psoHdrName, 0);
  /* Content-location */
  octstr_append_cstr(psoHdrName, "Content-location");
  psoHdrValue = http_header_value(psoHdrList, psoHdrName);
  octstr_format_append(p_psoHdrs, "\r\n%S;%S", psoHdrName, psoHdrValue);
  octstr_truncate(psoHdrName, 0);
  /**/

  /* формируем имя файла */
  psoFileName = octstr_create(p_pszWebDir);
  if('/' != octstr_get_char(psoFileName, octstr_len(psoFileName) - 1)) {
    octstr_append_char(psoFileName, '/');
  }
  octstr_append(psoFileName, psoHdrValue);
  /* создаем файл */
  iFile = open(octstr_get_cstr(psoFileName), O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  if(0 > iFile) {
    if(errno != EEXIST) {
      iRetVal = 7;
      goto done;
    }
  }
  psoMIMEOStr = mime_entity_body(p_psoMIME);
  octstr_base64_to_binary(psoMIMEOStr);
  if(octstr_len(psoMIMEOStr) != write(iFile, octstr_get_cstr(psoMIMEOStr), octstr_len(psoMIMEOStr))) {
    iRetVal = 8;
    goto done;
  }

  done:
  if(psoHdrName) {
    octstr_destroy(psoHdrName);
  }
  if(psoFileName) {
    octstr_destroy(psoFileName);
  }
  if(0 < iFile) {
    close(iFile);
  }

  return iRetVal;
}
Exemple #8
0
static void exchange_keys(WAPEvent * event, WTLSMachine * wtls_machine)
{
   RSAPublicKey *public_key = NULL;
   Octstr *checking_data = NULL;

   /* The Wap PDUs we have to dispatch */
   wtls_PDU *changeCipherSpecPDU;
   wtls_PDU *finishedPDU;

   /* The PDUs we have to process */
   wtls_Payload *tempPayload;
   wtls_PDU *clientKeyXchgPDU;
   wtls_PDU *changeCipherSpec_incoming_PDU;
   wtls_PDU *finished_incoming_PDU;

   /* For decrypting/encrypting data */
   Octstr *concatenatedRandoms = NULL;
   Octstr *encryptedData = NULL;
   Octstr *decryptedData = NULL;
   Octstr *labelVerify = NULL;
   Octstr *labelMaster = NULL;

   /* Process the incoming event : ClientKeyExchange */
   tempPayload =
       (wtls_Payload *) gwlist_search(event->u.T_Unitdata_Ind.pdu_list,
                  (void *)client_key_exchange,
                  match_handshake_type);

   if (!tempPayload) {
      error(0, "Missing client_key_exchange. Aborting...");
      fatalAlert(event, unexpected_message);
      return;
   }

   /* Keep the data so we can send it back */
   octstr_insert(wtls_machine->handshake_data, tempPayload->data,
            octstr_len(wtls_machine->handshake_data));

   clientKeyXchgPDU = wtls_pdu_unpack(tempPayload, wtls_machine);
   wtls_pdu_dump(clientKeyXchgPDU, 0);

   /* Decrypt the client key exchange PDU */
   encryptedData =
       clientKeyXchgPDU->u.handshake.client_key_exchange->rsa_params->
       encrypted_secret;
   decryptedData =
       wtls_decrypt_key(wtls_machine->key_algorithm, encryptedData);

   if (!decryptedData) {
      error(0,
            "Key Exchange failed. Couldn't decrypt client's secret (%d)."
            " Aborting...", wtls_machine->key_algorithm);
      wtls_pdu_destroy(clientKeyXchgPDU);
      fatalAlert(event, decryption_failed);
      return;
   }
   public_key = wtls_get_rsapublickey();
   pack_int16(decryptedData, octstr_len(decryptedData),
         octstr_len(public_key->rsa_exponent));
   octstr_insert(decryptedData, public_key->rsa_exponent,
            octstr_len(decryptedData));
   pack_int16(decryptedData, octstr_len(decryptedData),
         octstr_len(public_key->rsa_modulus));
   octstr_insert(decryptedData, public_key->rsa_modulus,
            octstr_len(decryptedData));

   /* Concatenate our random data */
   concatenatedRandoms = octstr_cat(wtls_machine->client_random,
                wtls_machine->server_random);

   /* Generate our master secret */
   labelMaster = octstr_create("master secret");
   wtls_machine->master_secret = wtls_calculate_prf(decryptedData,
                      labelMaster,
                      concatenatedRandoms,
                      20, wtls_machine);

   /* Process the incoming event : ChangeCipherSpec */
   tempPayload =
       (wtls_Payload *) gwlist_search(event->u.T_Unitdata_Ind.pdu_list,
                  (void *)ChangeCipher_PDU,
                  match_pdu_type);

   if (!tempPayload) {
      error(0, "Missing change_cipher. Aborting...");
      octstr_destroy(labelMaster);
      octstr_destroy(concatenatedRandoms);
      destroy_rsa_pubkey(public_key);
      octstr_destroy(decryptedData);
      octstr_destroy(encryptedData);
      fatalAlert(event, unexpected_message);
      return;
   }

   changeCipherSpec_incoming_PDU = wtls_pdu_unpack(tempPayload,
                     wtls_machine);
   octstr_dump(wtls_machine->client_write_MAC_secret, 0);

   wtls_pdu_dump(changeCipherSpec_incoming_PDU, 0);

   if (changeCipherSpec_incoming_PDU->u.cc.change == 1) {
      debug("wtls", 0, "Need to decrypt the PDUs from now on...");
      wtls_decrypt_pdu_list(wtls_machine,
                  event->u.T_Unitdata_Ind.pdu_list);
   }

   /* Process the incoming event : Finished */
   tempPayload =
       (wtls_Payload *) gwlist_search(event->u.T_Unitdata_Ind.pdu_list,
                  (void *)finished,
                  match_handshake_type);
   if (!tempPayload) {
      error(0, "Failed to decrypt finished PDU. Aborting...");
      wtls_pdu_destroy(changeCipherSpec_incoming_PDU);
      octstr_destroy(labelMaster);
      octstr_destroy(concatenatedRandoms);
      destroy_rsa_pubkey(public_key);
      octstr_destroy(decryptedData);
      octstr_destroy(encryptedData);
      fatalAlert(event, decrypt_error);
      return;
   }
   finished_incoming_PDU = wtls_pdu_unpack(tempPayload, wtls_machine);
   debug("wtls", 0, "Client Finished PDU:");
   wtls_pdu_dump(finished_incoming_PDU, 0);

   /* Check the verify_data */
   labelVerify = octstr_create("client finished");
   checking_data = wtls_calculate_prf(wtls_machine->master_secret,
                  labelVerify,
                  (Octstr *) wtls_hash(wtls_machine->
                        handshake_data,
                        wtls_machine),
                  12, wtls_machine);

   if (octstr_compare
       (finished_incoming_PDU->u.handshake.finished->verify_data,
        checking_data) == 0) {
      wtls_machine->encrypted = 1;
      debug("wtls", 0, "DATA VERIFICATION OK");
   }

   /* Keep the data so we can send it back in the next message
    * octstr_insert(wtls_machine->handshake_data, tempPayload->data,
    * octstr_len(wtls_machine->handshake_data));
    */
   // temporary fix
   octstr_truncate(tempPayload->data, 15);
   octstr_insert(wtls_machine->handshake_data, tempPayload->data,
            octstr_len(wtls_machine->handshake_data));

   /* Create a new PDU List containing a ChangeCipherSpec and a Finished */
   changeCipherSpecPDU = wtls_pdu_create(ChangeCipher_PDU);
   changeCipherSpecPDU->u.cc.change = 1;
   changeCipherSpecPDU->rlen = 1;
   changeCipherSpecPDU->snMode =
       wtls_machine->sequence_number_mode ? 1 : 0;

   /* Generate our verify data */
   finishedPDU = wtls_pdu_create(Handshake_PDU);
   finishedPDU->u.handshake.msg_type = finished;
   finishedPDU->cipher = 1;
   finishedPDU->rlen = 1;
   finishedPDU->snMode = wtls_machine->sequence_number_mode ? 1 : 0;;
   finishedPDU->u.handshake.finished = gw_malloc(sizeof(Finished));

   octstr_destroy(labelVerify);
   labelVerify = octstr_create("server finished");

   finishedPDU->u.handshake.finished->verify_data = wtls_calculate_prf
       (wtls_machine->master_secret, labelVerify, (Octstr *) wtls_hash
        (wtls_machine->handshake_data, wtls_machine), 12, wtls_machine);

   /* Reset the accumulated Handshake data */
   octstr_destroy(wtls_machine->handshake_data);
   wtls_machine->handshake_data = octstr_create("");

   /* Add the pdus to our list */
   add_pdu(wtls_machine, changeCipherSpecPDU);
   add_pdu(wtls_machine, finishedPDU);

   /* Send it off */
   send_queuedpdus(wtls_machine);

   octstr_destroy(labelMaster);
   octstr_destroy(labelVerify);
   octstr_destroy(decryptedData);
   octstr_destroy(encryptedData);
   octstr_destroy(concatenatedRandoms);

   wtls_pdu_destroy(finished_incoming_PDU);
   wtls_pdu_destroy(changeCipherSpec_incoming_PDU);

   wtls_pdu_destroy(finishedPDU);
   wtls_pdu_destroy(changeCipherSpecPDU);

   octstr_destroy(checking_data);
   destroy_rsa_pubkey(public_key);
}