Пример #1
0
/*
 * Re-escape SMASI ASCII representation of binary data with the
 * original binary data octet string.
 * XXX this may be done by the internal parser routines too.
 */
static void decode_binary_data(Octstr *data) 
{
    long pos = 0;

    while (pos < octstr_len(data)) {
        int check = octstr_get_char(data, pos);

        if (check == ':') {
            Octstr *byte;
            int msb = octstr_get_char(data, pos + 1);
            int lsb = octstr_get_char(data, pos + 2);

            if (msb != -1 && lsb != -1) {
                byte = octstr_create("");
                octstr_append_char(byte, msb);
                octstr_append_char(byte, lsb);

                if (octstr_hex_to_binary(byte) != -1) {
                    /* Do inplace unescaping. */
                    octstr_delete(data, pos, 3);
                    octstr_insert(data, byte, pos);
                } else {
                    error(0, "Malformed binary encoded data.");
                }

                octstr_destroy(byte);
            }
        } 
        pos++;
    } 
}
Пример #2
0
/*
 * Escapes outgoing message body data by replacing occurrences of "special"
 * chars inside the octet string.
 */
static void escape_data(Octstr *data) 
{
    long pos = 0;

    /* This one uses a different approach than the encode and decode
     * functions. Because it is assumed, that only a fraction of the
     * contained chars have to be escaped.
     */
    while (pos < octstr_len(data)) {
        Octstr * escaped = NULL;
        int check = octstr_get_char(data, pos);

        if (check == ':') escaped = colon;
        else if (check == '=') escaped = assign;
        else if (check == ',') escaped = comma;
        else if (check == '\n') escaped = cr;
        else if (check == '\r') escaped = lf;

        if (escaped != NULL) {
            /* If the current char has to be escaped, delete the char from
             * the source string, replace it with the escape sequence, and
             * advance position until after the inserted sequence.
             */
            octstr_delete(data, pos, 1);
            octstr_insert(data, escaped, pos);
            pos += octstr_len(escaped);
        } else {
            /* If not escaped, simply skip the current char. */
            pos++;
        } 
    } 
} 
Пример #3
0
static void flag_date_length(Octstr **token)
{
    Octstr *lenos;

    lenos = octstr_format("%c", octstr_len(*token) - 1);
    octstr_insert(*token, lenos, 1);

    octstr_destroy(lenos);
}
Пример #4
0
/*
 * Add global tokens to the start and to the end of an inline string.
 */ 
