1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/wappush/src/gonk/CpPduHelper.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,485 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +"use strict"; 1.9 + 1.10 +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; 1.11 + 1.12 +let WSP = {}; 1.13 +Cu.import("resource://gre/modules/WspPduHelper.jsm", WSP); 1.14 +let WBXML = {}; 1.15 +Cu.import("resource://gre/modules/WbxmlPduHelper.jsm", WBXML); 1.16 + 1.17 +Cu.import("resource://services-crypto/utils.js"); 1.18 +Cu.import("resource://services-common/utils.js"); 1.19 + 1.20 +// set to true to see debug messages 1.21 +let DEBUG = WBXML.DEBUG_ALL | false; 1.22 + 1.23 +/** 1.24 + * Public identifier for CP 1.25 + * 1.26 + * @see http://technical.openmobilealliance.org/tech/omna/omna-wbxml-public-docid.aspx 1.27 + */ 1.28 +const PUBLIC_IDENTIFIER_CP = "-//WAPFORUM//DTD PROV 1.0//EN"; 1.29 + 1.30 +this.PduHelper = { 1.31 + 1.32 + /** 1.33 + * @param data 1.34 + * A wrapped object containing raw PDU data. 1.35 + * @param contentType 1.36 + * Content type of incoming CP message, should be "text/vnd.wap.connectivity-xml" 1.37 + * or "application/vnd.wap.connectivity-wbxml". 1.38 + * 1.39 + * @return A message object containing attribute content and contentType. 1.40 + * |content| will contain string of decoded CP message if successfully 1.41 + * decoded, or raw data if failed. 1.42 + * |contentType| will be string representing corresponding type of 1.43 + * content. 1.44 + */ 1.45 + parse: function parse_cp(data, contentType) { 1.46 + // We only need content and contentType 1.47 + let msg = { 1.48 + contentType: contentType 1.49 + }; 1.50 + 1.51 + /** 1.52 + * Message is compressed by WBXML, decode into string. 1.53 + * 1.54 + * @see WAP-192-WBXML-20010725-A 1.55 + */ 1.56 + if (contentType === "application/vnd.wap.connectivity-wbxml") { 1.57 + let appToken = { 1.58 + publicId: PUBLIC_IDENTIFIER_CP, 1.59 + tagTokenList: CP_TAG_FIELDS, 1.60 + attrTokenList: CP_ATTRIBUTE_FIELDS, 1.61 + valueTokenList: CP_VALUE_FIELDS, 1.62 + globalTokenOverride: null 1.63 + } 1.64 + 1.65 + try { 1.66 + let parseResult = WBXML.PduHelper.parse(data, appToken, msg); 1.67 + msg.content = parseResult.content; 1.68 + msg.contentType = "text/vnd.wap.connectivity-xml"; 1.69 + } catch (e) { 1.70 + // Provide raw data if we failed to parse. 1.71 + msg.content = data.array; 1.72 + } 1.73 + 1.74 + return msg; 1.75 + } 1.76 + 1.77 + /** 1.78 + * Message is plain text, transform raw to string. 1.79 + */ 1.80 + try { 1.81 + let stringData = WSP.Octet.decodeMultiple(data, data.array.length); 1.82 + msg.content = WSP.PduHelper.decodeStringContent(stringData, "UTF-8"); 1.83 + } catch (e) { 1.84 + // Provide raw data if we failed to parse. 1.85 + msg.content = data.array; 1.86 + } 1.87 + return msg; 1.88 + 1.89 + } 1.90 +}; 1.91 + 1.92 +/** 1.93 + * SEC type values 1.94 + * 1.95 + * @see WAP-183-ProvCont-20010724-A, clause 5.3 1.96 + */ 1.97 +const AUTH_SEC_TYPE = (function () { 1.98 + let names = {}; 1.99 + function add(name, number) { 1.100 + names[number] = name; 1.101 + } 1.102 + 1.103 + add("NETWPIN", 0); 1.104 + add("USERPIN", 1); 1.105 + add("USERNETWPIN", 2); 1.106 + add("USERPINMAC", 3); 1.107 + 1.108 + return names; 1.109 +})(); 1.110 + 1.111 +this.Authenticator = { 1.112 + /** 1.113 + * Format IMSI string into GSM format 1.114 + * 1.115 + * @param imsi 1.116 + * IMSI string 1.117 + * 1.118 + * @return IMSI in GSM format as string object 1.119 + */ 1.120 + formatImsi: function formatImsi(imsi) { 1.121 + let parityByte = ((imsi.length & 1) ? 9 : 1); 1.122 + 1.123 + // Make sure length of IMSI is 15 digits. 1.124 + // @see GSM 11.11, clause 10.2.2 1.125 + let i = 0; 1.126 + for (i = 15 - imsi.length; i > 0; i--) { 1.127 + imsi += "F"; 1.128 + } 1.129 + 1.130 + // char-by-char atoi 1.131 + let imsiValue = []; 1.132 + imsiValue.push(parityByte); 1.133 + for (i = 0; i < imsi.length; i++) { 1.134 + imsiValue.push(parseInt(imsi.substr(i, 1), 10)); 1.135 + } 1.136 + 1.137 + // encoded IMSI 1.138 + let imsiEncoded = ""; 1.139 + for (i = 0; i < imsiValue.length; i += 2) { 1.140 + imsiEncoded += String.fromCharCode(imsiValue[i] | (imsiValue[i+1] << 4)); 1.141 + } 1.142 + 1.143 + return imsiEncoded; 1.144 + }, 1.145 + 1.146 + /** 1.147 + * Perform HMAC check 1.148 + * 1.149 + * @param wbxml 1.150 + * Uint8 typed array of raw WBXML data. 1.151 + * @param key 1.152 + * key string for HMAC check. 1.153 + * @param mac 1.154 + * Expected MAC value. 1.155 + * 1.156 + * @return true for valid, false for invalid. 1.157 + */ 1.158 + isValid: function isValid(wbxml, key, mac) { 1.159 + let hasher = CryptoUtils.makeHMACHasher(Ci.nsICryptoHMAC.SHA1, 1.160 + CryptoUtils.makeHMACKey(key)); 1.161 + hasher.update(wbxml, wbxml.length); 1.162 + let result = CommonUtils.bytesAsHex(hasher.finish(false)).toUpperCase(); 1.163 + return mac == result; 1.164 + }, 1.165 + 1.166 + /** 1.167 + * Perform HMAC authentication. 1.168 + * 1.169 + * @param wbxml 1.170 + * Uint8 typed array of raw WBXML data. 1.171 + * @param sec 1.172 + * Security method for HMAC check. 1.173 + * @param mac 1.174 + * Expected MAC value. 1.175 + * @param getNetworkPin 1.176 + * Callback function for getting network pin. 1.177 + * 1.178 + * @return true for valid, false for invalid. 1.179 + */ 1.180 + check: function check_hmac(wbxml, sec, mac, getNetworkPin) { 1.181 + // No security set. 1.182 + if (sec == null || !mac) { 1.183 + return null; 1.184 + } 1.185 + 1.186 + let authInfo = { 1.187 + pass: false, 1.188 + checked: false, 1.189 + sec: AUTH_SEC_TYPE[sec], 1.190 + mac: mac.toUpperCase(), 1.191 + data: wbxml 1.192 + }; 1.193 + 1.194 + switch (authInfo.sec) { 1.195 + case "NETWPIN": 1.196 + let key = getNetworkPin(); 1.197 + authInfo.pass = this.isValid(wbxml, key, authInfo.mac); 1.198 + authInfo.checked = true; 1.199 + return authInfo; 1.200 + 1.201 + case "USERPIN": 1.202 + case "USERPINMAC": 1.203 + // We can't check without USER PIN 1.204 + return authInfo; 1.205 + 1.206 + case "USERNETWPIN": 1.207 + default: 1.208 + return null; 1.209 + } 1.210 + } 1.211 +}; 1.212 + 1.213 +/** 1.214 + * Tag tokens 1.215 + * 1.216 + * @see OMA-WAP-TS-ProvCont-V1_1-20090421-C, clause 7.1 1.217 + */ 1.218 +const CP_TAG_FIELDS = (function () { 1.219 + let names = {}; 1.220 + function add(name, codepage, number) { 1.221 + let entry = { 1.222 + name: name, 1.223 + number: number, 1.224 + }; 1.225 + if (!names[codepage]) { 1.226 + names[codepage] = {}; 1.227 + } 1.228 + names[codepage][number] = entry; 1.229 + } 1.230 + 1.231 + // Code page 0 1.232 + add("wap-provisioningdoc", 0, 0x05); 1.233 + add("characteristic", 0, 0x06); 1.234 + add("parm", 0, 0x07); 1.235 + // Code page 1 1.236 + add("characteristic", 1, 0x06); 1.237 + add("parm", 1, 0x07); 1.238 + 1.239 + return names; 1.240 +})(); 1.241 + 1.242 +/** 1.243 + * Attribute Tokens 1.244 + * 1.245 + * @see OMA-WAP-TS-ProvCont-V1_1-20090421-C, clause 7.2 1.246 + */ 1.247 +const CP_ATTRIBUTE_FIELDS = (function () { 1.248 + let names = {}; 1.249 + function add(name, value, codepage, number) { 1.250 + let entry = { 1.251 + name: name, 1.252 + value: value, 1.253 + number: number, 1.254 + }; 1.255 + if (!names[codepage]) { 1.256 + names[codepage] = {}; 1.257 + } 1.258 + names[codepage][number] = entry; 1.259 + } 1.260 + 1.261 + // Code page 0 1.262 + add("name", "", 0, 0x05); 1.263 + add("value", "", 0, 0x06); 1.264 + add("name", "NAME", 0, 0x07); 1.265 + add("name", "NAP-ADDRESS", 0, 0x08); 1.266 + add("name", "NAP-ADDRTYPE", 0, 0x09); 1.267 + add("name", "CALLTYPE", 0, 0x0A); 1.268 + add("name", "VALIDUNTIL", 0, 0x0B); 1.269 + add("name", "AUTHTYPE", 0, 0x0C); 1.270 + add("name", "AUTHNAME", 0, 0x0D); 1.271 + add("name", "AUTHSECRET", 0, 0x0E); 1.272 + add("name", "LINGER", 0, 0x0F); 1.273 + add("name", "BEARER", 0, 0x10); 1.274 + add("name", "NAPID", 0, 0x11); 1.275 + add("name", "COUNTRY", 0, 0x12); 1.276 + add("name", "NETWORK", 0, 0x13); 1.277 + add("name", "INTERNET", 0, 0x14); 1.278 + add("name", "PROXY-ID", 0, 0x15); 1.279 + add("name", "PROXY-PROVIDER-ID", 0, 0x16); 1.280 + add("name", "DOMAIN", 0, 0x17); 1.281 + add("name", "PROVURL", 0, 0x18); 1.282 + add("name", "PXAUTH-TYPE", 0, 0x19); 1.283 + add("name", "PXAUTH-ID", 0, 0x1A); 1.284 + add("name", "PXAUTH-PW", 0, 0x1B); 1.285 + add("name", "STARTPAGE", 0, 0x1C); 1.286 + add("name", "BASAUTH-ID", 0, 0x1D); 1.287 + add("name", "BASAUTH-PW", 0, 0x1E); 1.288 + add("name", "PUSHENABLED", 0, 0x1F); 1.289 + add("name", "PXADDR", 0, 0x20); 1.290 + add("name", "PXADDRTYPE", 0, 0x21); 1.291 + add("name", "TO-NAPID", 0, 0x22); 1.292 + add("name", "PORTNBR", 0, 0x23); 1.293 + add("name", "SERVICE", 0, 0x24); 1.294 + add("name", "LINKSPEED", 0, 0x25); 1.295 + add("name", "DNLINKSPEED", 0, 0x26); 1.296 + add("name", "LOCAL-ADDR", 0, 0x27); 1.297 + add("name", "LOCAL-ADDRTYPE", 0, 0x28); 1.298 + add("name", "CONTEXT-ALLOW", 0, 0x29); 1.299 + add("name", "TRUST", 0, 0x2A); 1.300 + add("name", "MASTER", 0, 0x2B); 1.301 + add("name", "SID", 0, 0x2C); 1.302 + add("name", "SOC", 0, 0x2D); 1.303 + add("name", "WSP-VERSION", 0, 0x2E); 1.304 + add("name", "PHYSICAL-PROXY-ID", 0, 0x2F); 1.305 + add("name", "CLIENT-ID", 0, 0x30); 1.306 + add("name", "DELIVERY-ERR-PDU", 0, 0x31); 1.307 + add("name", "DELIVERY-ORDER", 0, 0x32); 1.308 + add("name", "TRAFFIC-CLASS", 0, 0x33); 1.309 + add("name", "MAX-SDU-SIZE", 0, 0x34); 1.310 + add("name", "MAX-BITRATE-UPLINK", 0, 0x35); 1.311 + add("name", "MAX-BITRATE-DNLINK", 0, 0x36); 1.312 + add("name", "RESIDUAL-BER", 0, 0x37); 1.313 + add("name", "SDU-ERROR-RATIO", 0, 0x38); 1.314 + add("name", "TRAFFIC-HANDL-PRIO", 0, 0x39); 1.315 + add("name", "TRANSFER-DELAY", 0, 0x3A); 1.316 + add("name", "GUARANTEED-BITRATE-UPLINK", 0, 0x3B); 1.317 + add("name", "GUARANTEED-BITRATE-DNLINK", 0, 0x3C); 1.318 + add("name", "PXADDR-FQDN", 0, 0x3D); 1.319 + add("name", "PROXY-PW", 0, 0x3E); 1.320 + add("name", "PPGAUTH-TYPE", 0, 0x3F); 1.321 + add("version", "", 0, 0x45); 1.322 + add("version", "1.0", 0, 0x46); 1.323 + add("name", "PULLENABLED", 0, 0x47); 1.324 + add("name", "DNS-ADDR", 0, 0x48); 1.325 + add("name", "MAX-NUM-RETRY", 0, 0x49); 1.326 + add("name", "FIRST-RETRY-TIMEOUT", 0, 0x4A); 1.327 + add("name", "REREG-THRESHOLD", 0, 0x4B); 1.328 + add("name", "T-BIT", 0, 0x4C); 1.329 + add("name", "AUTH-ENTITY", 0, 0x4E); 1.330 + add("name", "SPI", 0, 0x4F); 1.331 + add("type", "", 0, 0x50); 1.332 + add("type", "PXLOGICAL", 0, 0x51); 1.333 + add("type", "PXPHYSICAL", 0, 0x52); 1.334 + add("type", "PORT", 0, 0x53); 1.335 + add("type", "VALIDITY", 0, 0x54); 1.336 + add("type", "NAPDEF", 0, 0x55); 1.337 + add("type", "BOOTSTRAP", 0, 0x56); 1.338 +/* 1.339 + * Mark out VENDORCONFIG so if it is contained in message, parse 1.340 + * will failed and raw data is returned. 1.341 + */ 1.342 +// add("type", "VENDORCONFIG", 0, 0x57); 1.343 + add("type", "CLIENTIDENTITY", 0, 0x58); 1.344 + add("type", "PXAUTHINFO", 0, 0x59); 1.345 + add("type", "NAPAUTHINFO", 0, 0x5A); 1.346 + add("type", "ACCESS", 0, 0x5B); 1.347 + 1.348 + // Code page 1 1.349 + add("name", "", 1, 0x05); 1.350 + add("value", "", 1, 0x06); 1.351 + add("name", "NAME", 1, 0x07); 1.352 + add("name", "INTERNET", 1, 0x14); 1.353 + add("name", "STARTPAGE", 1, 0x1C); 1.354 + add("name", "TO-NAPID", 1, 0x22); 1.355 + add("name", "PORTNBR", 1, 0x23); 1.356 + add("name", "SERVICE", 1, 0x24); 1.357 + add("name", "AACCEPT", 1, 0x2E); 1.358 + add("name", "AAUTHDATA", 1, 0x2F); 1.359 + add("name", "AAUTHLEVEL", 1, 0x30); 1.360 + add("name", "AAUTHNAME", 1, 0x31); 1.361 + add("name", "AAUTHSECRET", 1, 0x32); 1.362 + add("name", "AAUTHTYPE", 1, 0x33); 1.363 + add("name", "ADDR", 1, 0x34); 1.364 + add("name", "ADDRTYPE", 1, 0x35); 1.365 + add("name", "APPID", 1, 0x36); 1.366 + add("name", "APROTOCOL", 1, 0x37); 1.367 + add("name", "PROVIDER-ID", 1, 0x38); 1.368 + add("name", "TO-PROXY", 1, 0x39); 1.369 + add("name", "URI", 1, 0x3A); 1.370 + add("name", "RULE", 1, 0x3B); 1.371 + add("type", "", 1, 0x50); 1.372 + add("type", "PORT", 1, 0x53); 1.373 + add("type", "APPLICATION", 1, 0x55); 1.374 + add("type", "APPADDR", 1, 0x56); 1.375 + add("type", "APPAUTH", 1, 0x57); 1.376 + add("type", "CLIENTIDENTITY", 1, 0x58); 1.377 + add("type", "RESOURCE", 1, 0x59); 1.378 + 1.379 + return names; 1.380 +})(); 1.381 + 1.382 +/** 1.383 + * Value Tokens 1.384 + * 1.385 + * @see OMA-WAP-TS-ProvCont-V1_1-20090421-C, clause 7.3 1.386 + */ 1.387 +const CP_VALUE_FIELDS = (function () { 1.388 + let names = {}; 1.389 + function add(value, codepage, number) { 1.390 + let entry = { 1.391 + value: value, 1.392 + number: number, 1.393 + }; 1.394 + if (!names[codepage]) { 1.395 + names[codepage] = {}; 1.396 + } 1.397 + names[codepage][number] = entry; 1.398 + } 1.399 + 1.400 + // Code page 0 1.401 + add("IPV4", 0, 0x85); 1.402 + add("IPV6", 0, 0x86); 1.403 + add("E164", 0, 0x87); 1.404 + add("ALPHA", 0, 0x88); 1.405 + add("APN", 0, 0x89); 1.406 + add("SCODE", 0, 0x8A); 1.407 + add("TETRA-ITSI", 0, 0x8B); 1.408 + add("MAN", 0, 0x8C); 1.409 + add("ANALOG-MODEM", 0, 0x90); 1.410 + add("V.120", 0, 0x91); 1.411 + add("V.110", 0, 0x92); 1.412 + add("X.31", 0, 0x93); 1.413 + add("BIT-TRANSPARENT", 0, 0x94); 1.414 + add("DIRECT-ASYNCHRONOUS-DATA-SERVICE", 0, 0x95); 1.415 + add("PAP", 0, 0x9A); 1.416 + add("CHAP", 0, 0x9B); 1.417 + add("HTTP-BASIC", 0, 0x9C); 1.418 + add("HTTP-DIGEST", 0, 0x9D); 1.419 + add("WTLS-SS", 0, 0x9E); 1.420 + add("MD5", 0, 0x9F); // Added in OMA, 7.3.3 1.421 + add("GSM-USSD", 0, 0xA2); 1.422 + add("GSM-SMS", 0, 0xA3); 1.423 + add("ANSI-136-GUTS", 0, 0xA4); 1.424 + add("IS-95-CDMA-SMS", 0, 0xA5); 1.425 + add("IS-95-CDMA-CSD", 0, 0xA6); 1.426 + add("IS-95-CDMA-PAC", 0, 0xA7); 1.427 + add("ANSI-136-CSD", 0, 0xA8); 1.428 + add("ANSI-136-GPRS", 0, 0xA9); 1.429 + add("GSM-CSD", 0, 0xAA); 1.430 + add("GSM-GPRS", 0, 0xAB); 1.431 + add("AMPS-CDPD", 0, 0xAC); 1.432 + add("PDC-CSD", 0, 0xAD); 1.433 + add("PDC-PACKET", 0, 0xAE); 1.434 + add("IDEN-SMS", 0, 0xAF); 1.435 + add("IDEN-CSD", 0, 0xB0); 1.436 + add("IDEN-PACKET", 0, 0xB1); 1.437 + add("FLEX/REFLEX", 0, 0xB2); 1.438 + add("PHS-SMS", 0, 0xB3); 1.439 + add("PHS-CSD", 0, 0xB4); 1.440 + add("TETRA-SDS", 0, 0xB5); 1.441 + add("TETRA-PACKET", 0, 0xB6); 1.442 + add("ANSI-136-GHOST", 0, 0xB7); 1.443 + add("MOBITEX-MPAK", 0, 0xB8); 1.444 + add("CDMA2000-1X-SIMPLE-IP", 0, 0xB9); // Added in OMA, 7.3.4 1.445 + add("CDMA2000-1X-MOBILE-IP", 0, 0xBA); // Added in OMA, 7.3.4 1.446 + add("AUTOBOUDING", 0, 0xC5); 1.447 + add("CL-WSP", 0, 0xCA); 1.448 + add("CO-WSP", 0, 0xCB); 1.449 + add("CL-SEC-WSP", 0, 0xCC); 1.450 + add("CO-SEC-WSP", 0, 0xCD); 1.451 + add("CL-SEC-WTA", 0, 0xCE); 1.452 + add("CO-SEC-WTA", 0, 0xCF); 1.453 + add("OTA-HTTP-TO", 0, 0xD0); // Added in OMA, 7.3.6 1.454 + add("OTA-HTTP-TLS-TO", 0, 0xD1); // Added in OMA, 7.3.6 1.455 + add("OTA-HTTP-PO", 0, 0xD2); // Added in OMA, 7.3.6 1.456 + add("OTA-HTTP-TLS-PO", 0, 0xD3); // Added in OMA, 7.3.6 1.457 + add("AAA", 0, 0xE0); // Added in OMA, 7.3.8 1.458 + add("HA", 0, 0xE1); // Added in OMA, 7.3.8 1.459 + 1.460 + // Code page 1 1.461 + add("IPV6", 1, 0x86); 1.462 + add("E164", 1, 0x87); 1.463 + add("ALPHA", 1, 0x88); 1.464 + add("APPSRV", 1, 0x8D); 1.465 + add("OBEX", 1, 0x8E); 1.466 + add(",", 1, 0x90); 1.467 + add("HTTP-", 1, 0x91); 1.468 + add("BASIC", 1, 0x92); 1.469 + add("DIGEST", 1, 0x93); 1.470 + 1.471 + return names; 1.472 +})(); 1.473 + 1.474 +let debug; 1.475 +if (DEBUG) { 1.476 + debug = function (s) { 1.477 + dump("-$- CpPduHelper: " + s + "\n"); 1.478 + }; 1.479 +} else { 1.480 + debug = function (s) {}; 1.481 +} 1.482 + 1.483 +this.EXPORTED_SYMBOLS = [ 1.484 + // Parser 1.485 + "PduHelper", 1.486 + // HMAC Authenticator 1.487 + "Authenticator", 1.488 +];