diff -r 000000000000 -r 6474c204b198 dom/wappush/src/gonk/CpPduHelper.jsm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/wappush/src/gonk/CpPduHelper.jsm Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,485 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +let WSP = {}; +Cu.import("resource://gre/modules/WspPduHelper.jsm", WSP); +let WBXML = {}; +Cu.import("resource://gre/modules/WbxmlPduHelper.jsm", WBXML); + +Cu.import("resource://services-crypto/utils.js"); +Cu.import("resource://services-common/utils.js"); + +// set to true to see debug messages +let DEBUG = WBXML.DEBUG_ALL | false; + +/** + * Public identifier for CP + * + * @see http://technical.openmobilealliance.org/tech/omna/omna-wbxml-public-docid.aspx + */ +const PUBLIC_IDENTIFIER_CP = "-//WAPFORUM//DTD PROV 1.0//EN"; + +this.PduHelper = { + + /** + * @param data + * A wrapped object containing raw PDU data. + * @param contentType + * Content type of incoming CP message, should be "text/vnd.wap.connectivity-xml" + * or "application/vnd.wap.connectivity-wbxml". + * + * @return A message object containing attribute content and contentType. + * |content| will contain string of decoded CP message if successfully + * decoded, or raw data if failed. + * |contentType| will be string representing corresponding type of + * content. + */ + parse: function parse_cp(data, contentType) { + // We only need content and contentType + let msg = { + contentType: contentType + }; + + /** + * Message is compressed by WBXML, decode into string. + * + * @see WAP-192-WBXML-20010725-A + */ + if (contentType === "application/vnd.wap.connectivity-wbxml") { + let appToken = { + publicId: PUBLIC_IDENTIFIER_CP, + tagTokenList: CP_TAG_FIELDS, + attrTokenList: CP_ATTRIBUTE_FIELDS, + valueTokenList: CP_VALUE_FIELDS, + globalTokenOverride: null + } + + try { + let parseResult = WBXML.PduHelper.parse(data, appToken, msg); + msg.content = parseResult.content; + msg.contentType = "text/vnd.wap.connectivity-xml"; + } catch (e) { + // Provide raw data if we failed to parse. + msg.content = data.array; + } + + return msg; + } + + /** + * Message is plain text, transform raw to string. + */ + try { + let stringData = WSP.Octet.decodeMultiple(data, data.array.length); + msg.content = WSP.PduHelper.decodeStringContent(stringData, "UTF-8"); + } catch (e) { + // Provide raw data if we failed to parse. + msg.content = data.array; + } + return msg; + + } +}; + +/** + * SEC type values + * + * @see WAP-183-ProvCont-20010724-A, clause 5.3 + */ +const AUTH_SEC_TYPE = (function () { + let names = {}; + function add(name, number) { + names[number] = name; + } + + add("NETWPIN", 0); + add("USERPIN", 1); + add("USERNETWPIN", 2); + add("USERPINMAC", 3); + + return names; +})(); + +this.Authenticator = { + /** + * Format IMSI string into GSM format + * + * @param imsi + * IMSI string + * + * @return IMSI in GSM format as string object + */ + formatImsi: function formatImsi(imsi) { + let parityByte = ((imsi.length & 1) ? 9 : 1); + + // Make sure length of IMSI is 15 digits. + // @see GSM 11.11, clause 10.2.2 + let i = 0; + for (i = 15 - imsi.length; i > 0; i--) { + imsi += "F"; + } + + // char-by-char atoi + let imsiValue = []; + imsiValue.push(parityByte); + for (i = 0; i < imsi.length; i++) { + imsiValue.push(parseInt(imsi.substr(i, 1), 10)); + } + + // encoded IMSI + let imsiEncoded = ""; + for (i = 0; i < imsiValue.length; i += 2) { + imsiEncoded += String.fromCharCode(imsiValue[i] | (imsiValue[i+1] << 4)); + } + + return imsiEncoded; + }, + + /** + * Perform HMAC check + * + * @param wbxml + * Uint8 typed array of raw WBXML data. + * @param key + * key string for HMAC check. + * @param mac + * Expected MAC value. + * + * @return true for valid, false for invalid. + */ + isValid: function isValid(wbxml, key, mac) { + let hasher = CryptoUtils.makeHMACHasher(Ci.nsICryptoHMAC.SHA1, + CryptoUtils.makeHMACKey(key)); + hasher.update(wbxml, wbxml.length); + let result = CommonUtils.bytesAsHex(hasher.finish(false)).toUpperCase(); + return mac == result; + }, + + /** + * Perform HMAC authentication. + * + * @param wbxml + * Uint8 typed array of raw WBXML data. + * @param sec + * Security method for HMAC check. + * @param mac + * Expected MAC value. + * @param getNetworkPin + * Callback function for getting network pin. + * + * @return true for valid, false for invalid. + */ + check: function check_hmac(wbxml, sec, mac, getNetworkPin) { + // No security set. + if (sec == null || !mac) { + return null; + } + + let authInfo = { + pass: false, + checked: false, + sec: AUTH_SEC_TYPE[sec], + mac: mac.toUpperCase(), + data: wbxml + }; + + switch (authInfo.sec) { + case "NETWPIN": + let key = getNetworkPin(); + authInfo.pass = this.isValid(wbxml, key, authInfo.mac); + authInfo.checked = true; + return authInfo; + + case "USERPIN": + case "USERPINMAC": + // We can't check without USER PIN + return authInfo; + + case "USERNETWPIN": + default: + return null; + } + } +}; + +/** + * Tag tokens + * + * @see OMA-WAP-TS-ProvCont-V1_1-20090421-C, clause 7.1 + */ +const CP_TAG_FIELDS = (function () { + let names = {}; + function add(name, codepage, number) { + let entry = { + name: name, + number: number, + }; + if (!names[codepage]) { + names[codepage] = {}; + } + names[codepage][number] = entry; + } + + // Code page 0 + add("wap-provisioningdoc", 0, 0x05); + add("characteristic", 0, 0x06); + add("parm", 0, 0x07); + // Code page 1 + add("characteristic", 1, 0x06); + add("parm", 1, 0x07); + + return names; +})(); + +/** + * Attribute Tokens + * + * @see OMA-WAP-TS-ProvCont-V1_1-20090421-C, clause 7.2 + */ +const CP_ATTRIBUTE_FIELDS = (function () { + let names = {}; + function add(name, value, codepage, number) { + let entry = { + name: name, + value: value, + number: number, + }; + if (!names[codepage]) { + names[codepage] = {}; + } + names[codepage][number] = entry; + } + + // Code page 0 + add("name", "", 0, 0x05); + add("value", "", 0, 0x06); + add("name", "NAME", 0, 0x07); + add("name", "NAP-ADDRESS", 0, 0x08); + add("name", "NAP-ADDRTYPE", 0, 0x09); + add("name", "CALLTYPE", 0, 0x0A); + add("name", "VALIDUNTIL", 0, 0x0B); + add("name", "AUTHTYPE", 0, 0x0C); + add("name", "AUTHNAME", 0, 0x0D); + add("name", "AUTHSECRET", 0, 0x0E); + add("name", "LINGER", 0, 0x0F); + add("name", "BEARER", 0, 0x10); + add("name", "NAPID", 0, 0x11); + add("name", "COUNTRY", 0, 0x12); + add("name", "NETWORK", 0, 0x13); + add("name", "INTERNET", 0, 0x14); + add("name", "PROXY-ID", 0, 0x15); + add("name", "PROXY-PROVIDER-ID", 0, 0x16); + add("name", "DOMAIN", 0, 0x17); + add("name", "PROVURL", 0, 0x18); + add("name", "PXAUTH-TYPE", 0, 0x19); + add("name", "PXAUTH-ID", 0, 0x1A); + add("name", "PXAUTH-PW", 0, 0x1B); + add("name", "STARTPAGE", 0, 0x1C); + add("name", "BASAUTH-ID", 0, 0x1D); + add("name", "BASAUTH-PW", 0, 0x1E); + add("name", "PUSHENABLED", 0, 0x1F); + add("name", "PXADDR", 0, 0x20); + add("name", "PXADDRTYPE", 0, 0x21); + add("name", "TO-NAPID", 0, 0x22); + add("name", "PORTNBR", 0, 0x23); + add("name", "SERVICE", 0, 0x24); + add("name", "LINKSPEED", 0, 0x25); + add("name", "DNLINKSPEED", 0, 0x26); + add("name", "LOCAL-ADDR", 0, 0x27); + add("name", "LOCAL-ADDRTYPE", 0, 0x28); + add("name", "CONTEXT-ALLOW", 0, 0x29); + add("name", "TRUST", 0, 0x2A); + add("name", "MASTER", 0, 0x2B); + add("name", "SID", 0, 0x2C); + add("name", "SOC", 0, 0x2D); + add("name", "WSP-VERSION", 0, 0x2E); + add("name", "PHYSICAL-PROXY-ID", 0, 0x2F); + add("name", "CLIENT-ID", 0, 0x30); + add("name", "DELIVERY-ERR-PDU", 0, 0x31); + add("name", "DELIVERY-ORDER", 0, 0x32); + add("name", "TRAFFIC-CLASS", 0, 0x33); + add("name", "MAX-SDU-SIZE", 0, 0x34); + add("name", "MAX-BITRATE-UPLINK", 0, 0x35); + add("name", "MAX-BITRATE-DNLINK", 0, 0x36); + add("name", "RESIDUAL-BER", 0, 0x37); + add("name", "SDU-ERROR-RATIO", 0, 0x38); + add("name", "TRAFFIC-HANDL-PRIO", 0, 0x39); + add("name", "TRANSFER-DELAY", 0, 0x3A); + add("name", "GUARANTEED-BITRATE-UPLINK", 0, 0x3B); + add("name", "GUARANTEED-BITRATE-DNLINK", 0, 0x3C); + add("name", "PXADDR-FQDN", 0, 0x3D); + add("name", "PROXY-PW", 0, 0x3E); + add("name", "PPGAUTH-TYPE", 0, 0x3F); + add("version", "", 0, 0x45); + add("version", "1.0", 0, 0x46); + add("name", "PULLENABLED", 0, 0x47); + add("name", "DNS-ADDR", 0, 0x48); + add("name", "MAX-NUM-RETRY", 0, 0x49); + add("name", "FIRST-RETRY-TIMEOUT", 0, 0x4A); + add("name", "REREG-THRESHOLD", 0, 0x4B); + add("name", "T-BIT", 0, 0x4C); + add("name", "AUTH-ENTITY", 0, 0x4E); + add("name", "SPI", 0, 0x4F); + add("type", "", 0, 0x50); + add("type", "PXLOGICAL", 0, 0x51); + add("type", "PXPHYSICAL", 0, 0x52); + add("type", "PORT", 0, 0x53); + add("type", "VALIDITY", 0, 0x54); + add("type", "NAPDEF", 0, 0x55); + add("type", "BOOTSTRAP", 0, 0x56); +/* + * Mark out VENDORCONFIG so if it is contained in message, parse + * will failed and raw data is returned. + */ +// add("type", "VENDORCONFIG", 0, 0x57); + add("type", "CLIENTIDENTITY", 0, 0x58); + add("type", "PXAUTHINFO", 0, 0x59); + add("type", "NAPAUTHINFO", 0, 0x5A); + add("type", "ACCESS", 0, 0x5B); + + // Code page 1 + add("name", "", 1, 0x05); + add("value", "", 1, 0x06); + add("name", "NAME", 1, 0x07); + add("name", "INTERNET", 1, 0x14); + add("name", "STARTPAGE", 1, 0x1C); + add("name", "TO-NAPID", 1, 0x22); + add("name", "PORTNBR", 1, 0x23); + add("name", "SERVICE", 1, 0x24); + add("name", "AACCEPT", 1, 0x2E); + add("name", "AAUTHDATA", 1, 0x2F); + add("name", "AAUTHLEVEL", 1, 0x30); + add("name", "AAUTHNAME", 1, 0x31); + add("name", "AAUTHSECRET", 1, 0x32); + add("name", "AAUTHTYPE", 1, 0x33); + add("name", "ADDR", 1, 0x34); + add("name", "ADDRTYPE", 1, 0x35); + add("name", "APPID", 1, 0x36); + add("name", "APROTOCOL", 1, 0x37); + add("name", "PROVIDER-ID", 1, 0x38); + add("name", "TO-PROXY", 1, 0x39); + add("name", "URI", 1, 0x3A); + add("name", "RULE", 1, 0x3B); + add("type", "", 1, 0x50); + add("type", "PORT", 1, 0x53); + add("type", "APPLICATION", 1, 0x55); + add("type", "APPADDR", 1, 0x56); + add("type", "APPAUTH", 1, 0x57); + add("type", "CLIENTIDENTITY", 1, 0x58); + add("type", "RESOURCE", 1, 0x59); + + return names; +})(); + +/** + * Value Tokens + * + * @see OMA-WAP-TS-ProvCont-V1_1-20090421-C, clause 7.3 + */ +const CP_VALUE_FIELDS = (function () { + let names = {}; + function add(value, codepage, number) { + let entry = { + value: value, + number: number, + }; + if (!names[codepage]) { + names[codepage] = {}; + } + names[codepage][number] = entry; + } + + // Code page 0 + add("IPV4", 0, 0x85); + add("IPV6", 0, 0x86); + add("E164", 0, 0x87); + add("ALPHA", 0, 0x88); + add("APN", 0, 0x89); + add("SCODE", 0, 0x8A); + add("TETRA-ITSI", 0, 0x8B); + add("MAN", 0, 0x8C); + add("ANALOG-MODEM", 0, 0x90); + add("V.120", 0, 0x91); + add("V.110", 0, 0x92); + add("X.31", 0, 0x93); + add("BIT-TRANSPARENT", 0, 0x94); + add("DIRECT-ASYNCHRONOUS-DATA-SERVICE", 0, 0x95); + add("PAP", 0, 0x9A); + add("CHAP", 0, 0x9B); + add("HTTP-BASIC", 0, 0x9C); + add("HTTP-DIGEST", 0, 0x9D); + add("WTLS-SS", 0, 0x9E); + add("MD5", 0, 0x9F); // Added in OMA, 7.3.3 + add("GSM-USSD", 0, 0xA2); + add("GSM-SMS", 0, 0xA3); + add("ANSI-136-GUTS", 0, 0xA4); + add("IS-95-CDMA-SMS", 0, 0xA5); + add("IS-95-CDMA-CSD", 0, 0xA6); + add("IS-95-CDMA-PAC", 0, 0xA7); + add("ANSI-136-CSD", 0, 0xA8); + add("ANSI-136-GPRS", 0, 0xA9); + add("GSM-CSD", 0, 0xAA); + add("GSM-GPRS", 0, 0xAB); + add("AMPS-CDPD", 0, 0xAC); + add("PDC-CSD", 0, 0xAD); + add("PDC-PACKET", 0, 0xAE); + add("IDEN-SMS", 0, 0xAF); + add("IDEN-CSD", 0, 0xB0); + add("IDEN-PACKET", 0, 0xB1); + add("FLEX/REFLEX", 0, 0xB2); + add("PHS-SMS", 0, 0xB3); + add("PHS-CSD", 0, 0xB4); + add("TETRA-SDS", 0, 0xB5); + add("TETRA-PACKET", 0, 0xB6); + add("ANSI-136-GHOST", 0, 0xB7); + add("MOBITEX-MPAK", 0, 0xB8); + add("CDMA2000-1X-SIMPLE-IP", 0, 0xB9); // Added in OMA, 7.3.4 + add("CDMA2000-1X-MOBILE-IP", 0, 0xBA); // Added in OMA, 7.3.4 + add("AUTOBOUDING", 0, 0xC5); + add("CL-WSP", 0, 0xCA); + add("CO-WSP", 0, 0xCB); + add("CL-SEC-WSP", 0, 0xCC); + add("CO-SEC-WSP", 0, 0xCD); + add("CL-SEC-WTA", 0, 0xCE); + add("CO-SEC-WTA", 0, 0xCF); + add("OTA-HTTP-TO", 0, 0xD0); // Added in OMA, 7.3.6 + add("OTA-HTTP-TLS-TO", 0, 0xD1); // Added in OMA, 7.3.6 + add("OTA-HTTP-PO", 0, 0xD2); // Added in OMA, 7.3.6 + add("OTA-HTTP-TLS-PO", 0, 0xD3); // Added in OMA, 7.3.6 + add("AAA", 0, 0xE0); // Added in OMA, 7.3.8 + add("HA", 0, 0xE1); // Added in OMA, 7.3.8 + + // Code page 1 + add("IPV6", 1, 0x86); + add("E164", 1, 0x87); + add("ALPHA", 1, 0x88); + add("APPSRV", 1, 0x8D); + add("OBEX", 1, 0x8E); + add(",", 1, 0x90); + add("HTTP-", 1, 0x91); + add("BASIC", 1, 0x92); + add("DIGEST", 1, 0x93); + + return names; +})(); + +let debug; +if (DEBUG) { + debug = function (s) { + dump("-$- CpPduHelper: " + s + "\n"); + }; +} else { + debug = function (s) {}; +} + +this.EXPORTED_SYMBOLS = [ + // Parser + "PduHelper", + // HMAC Authenticator + "Authenticator", +];