void parse_inline_string(Octstr *temp, simple_binary_t **binary)
{
    Octstr *startos;   

    octstr_insert(temp, startos = octstr_format("%c", WBXML_STR_I), 0);
    octstr_destroy(startos);
    octstr_format_append(temp, "%c", WBXML_STR_END);
    parse_octet_string(temp, binary);
}
Пример #5
0
static Octstr *cgw_decode_msg(Octstr* str)
{
    int i;

    /* make \n -> linefeed */
    while ((i = octstr_search(str, octstr_imm("\\n"), 0)) != -1) {
        octstr_delete(str, i, 2);     /* delete "\n" str */
        octstr_insert(str, octstr_imm("\n"), i);
    }
    /* make \r -> carriage return */
    while ((i = octstr_search(str, octstr_imm("\\r"), 0)) != -1) {
        octstr_delete(str, i, 2);     /* delete EOL char */
        octstr_insert(str, octstr_imm("\r"), i);
    }
    /* remove double backslashes */
    while ((i = octstr_search(str, octstr_imm("\\\\"), 0)) != -1) {
        octstr_delete(str, i, 1);
    }

    return str;
}
Пример #6
0
static Octstr *cgw_encode_msg(Octstr* str)
{
    int i;
    char esc = 27;
    char e = 'e';

    /* Euro char (0x80) -> ESC + e. We do this conversion as long as the message 
       length is under 160 chars (the checking could probably be done better) */

    while ((i = octstr_search_char(str, 0x80, 0)) != -1) {    
        octstr_delete(str, i, 1);     /* delete Euro char */
	if (octstr_len(str) < 160) {
	    octstr_insert_data(str, i, &esc, 1);  /* replace with ESC + e */
	    octstr_insert_data(str, i+1, &e, 1);  
	} else {
	    octstr_insert_data(str, i, &e, 1);  /* no room for ESC + e, just replace with an e */
        }
    }


    /* Escape backslash characters */
    while ((i = octstr_search_char(str, '\\', 0)) != -1) {
        octstr_insert(str, octstr_imm("\\"), i);
    }
    /* Remove Line Feed characters */
    while ((i = octstr_search_char(str, CGW_EOL, 0)) != -1) {
        octstr_delete(str, i, 1);     /* delete EOL char */
        octstr_insert(str, octstr_imm("\\n"), i);
    }
    /* Remove Carriage return characters */
    while ((i = octstr_search_char(str, 13, 0)) != -1) {
        octstr_delete(str, i, 1);     /* delete EOL char */
        octstr_insert(str, octstr_imm("\\r"), i);
    }

    return str;
}
Пример #7
0
Octstr *radius_pdu_pack(RADIUS_PDU *pdu)
{
    Octstr *os,*oos;
    Octstr *temp;

    os = octstr_create("");

    gw_assert(pdu != NULL);

    /*
    switch (pdu->type) {
    #define INTEGER(name, octets) p = *(&p);
    #define NULTERMINATED(name, max_octets) p = *(&p);
    #define OCTETS(name, field_giving_octets) \
    	p->field_giving_octets = octstr_len(p->name);
    #define PDU(name, id, fields) \
    	case id: { struct name *p = &pdu->u.name; fields } break;
    #include "radius_pdu.def"
    default:
    	error(0, "Unknown RADIUS_PDU type, internal error while packing.");
    }
    */

    switch (pdu->type) {
    #define INTEGER(name, octets) \
    	append_encoded_integer(os, p->name, octets);
    #define OCTETS(name, field_giving_octets) \
    	octstr_append(os, p->name);
    #define PDU(name, id, fields) \
    	case id: { struct name *p = &pdu->u.name; fields; oos = radius_attr_pack(pdu); \
                   octstr_append(os, oos);octstr_destroy(oos); } break;
    #include "radius_pdu.def"
    default:
    	error(0, "Unknown RADIUS_PDU type, internal error while packing.");
    }

    /* now set PDU length */
    temp = octstr_create("");
    append_encoded_integer(temp, octstr_len(os), 2);
    octstr_delete(os, 2, 2);
    octstr_insert(os, temp, 2);
    octstr_destroy(temp);
    
    return os;
}
Пример #8
0
Octstr *wtls_payload_pack(wtls_Payload *payload) {
        Octstr *data;
        long bitpos, charpos;
        long messageSizePos, sizepos;
        /* Used for length calculations */
        int size;
        
        /* We rely on octstr_set_bits to lengthen our octstr as needed. */
        data = octstr_create("");
        bitpos = 0;
        charpos = 0;
        sizepos = 0;
        
        /* the record field length flag - always present*/
        octstr_set_bits(data, bitpos, 1, 1);
        bitpos += 1;
        /* the sequence number flag */
        octstr_set_bits(data, bitpos, 1, payload->seqnum);
        bitpos += 1;
        /* the cipher usage flag */
        octstr_set_bits(data, bitpos, 1, payload->cipher);
        bitpos += 1;
        /* the reserved bit */
        octstr_set_bits(data, bitpos, 1, payload->reserved);
        bitpos += 1;

        /* set the message type */
        octstr_set_bits(data, bitpos, 4, payload->type);
        bitpos += 4;
        charpos += 1;

        /* set the sequence number if present */
        if(payload->seqnum) {
                charpos = pack_int16(data, charpos, payload->seqnum);
        }

        /* set the WTLS length  */
        charpos = pack_int16(data, charpos, payload->rlen);
        
        /* append the data from the wtls_PDU */
        octstr_insert(data, payload->data, octstr_len(data)); 
        
        return data;
}
Пример #9
0
Octstr *smasi_pdu_pack(SMASI_PDU *pdu)
{
    Octstr *os;
    Octstr *temp;

    os = octstr_create("");

    /*
     * Fix lengths of octet string fields.
     */
    switch (pdu->type) {
    #define NONTERMINATED(name) p = *(&p);
    #define COMATERMINATED(name) p = *(&p);
    #define PDU(name, id, fields) \
        case id: { struct name *p = &pdu->u.name; fields } break;
    #include "smasi_pdu.def"
    default:
        error(0, "Unknown SMASI_PDU type, internal error while packing.");
    }

    switch (pdu->type) {
    #define NONTERMINATED(name) p = *(&p);
    #define COMATERMINATED(name) \
    if (p->name != NULL) { octstr_append_cstr(os, #name); \
    octstr_append_char(os, '='); \
    octstr_append(os, p->name); \
    octstr_append_char(os, ','); }
    #define PDU(name, id, fields) \
        case id: { struct name *p = &pdu->u.name; fields } break;
    #include "smasi_pdu.def"
    default:
        error(0, "Unknown SMASI_PDU type, internal error while packing.");
    }

    octstr_append_char(os, '\n');
    temp = pdu->needs_hyphen ? octstr_create("!") : octstr_create("");
    octstr_append_cstr(temp, pdu->type_name); 
    octstr_append_char(temp, ':');
    octstr_insert(os, temp, 0);
    octstr_destroy(temp);

    return os;
}
Пример #10
0
int radius_authenticate_pdu(RADIUS_PDU *pdu, Octstr **data, Octstr *secret)
{
    int rc = 0;
    Octstr *stream; 
    Octstr *attributes;
    Octstr *digest;

    stream = attributes = digest = NULL;

    /* first extract attributes from raw data, where
     * the first 20 octets are code, idendifier, length
     * and authenticator value as described in RFC2866, sec. 3 */
    if (octstr_len(*data) > 20)
        attributes = octstr_copy(*data, 20, octstr_len(*data)-20);
  
    switch (pdu->type) {
        case 0x04:  /* Accounting-Request, see RFC2866, page 6 */
            stream = octstr_copy(*data, 0, 4);
            octstr_append_data(stream, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16);
            octstr_append(stream, attributes);
            octstr_append(stream, secret);
            digest = md5(stream);
            rc = octstr_compare(pdu->u.Accounting_Request.authenticator, 
                                digest) == 0 ? 1 : 0;
            break;
        case 0x05:  /* Accounting-Response, create Response authenticator */
            stream = octstr_duplicate(*data);
            octstr_append(stream, secret);
            digest = md5(stream);
            octstr_delete(*data, 4, 16);
            octstr_insert(*data, digest, 4);
            break;
        default:
            break;
    }

    octstr_destroy(attributes);
    octstr_destroy(stream);
    octstr_destroy(digest);

    return rc;
}
Пример #11
0
static void add_crs(Octstr *os)
{
    long i;
    Octstr *nos;

    if (os == NULL)
        return;

    nos = octstr_format("%c", '\r');
    i = 0;
    while (i < octstr_len(os)) {
        if (octstr_get_char(os, i) == '\n') {
	    octstr_insert(os, nos, i);
            ++i;
        }
        ++i;
    }

    octstr_destroy(nos);
}
Пример #12
0
static void add_pdu(WTLSMachine * wtls_machine, wtls_PDU * pduToAdd)
{
        int currentLength;
   wtls_Payload *payloadToAdd;
   Octstr *packedPDU;

   /* Update sequence number before encryption */
   wtls_machine->server_seq_num++;

        /* Pack and encrypt the pdu */
   if (!(payloadToAdd = wtls_pdu_pack(pduToAdd, wtls_machine))) {
      wtls_machine->server_seq_num--;
      return;
   }
   if (!payloadToAdd->data) {
      wtls_machine->server_seq_num--;
      wtls_payload_destroy(payloadToAdd);
      return;
   }

   /* Check to see if we've already allocated some memory for the list */
   if (!wtls_machine->packet_to_send)
      wtls_machine->packet_to_send = octstr_create("");

        /* If the pdu is a Handshake pdu, append the Octstr to our wtls_machine's
           exchanged_handshakes Octstr */
   packedPDU =
       wtls_payload_pack(payloadToAdd, wtls_machine->server_seq_num);
   if (pduToAdd->type == ChangeCipher_PDU)
      wtls_machine->server_seq_num = -1;

        /* Add it to our list */
        currentLength = octstr_len(wtls_machine->packet_to_send);
        octstr_insert(wtls_machine->packet_to_send, packedPDU, currentLength);
   wtls_payload_destroy(payloadToAdd);
   octstr_destroy(packedPDU);
}
Пример #13
0
Octstr *smpp_pdu_pack(SMPP_PDU *pdu)
{
    Octstr *os;
    Octstr *temp;

    os = octstr_create("");

    gw_assert(pdu != NULL);

    /*
     * Fix lengths of octet string fields.
     */
    switch (pdu->type) {
    #define OPTIONAL_BEGIN
    #define TLV_INTEGER(name, octets)
    #define TLV_NULTERMINATED(name, max_len)
    #define TLV_OCTETS(name, min_len, max_len)
    #define OPTIONAL_END
    #define INTEGER(name, octets) p = *(&p);
    #define NULTERMINATED(name, max_octets) p = *(&p);
    #define OCTETS(name, field_giving_octets) \
    	p->field_giving_octets = octstr_len(p->name);
    #define PDU(name, id, fields) \
    	case id: { struct name *p = &pdu->u.name; fields } break;
    #include "smpp_pdu.def"
    default:
    	error(0, "Unknown SMPP_PDU type, internal error while packing.");
    }

    switch (pdu->type) {
    #define TL(name, octets) \
        append_encoded_integer(os, SMPP_##name, 2); \
        append_encoded_integer(os, octets, 2);
    #define OPTIONAL_BEGIN
    #define TLV_INTEGER(name, octets) \
        if (p->name != -1) { \
            TL(name, octets); \
            INTEGER(name, octets) \
        }
    #define TLV_NULTERMINATED(name, max_len) \
        if (p->name != NULL) { \
            TL(name, (octstr_len(p->name) > max_len ? max_len : octstr_len(p->name))); \
            NULTERMINATED(name, max_len) \
        }
    #define TLV_OCTETS(name, min_len, max_len) \
        if (p->name != NULL) { \
            unsigned long len = octstr_len(p->name); \
            if (len > max_len || len < min_len) { \
                error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %d - %d) dropped.", \
                    #name, len, min_len, max_len);\
            } else { \
                TL(name, len); \
                octstr_append(os, p->name); \
            } \
        }
    #define OPTIONAL_END
    #define INTEGER(name, octets) \
    	append_encoded_integer(os, p->name, octets);
    #define NULTERMINATED(name, max_octets) \
        if (p->name != NULL) { \
            if (octstr_len(p->name) >= max_octets) { \
                warning(0, "SMPP: PDU element <%s> too long " \
                        "(length is %ld, should be %d)", \
                        #name, octstr_len(p->name), max_octets-1); \
                temp = octstr_copy(p->name, 0, max_octets-1); \
            } else \
                temp = octstr_duplicate(p->name); \
            octstr_append(os, temp); \
            octstr_destroy(temp); \
        } \
        octstr_append_char(os, '\0');
    #define OCTETS(name, field_giving_octets) \
        if (p->name) octstr_append(os, p->name);
    #define PDU(name, id, fields) \
    	case id: { struct name *p = &pdu->u.name; fields } break;
    #include "smpp_pdu.def"
    default:
    	error(0, "Unknown SMPP_PDU type, internal error while packing.");
    }

    temp = octstr_create("");
    append_encoded_integer(temp, octstr_len(os) + 4, 4);
    octstr_insert(os, temp, 0);
    octstr_destroy(temp);

    return os;
}
Пример #14
0
static void prepend_crlf(Octstr **os)
{
    octstr_insert(*os, octstr_imm("\r\n"), 0);
}
Пример #15
0
int main(int argc, char **argv)
{
    output_t outputti = NORMAL_OUT;
    FILE *fp = NULL;
    Octstr *output = NULL;
    Octstr *filename = NULL;
    Octstr *wml_text = NULL;
    Octstr *charset = NULL;
    Octstr *wml_binary = NULL;
    int i, ret = 0, opt, file = 0, zero = 0, numstatus = 0, wml_strict = 1;
    long num = 0;

    /* You can give an wml text file as an argument './wml_tester main.wml' */

    gwlib_init();

    while ((opt = getopt(argc, argv, "hsbzrn:f:c:")) != EOF) {
        switch (opt) {
        case 'h':
            help();
            exit(0);
        case 's':
            if (outputti == NORMAL_OUT)
                outputti = SOURCE_OUT;
            else {
                help();
                exit(0);
            }
            break;
        case 'b':
            if (outputti == NORMAL_OUT)
                outputti = BINARY_OUT;
            else {
                help();
                exit(0);
            }
            break;
        case 'z':
            zero = 1;
            break;
        case 'r':
            wml_strict = 0;
            break;
        case 'n':
            numstatus = octstr_parse_long(&num, octstr_imm(optarg), 0, 0);
            if (numstatus == -1) {
                /* Error in the octstr_parse_long */
                error(num, "Error in the handling of argument to option n");
                help();
                panic(0, "Stopping.");
            }
            break;
        case 'f':
            file = 1;
            filename = octstr_create(optarg);
            fp = fopen(optarg, "a");
            if (fp == NULL)
                panic(0, "Couldn't open output file.");
            break;
        case 'c':
            charset = octstr_create(optarg);
            break;
        case '?':
        default:
            error(0, "Invalid option %c", opt);
            help();
            panic(0, "Stopping.");
        }
    }

    if (optind >= argc) {
        error(0, "Missing arguments.");
        help();
        panic(0, "Stopping.");
    }

    if (outputti == BINARY_OUT)
        log_set_output_level(GW_PANIC);
    wml_init(wml_strict);

    while (optind < argc) {
        wml_text = octstr_read_file(argv[optind]);
        if (wml_text == NULL)
            panic(0, "Couldn't read WML source file.");

        if (zero)
            set_zero(wml_text);

        for (i = 0; i <= num; i++) {
            ret = wml_compile(wml_text, charset, &wml_binary, NULL);
            if (i < num)
                octstr_destroy(wml_binary);
        }
        optind++;

        output = octstr_format("wml_compile returned: %d\n\n", ret);

        if (ret == 0) {
            if (fp == NULL)
                fp = stdout;

            if (outputti != BINARY_OUT) {
                if (outputti == SOURCE_OUT) {
                    octstr_insert(output, wml_text, octstr_len(output));
                    octstr_append_char(output, '\n');
                }

                octstr_append(output, octstr_imm(
                                  "Here's the binary output: \n\n"));
                octstr_print(fp, output);
            }

            if (file && outputti != BINARY_OUT) {
                fclose(fp);
                log_open(octstr_get_cstr(filename), 0, GW_NON_EXCL);
                octstr_dump(wml_binary, 0);
                log_close_all();
                fp = fopen(octstr_get_cstr(filename), "a");
            } else if (outputti != BINARY_OUT)
                octstr_dump(wml_binary, 0);
            else
                octstr_print(fp, wml_binary);

            if (outputti != BINARY_OUT) {
                octstr_destroy(output);
                output = octstr_format("\n And as a text: \n\n");
                octstr_print(fp, output);

                octstr_pretty_print(fp, wml_binary);
                octstr_destroy(output);
                output = octstr_format("\n\n");
                octstr_print(fp, output);
            }
        }

        octstr_destroy(wml_text);
        octstr_destroy(output);
        octstr_destroy(wml_binary);
    }

    if (file) {
        fclose(fp);
        octstr_destroy(filename);
    }

    if (charset != NULL)
        octstr_destroy(charset);

    wml_shutdown();
    gwlib_shutdown();

    return ret;
}
Пример #16
0
/*
 * Populates the corresponding smsbox_by_foobar dictionary hash tables
 */
static void init_smsbox_routes(Cfg *cfg)
{
    CfgGroup *grp;
    List *list, *items;
    Octstr *boxc_id, *smsc_ids, *shortcuts;
    int i, j;

    boxc_id = smsc_ids = shortcuts = NULL;

    list = cfg_get_multi_group(cfg, octstr_imm("smsbox-route")); 
 
    /* loop multi-group "smsbox-route" */
    while (list && (grp = gwlist_extract_first(list)) != NULL) { 
         
        if ((boxc_id = cfg_get(grp, octstr_imm("smsbox-id"))) == NULL) { 
            grp_dump(grp); 
            panic(0,"'smsbox-route' group without valid 'smsbox-id' directive!"); 
        }

        /*
         * If smsc-id is given, then any message comming from the specified
         * smsc-id in the list will be routed to this smsbox instance.
         * If shortcode is given, then any message with receiver number 
         * matching those will be routed to this smsbox instance.
         * If both are given, then only receiver within shortcode originating
         * from smsc-id list will be routed to this smsbox instance. So if both
         * are present then this is a logical AND operation.
         */
        smsc_ids = cfg_get(grp, octstr_imm("smsc-id"));
        shortcuts = cfg_get(grp, octstr_imm("shortcode"));

        /* consider now the 3 possibilities: */
        if (smsc_ids && !shortcuts) {
            /* smsc-id only, so all MO traffic */
            items = octstr_split(smsc_ids, octstr_imm(";"));
            for (i = 0; i < gwlist_len(items); i++) {
                Octstr *item = gwlist_get(items, i);
                octstr_strip_blanks(item);

                debug("bb.boxc",0,"Adding smsbox routing to id <%s> for smsc id <%s>",
                      octstr_get_cstr(boxc_id), octstr_get_cstr(item));

                if (!dict_put_once(smsbox_by_smsc, item, octstr_duplicate(boxc_id)))
                    panic(0, "Routing for smsc-id <%s> already exists!",
                          octstr_get_cstr(item));
            }
            gwlist_destroy(items, octstr_destroy_item);
            octstr_destroy(smsc_ids);
        }
        else if (!smsc_ids && shortcuts) {
            /* shortcode only, so these MOs from all smscs */
            items = octstr_split(shortcuts, octstr_imm(";"));
            for (i = 0; i < gwlist_len(items); i++) {
                Octstr *item = gwlist_get(items, i);
                octstr_strip_blanks(item);

                debug("bb.boxc",0,"Adding smsbox routing to id <%s> for receiver no <%s>",
                      octstr_get_cstr(boxc_id), octstr_get_cstr(item));
            
                if (!dict_put_once(smsbox_by_receiver, item, octstr_duplicate(boxc_id)))
                    panic(0, "Routing for receiver no <%s> already exists!",
                          octstr_get_cstr(item));
            }
            gwlist_destroy(items, octstr_destroy_item);
            octstr_destroy(shortcuts);
        }
        else if (smsc_ids && shortcuts) {
            /* both, so only specified MOs from specified smscs */
            items = octstr_split(shortcuts, octstr_imm(";"));
            for (i = 0; i < gwlist_len(items); i++) {
                List *subitems;
                Octstr *item = gwlist_get(items, i);
                octstr_strip_blanks(item);
                subitems = octstr_split(smsc_ids, octstr_imm(";")); 
                for (j = 0; j < gwlist_len(subitems); j++) {
                    Octstr *subitem = gwlist_get(subitems, j);
                    octstr_strip_blanks(subitem);
                    
                    debug("bb.boxc",0,"Adding smsbox routing to id <%s> "
                          "for receiver no <%s> and smsc id <%s>",
                          octstr_get_cstr(boxc_id), octstr_get_cstr(item),
                          octstr_get_cstr(subitem));
            
                    /* construct the dict key '<shortcode>:<smsc-id>' */
                    octstr_insert(subitem, item, 0);
                    octstr_insert_char(subitem, octstr_len(item), ':');
                    if (!dict_put_once(smsbox_by_smsc_receiver, subitem, octstr_duplicate(boxc_id)))
                        panic(0, "Routing for receiver:smsc <%s> already exists!",
                              octstr_get_cstr(subitem));
                }
                gwlist_destroy(subitems, octstr_destroy_item);
            }
            gwlist_destroy(items, octstr_destroy_item);
            octstr_destroy(shortcuts);
        }
        octstr_destroy(boxc_id);
    }

    gwlist_destroy(list, NULL);
}
Пример #17
0
Octstr *smpp_pdu_pack(Octstr *smsc_id, SMPP_PDU *pdu)
{
    Octstr *os;
    Octstr *temp;

    os = octstr_create("");

    gw_assert(pdu != NULL);

    /*
     * Fix lengths of octet string fields.
     */
    switch (pdu->type) {
    #define OPTIONAL_BEGIN
    #define TLV_INTEGER(name, octets)
    #define TLV_NULTERMINATED(name, max_len)
    #define TLV_OCTETS(name, min_len, max_len)
    #define OPTIONAL_END
    #define INTEGER(name, octets) p = *(&p);
    #define NULTERMINATED(name, max_octets) p = *(&p);
    #define OCTETS(name, field_giving_octets) \
    	p->field_giving_octets = octstr_len(p->name);
    #define PDU(name, id, fields) \
    	case id: { struct name *p = &pdu->u.name; fields } break;
    #include "smpp_pdu.def"
    default:
    	error(0, "Unknown SMPP_PDU type, internal error while packing.");
    }

    switch (pdu->type) {
    #define TL(name, octets) \
        append_encoded_integer(os, SMPP_##name, 2); \
        append_encoded_integer(os, octets, 2);
    #define OPTIONAL_BEGIN
    #define TLV_INTEGER(name, octets) \
        if (p->name >= 0) { \
            TL(name, octets); \
            INTEGER(name, octets) \
        }
    #define TLV_NULTERMINATED(name, max_len) \
        if (p->name != NULL) { \
            TL(name, (octstr_len(p->name) > max_len ? max_len : octstr_len(p->name) + 1)); \
            NULTERMINATED(name, max_len) \
        }
    #define TLV_OCTETS(name, min_len, max_len) \
        if (p->name != NULL) { \
            unsigned long len = octstr_len(p->name); \
            if (len > max_len || len < min_len) { \
                error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %d - %d) dropped.", \
                    #name, len, min_len, max_len);\
            } else { \
                TL(name, len); \
                octstr_append(os, p->name); \
            } \
        }
    #define OPTIONAL_END \
        if (p->tlv != NULL) { \
            Octstr *key; \
            List *keys; \
            struct smpp_tlv *tlv; \
            keys = dict_keys(p->tlv); \
            while(keys != NULL && (key = gwlist_extract_first(keys)) != NULL) { \
                tlv = smpp_tlv_get_by_name(smsc_id, key); \
                if (tlv == NULL) { \
                    error(0, "SMPP: Unknown TLV `%s', don't send.", octstr_get_cstr(key)); \
                    octstr_destroy(key); \
                    continue; \
                } \
                switch(tlv->type) { \
                case SMPP_TLV_INTEGER: { \
                    long val = atol(octstr_get_cstr(dict_get(p->tlv, key))); \
                    append_encoded_integer(os, tlv->tag, 2); \
                    append_encoded_integer(os, tlv->length, 2); \
                    append_encoded_integer(os, val, tlv->length); \
                    break; \
                } \
                case SMPP_TLV_OCTETS: \
                case SMPP_TLV_NULTERMINATED: { \
                    Octstr *val = dict_get(p->tlv, key); \
                    unsigned long len = octstr_len(val); \
                    if (len > tlv->length) { \
                        error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %ld) dropped.", \
                              octstr_get_cstr(key), len, tlv->length);\
                        octstr_destroy(key); \
                        continue; \
                    } \
                    append_encoded_integer(os, tlv->tag, 2); \
                    if (tlv->type == SMPP_TLV_NULTERMINATED) \
                        append_encoded_integer(os, len + 1, 2); \
                    else \
                        append_encoded_integer(os, len, 2); \
                    octstr_append(os, val); \
                    if (tlv->type == SMPP_TLV_NULTERMINATED) \
                        octstr_append_char(os, '\0'); \
                    break; \
                } \
                default: \
                    panic(0, "SMPP: Internal error, unknown configured TLV type %d.", tlv->type); \
                    break; \
                } \
                octstr_destroy(key); \
            } \
            gwlist_destroy(keys, octstr_destroy_item); \
        }
    #define INTEGER(name, octets) \
        append_encoded_integer(os, p->name, octets);
    #define NULTERMINATED(name, max_octets) \
        if (p->name != NULL) { \
            if (octstr_len(p->name) >= max_octets) { \
                warning(0, "SMPP: PDU element <%s> too long " \
                        "(length is %ld, should be %d)", \
                        #name, octstr_len(p->name), max_octets-1); \
                temp = octstr_copy(p->name, 0, max_octets-1); \
            } else \
                temp = octstr_duplicate(p->name); \
            octstr_append(os, temp); \
            octstr_destroy(temp); \
        } \
        octstr_append_char(os, '\0');
    #define OCTETS(name, field_giving_octets) \
        if (p->name) octstr_append(os, p->name);
    #define PDU(name, id, fields) \
        case id: { struct name *p = &pdu->u.name; fields } break;
    #include "smpp_pdu.def"
    default:
        error(0, "Unknown SMPP_PDU type 0x%08lx, internal error while packing.", pdu->type);
        break;
    }

    temp = octstr_create("");
    append_encoded_integer(temp, octstr_len(os) + 4, 4);
    octstr_insert(os, temp, 0);
    octstr_destroy(temp);

    return os;
}
Пример #18
0
void output_octet_string(Octstr *os, simple_binary_t **sibxml)
{
    octstr_insert((*sibxml)->binary, os, octstr_len((*sibxml)->binary));
}
Пример #19
0
static void clientHello(WAPEvent * event, WTLSMachine * wtls_machine)
{
   /* The Wap event we have to dispatch */
   WAPEvent *res;
   wtls_Payload *tempPayload;
   wtls_PDU *clientHelloPDU;
   CipherSuite *ciphersuite;
   int randomCounter, algo;

   tempPayload =
       (wtls_Payload *) gwlist_search(event->u.T_Unitdata_Ind.pdu_list,
                  (void *)client_hello,
                  match_handshake_type);
   if (!tempPayload) {
      error(0, "Illegal PDU while waiting for a ClientHello");
      fatalAlert(event, unexpected_message);
      return;
   }
   clientHelloPDU = wtls_pdu_unpack(tempPayload, wtls_machine);

   /* Store the client's random value - use pack for simplicity */
   wtls_machine->client_random = octstr_create("");
   randomCounter = pack_int32(wtls_machine->client_random, 0,
               clientHelloPDU->u.handshake.client_hello->
               random->gmt_unix_time);
   octstr_insert(wtls_machine->client_random,
            clientHelloPDU->u.handshake.client_hello->random->
            random_bytes, randomCounter);

   /* Select the ciphersuite from the supplied list */
   ciphersuite =
       wtls_choose_ciphersuite(clientHelloPDU->u.handshake.client_hello->
                ciphersuites);
   if (!ciphersuite) {
      error(0, "Couldn't agree on encryption cipher. Aborting");
      wtls_pdu_destroy(clientHelloPDU);
      fatalAlert(event, handshake_failure);
      return;
   }
   /* Set the relevant values in the wtls_machine and PDU structure */
   wtls_machine->bulk_cipher_algorithm = ciphersuite->bulk_cipher_algo;
   wtls_machine->mac_algorithm = ciphersuite->mac_algo;

   /* Generate a SEC_Create_Res event, and pass it back into the queue */
   res = wap_event_create(SEC_Create_Res);
   res->u.SEC_Create_Res.addr_tuple =
       wap_addr_tuple_duplicate(event->u.T_Unitdata_Ind.addr_tuple);
   res->u.SEC_Create_Res.bulk_cipher_algo = ciphersuite->bulk_cipher_algo;
   res->u.SEC_Create_Res.mac_algo = ciphersuite->mac_algo;
   res->u.SEC_Create_Res.client_key_id = wtls_choose_clientkeyid
       (clientHelloPDU->u.handshake.client_hello->client_key_ids, &algo);
   if (!res->u.SEC_Create_Res.client_key_id) {
      error(0, "Couldn't agree on key exchange protocol. Aborting");
      wtls_pdu_destroy(clientHelloPDU);
      wap_event_destroy(res);
      fatalAlert(event, unknown_key_id);
      return;
   }
   wtls_machine->key_algorithm = algo;

   /* Set the sequence number mode in both the machine and the outgoing packet */
   res->u.SEC_Create_Res.snmode =
       wtls_choose_snmode(clientHelloPDU->u.handshake.client_hello->
                snmode);
   wtls_machine->sequence_number_mode = res->u.SEC_Create_Res.snmode;

   /* Set the key refresh mode in both the machine and the outgoing packet */
   res->u.SEC_Create_Res.krefresh =
       clientHelloPDU->u.handshake.client_hello->krefresh;
   wtls_machine->key_refresh = res->u.SEC_Create_Res.krefresh;
   /* Global refresh variable */
   debug("wtls", 0, "clientHello ~> Accepted refresh = %d, refresh_rate = "
         "%d", wtls_machine->key_refresh, 1 << wtls_machine->key_refresh);

   /* Keep the data so we can send it back in EXCHANGE
    * temporary - needs to delete old one if exists !
    * wtls_machine->handshake_data = octstr_create("");
    */
   if (wtls_machine->handshake_data)
      octstr_destroy(wtls_machine->handshake_data);
   wtls_machine->handshake_data = octstr_create("");
   octstr_append(wtls_machine->handshake_data, tempPayload->data);

   debug("wtls", 0, "clientHello ~> Dispatching SEC_Create_Res event");
   wtls_pdu_destroy(clientHelloPDU);
   wtls_dispatch_event(res);
}
Пример #20
0
static void serverHello(WAPEvent * event, WTLSMachine * wtls_machine)
{
   WAPEvent *req;
   wtls_PDU *serverHelloPDU;
//   wtls_PDU* certificatePDU;
   Random *tempRandom;
/*   List *certList;
   Certificate *cert;
*/ int randomCounter = 0;

   /* Our serverHello */
   serverHelloPDU = wtls_pdu_create(Handshake_PDU);
   serverHelloPDU->rlen = 1;
   serverHelloPDU->snMode = wtls_machine->sequence_number_mode ? 1 : 0;
   serverHelloPDU->u.handshake.msg_type = server_hello;
   serverHelloPDU->u.handshake.server_hello =
       (ServerHello *) gw_malloc(sizeof(ServerHello));

   /* Set our server version */
   serverHelloPDU->u.handshake.server_hello->serverversion = 1;

   /* Get a suitably random number - store it in both the machine structure and outgoing PDU */
   tempRandom = wtls_get_random();
   wtls_machine->server_random = octstr_create("");
   randomCounter =
       pack_int32(wtls_machine->server_random, 0,
             tempRandom->gmt_unix_time);
   octstr_insert(wtls_machine->server_random, tempRandom->random_bytes,
            octstr_len(wtls_machine->server_random));

   serverHelloPDU->u.handshake.server_hello->random = tempRandom;

   /* At the moment, we don't support session caching, so tell them to forget about caching us */
   serverHelloPDU->u.handshake.server_hello->session_id =
       octstr_format("%llu", wtls_machine->mid);

   /* We need to select an appropriate mechanism here from the ones listed */
   serverHelloPDU->u.handshake.server_hello->client_key_id =
       event->u.SEC_Create_Res.client_key_id;

   /* Get our ciphersuite details */
   serverHelloPDU->u.handshake.server_hello->ciphersuite = (CipherSuite *)
       gw_malloc(sizeof(CipherSuite));
   serverHelloPDU->u.handshake.server_hello->ciphersuite->bulk_cipher_algo
       = event->u.SEC_Create_Res.bulk_cipher_algo;
   serverHelloPDU->u.handshake.server_hello->ciphersuite->mac_algo =
       event->u.SEC_Create_Res.mac_algo;
   serverHelloPDU->u.handshake.server_hello->comp_method = null_comp;

   /* We need to confirm the client's choice, or if they haven't 
    * specified one, select one ourselves 
    */
   serverHelloPDU->u.handshake.server_hello->snmode =
       event->u.SEC_Create_Res.snmode;

   /* We need to either confirm the client's choice of key refresh rate, or choose a lower rate */
   serverHelloPDU->u.handshake.server_hello->krefresh =
       event->u.SEC_Create_Res.krefresh;

   /* Add the PDUsto the server's outgoing list  */
   add_pdu(wtls_machine, serverHelloPDU);
   wtls_pdu_destroy(serverHelloPDU);

   /* Generate and dispatch a SEC_Exchange_Req or maybe a SEC_Commit_Req */
   req = wap_event_create(SEC_Exchange_Req);
   req->u.SEC_Exchange_Req.addr_tuple =
       wap_addr_tuple_duplicate(event->u.T_Unitdata_Ind.addr_tuple);
   wtls_dispatch_event(req);
   debug("wtls", 0, "serverHello ~> Dispatching SEC_Exchange_Req event");
}
Пример #21
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);
}