Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "CSFLog.h"
7 #include "CC_Common.h"
8 #include "csf_common.h"
9 #ifdef WIN32
10 #include <windows.h>
11 #else
12 #ifdef LINUX
13 // for platGetIPAddr
14 #include <sys/ioctl.h>
15 #include <sys/types.h>
16 #include <arpa/inet.h>
17 #include <net/if.h>
18 #include <fcntl.h>
19 #endif
20 #endif
22 #include "cpr_string.h"
24 static const char* logTag = "sipcc";
26 extern "C"
27 {
28 #include "plat_api.h"
29 #include <stdarg.h>
32 void NotifyStateChange (cc_callid_t callid, int32_t state) {
33 //Don't need anything here.
34 //Call state change are notified to us via SIPCC "high level" API
35 }
37 #ifndef OSX
38 /**
39 * platGetFeatureAllowed
40 *
41 * Get whether the feature is allowed
42 *
43 * @param featureId - sis feature id
44 *
45 * @return 1 - allowed, 0 - not allowed
46 *
47 */
48 int platGetFeatureAllowed(cc_sis_feature_id_e featureId) {
49 return 1;
50 }
52 /**
53 * Set the Status message for failure reasons
54 * @param char *msg
55 * @return void
56 */
57 void platSetStatusMessage(char *msg) {
58 }
60 /**
61 * Sets the time based on Date header in 200 OK from REGISTER request
62 * @param void
63 * @return void
64 */
65 void platSetCucmRegTime (void) {
66 }
68 /**
69 * Enable / disable speaker
70 *
71 * @param[in] state - true -> enable speaker, false -> disable speaker
72 *
73 * @return void
74 */
75 extern "C" void platSetSpeakerMode(cc_boolean state) {
76 }
78 /**
79 * Get the status (on/off) of the audio device
80 *
81 * @param[in] device_type - headset or speaker (see vcm_audio_device_t)
82 *
83 * @return 1 -> On, 0 -> off, ERROR -> unknown (error)
84 */
85 int platGetAudioDeviceStatus(plat_audio_device_t device_type) {
86 //Tell SIPCC what the current audio path is by return 1 for one of either: headset or speaker.
87 return 1;
88 }
90 /**
91 * Check if the speaker or headset is enabled.
92 *
93 * @return boolean if the speaker or headset is enabled, returns true.
94 */
95 boolean platGetSpeakerHeadsetMode() {
96 return TRUE;
97 }
98 #endif
100 /**
101 * Provides the local MAC address
102 *
103 * @param *maddr the pointer to the string holding MAC address
104 * in the MAC address format after converting from string format.
105 * @return void
106 */
107 void platGetMacAddr(char *maddr) {
108 //Strictly speaking the code using this is not treating this as a string.
109 //It's taking the first 6 bytes out of the buffer, and printing these
110 //directly, so it's not enough to just make the first byte '\0' need
111 //to set all of the bytes in range 0-5 equal to '\0'.
112 //Have to assume here that the buffer is big enough.
113 for (int i=0; i<6; i++)
114 {
115 *(maddr+i) = '\0';
116 }
117 }
119 #ifndef OSX
120 /**
121 * Called by the thread to initialize any thread specific data
122 * once the thread is created.
123 *
124 * @param[in] tname thread name
125 *
126 * @return 0 - SUCCESS
127 * -1 - FAILURE
128 */
129 int platThreadInit(char * tname) {
130 return 0;
131 }
133 /**
134 * The initial initialization function for any platform related
135 * modules
136 *
137 *
138 * @return 0 - SUCCESS
139 * -1 - FAILURE
140 */
141 int platInit() {
142 return 0;
143 }
145 /**
146 * The initial initialization function for the debugging/logging
147 * modules
148 *
149 */
150 void debugInit() {
151 return ;
152 }
154 /**
155 * Add cc control classifier
156 *
157 * Called by SIP stack to specify addresses and ports that will be used for call control
158 *
159 * @param[in] myIPAddr - phone local interface IP Address
160 * @param[in] myPort - phone local interface Port
161 * @param[in] cucm1IPAddr - CUCM 1 IP Address
162 * @param[in] cucm1Port - CUCM 1 Port
163 * @param[in] cucm2IPAddr - CUCM 2 IP Address
164 * @param[in] cucm2Port - CUCM 2 Port
165 * @param[in] cucm3IPAddr - CUCM 3 IP Address
166 * @param[in] cucm3Port - CUCM 3 Port
167 * @param[in] protocol - CC_IPPROTO_UDP or CC_IP_PROTO_TCP
168 *
169 * @note : Needed only if using WiFi. If not using Wifi please provide a stub
170 */
171 void platAddCallControlClassifiers(unsigned long myIPAddr, unsigned short myPort,
172 unsigned long cucm1IPAddr, unsigned short cucm1Port,
173 unsigned long cucm2IPAddr, unsigned short cucm2Port,
174 unsigned long cucm3IPAddr, unsigned short cucm3Port,
175 unsigned char protocol) {
176 //Needed only if using WiFi. If not using Wifi please provide a stub
177 }
179 /**
180 * Remove cc control classifier.
181 *
182 * Undo platAddCallControlClassifiers
183 */
184 void platRemoveCallControlClassifiers() {
185 //Needed only if using WiFi. If not using Wifi please provide a stub
186 }
188 /**
189 * Set ip address mode
190 * e.g.
191 *
192 */
193 cpr_ip_mode_e platGetIpAddressMode() {
194 return CPR_IP_MODE_IPV4;
195 }
197 /**
198 * Tell whether wifi is supported and active
199 *
200 * @return boolean wether WLAN is active or not
201 */
202 cc_boolean platWlanISActive() {
203 return FALSE;
204 }
206 /**
207 * Check if the network interface changed.
208 *
209 * @return boolean returns TRUE if the network interface has changed
210 *
211 * @note Most common case is for softphone clients where if a PC is
212 * undocked the network interface changes from wired to wireless.
213 */
214 boolean platIsNetworkInterfaceChanged() {
215 //We're OK with this
216 return FALSE;
217 }
219 /**
220 * Get active phone load name
221 *
222 * Returns the phone images in the active and inactive partitions
223 * The phone reports these phone loads to CUCM for display on the Admin page
224 *
225 * @param[in] image_a : Populate the image name from partition a
226 * @param[in] image_b : Populate the image name from partition b
227 * @param[in] len : Length of the pointers for image_a and image_b
228 * @return 1 - image_a is active.
229 * Anything other than 1 - image_b is active
230 */
231 int platGetActiveInactivePhoneLoadName(char * image_a, char * image_b, int len) {
232 if (image_a != nullptr)
233 {
234 sstrncpy(image_a, "image_a", len);
235 }
237 if (image_b != nullptr)
238 {
239 sstrncpy(image_b, "image_b", len);
240 }
242 return 1;
243 }
245 /**
246 * Get or Set user defined phrases
247 * @param index the phrase index, see
248 * @param phrase the return phrase holder
249 * @param len the input length to cap the maximum value
250 * @return SUCCESS or FAILURE
251 */
252 int platGetPhraseText(int index, char* phrase, unsigned int len) {
253 //Need to copy something into "phrase" as this is used as a prefix
254 //in a starts with comparison (use strncmp) that will match against
255 //any string if the prefix is empty. Also in some places an
256 //uninitialized buffer is passed in as "phrase", so if we don't
257 //do something then SIPCC will go on the use the uninitialized
258 //buffer.
260 if (phrase == nullptr)
261 {
262 return CC_FAILURE;
263 }
265 sstrncpy(phrase, "?????", len);
267 return (int) CC_SUCCESS;
268 }
270 /**
271 * Get the unregistration reason code.
272 * @return reason code for unregistration, see the definition.
273 */
274 int platGetUnregReason() {
275 return 0;
276 }
278 /**
279 * Set the unregistration reason
280 * @param reason see the unregister reason definitions.
281 * @return void
282 */
283 void platSetUnregReason(int reason) {
284 //We may need to persist this for CUCM. WHen we restart next time call to platGetUnregReason above tells CUCM what why we unregistered last time.
285 typedef struct _unRegRreasonEnumPair {
286 int reason;
287 const char * pReasonStr;
288 } unRegRreasonEnumPair;
290 static unRegRreasonEnumPair unRegReasons[] = {
291 { CC_UNREG_REASON_UNSPECIFIED, "CC_UNREG_REASON_UNSPECIFIED" },
292 { CC_UNREG_REASON_TCP_TIMEOUT, "CC_UNREG_REASON_TCP_TIMEOUT" },
293 { CC_UNREG_REASON_CM_RESET_TCP, "CC_UNREG_REASON_CM_RESET_TCP" },
294 { CC_UNREG_REASON_CM_ABORTED_TCP, "CC_UNREG_REASON_CM_ABORTED_TCP" },
295 { CC_UNREG_REASON_CM_CLOSED_TCP, "C_UNREG_REASON_CM_CLOSED_TCP" },
296 { CC_UNREG_REASON_REG_TIMEOUT, "CC_UNREG_REASON_REG_TIMEOUT" },
297 { CC_UNREG_REASON_FALLBACK, "CC_UNREG_REASON_FALLBACK" },
298 { CC_UNREG_REASON_PHONE_KEYPAD, "CC_UNREG_REASON_PHONE_KEYPAD" },
299 { CC_UNREG_REASON_RESET_RESET, "CC_UNREG_REASON_RESET_RESET" },
300 { CC_UNREG_REASON_RESET_RESTART, "CC_UNREG_REASON_RESET_RESTART" },
301 { CC_UNREG_REASON_PHONE_REG_REJ, "CC_UNREG_REASON_PHONE_REG_REJ" },
302 { CC_UNREG_REASON_PHONE_INITIALIZED, "CC_UNREG_REASON_PHONE_INITIALIZED" },
303 { CC_UNREG_REASON_VOICE_VLAN_CHANGED, "CC_UNREG_REASON_VOICE_VLAN_CHANGED" },
304 { CC_UNREG_REASON_POWER_SAVE_PLUS, "CC_UNREG_REASON_POWER_SAVE_PLUS" },
305 { CC_UNREG_REASON_VERSION_STAMP_MISMATCH, "CC_UNREG_REASON_VERSION_STAMP_MISMATCH" },
306 { CC_UNREG_REASON_VERSION_STAMP_MISMATCH_CONFIG, "CC_UNREG_REASON_VERSION_STAMP_MISMATCH_CONFIG" },
307 { CC_UNREG_REASON_VERSION_STAMP_MISMATCH_SOFTKEY, "CC_UNREG_REASON_VERSION_STAMP_MISMATCH_SOFTKEY" },
308 { CC_UNREG_REASON_VERSION_STAMP_MISMATCH_DIALPLAN, "CC_UNREG_REASON_VERSION_STAMP_MISMATCH_DIALPLAN" },
309 { CC_UNREG_REASON_APPLY_CONFIG_RESTART, "CC_UNREG_REASON_APPLY_CONFIG_RESTART" },
310 { CC_UNREG_REASON_CONFIG_RETRY_RESTART, "CC_UNREG_REASON_CONFIG_RETRY_RESTART" },
311 { CC_UNREG_REASON_TLS_ERROR, "CC_UNREG_REASON_TLS_ERROR" },
312 { CC_UNREG_REASON_RESET_TO_INACTIVE_PARTITION, "CC_UNREG_REASON_RESET_TO_INACTIVE_PARTITION" },
313 { CC_UNREG_REASON_VPN_CONNECTIVITY_LOST, "CC_UNREG_REASON_VPN_CONNECTIVITY_LOST" }
314 };
316 for (int i=0; i< (int) csf_countof(unRegReasons); i++)
317 {
318 unRegRreasonEnumPair * pCurrentUnRegReasonPair = &unRegReasons[i];
320 if (pCurrentUnRegReasonPair->reason == reason)
321 {
322 CSFLogDebug( logTag, "platSetUnregReason(%s)", pCurrentUnRegReasonPair->pReasonStr);
323 return;
324 }
325 }
327 CSFLogError( logTag, "Unknown reason code (%d) passed to platSetUnregReason()", reason);
328 }
331 #endif
333 #ifndef OSX
334 /**
335 * Set the kpml value for application.
336 * @param kpml_config the kpml value
337 * @return void
338 */
339 void platSetKPMLConfig(cc_kpml_config_t kpml_config) {
340 }
342 /**
343 * Check if a line has active MWI status
344 * @param line
345 * @return boolean
346 */
347 boolean platGetMWIStatus(cc_lineid_t line) {
348 return TRUE;
349 }
352 /**
353 * Secure Socket API's.
354 * The pSIPCC expects the following Secure Socket APIs to be implemented in the
355 * vendor porting layer.
356 */
358 /**
359 * platSecIsServerSecure
360 *
361 * @brief Lookup the secure status of the server
362 *
363 * This function looks at the the CCM server type by using the security library
364 * and returns appropriate indication to the pSIPCC.
365 *
366 *
367 * @return Server is security enabled or not
368 * PLAT_SOCK_SECURE or PLAT_SOCK_NONSECURE
369 *
370 * @note This API maps to the following HandyIron API:
371 * int secIsServerSecure(SecServerType type) where type should be SRVR_TYPE_CCM
372 */
373 plat_soc_status_e platSecIsServerSecure(void) {
374 return PLAT_SOCK_NONSECURE;
375 }
378 /**
379 * platSecSocConnect
380 * @brief Securely connect to a remote server
381 *
382 * This function uses the security library APIs to connect to a remote server.
383 * @param[in] host server addr
384 * @param[in] port port number
385 * @param[in] ipMode IP mode to indicate v6, v4 or both
386 * @param[in] mode blocking connect or not
387 * FALSE: non-blocking; TRUE: blocking
388 * @param[in] tos TOS value
389 * @param[in] connectionType Are we talking to Call-Agent
390 * @param[in] connectionMode The mode of the connection
391 * (Authenticated/Encrypted)
392 * @param[out] localPort local port used for the connection
393 *
394 * @return client socket descriptor
395 * >=0: connected or in progress
396 * INVALID SOCKET: failed
397 *
398 * @pre (hostAndPort not_eq nullptr)
399 * @pre (localPort not_eq nullptr)
400 *
401 * @note localPort is undefined when the return value is INVALID_SOCKET
402 *
403 * @note This API maps to the HandyIron APIs as follows:
404 * If mode == TRUE (blocking):
405 * int secEstablishSecureConnection(const char* serverAddr, *uint32_t port, secConnectionType type)
406 * @li ipMode is UNUSED
407 * @li "host" maps to "serverAddr", "connectionType" maps to "type"
408 * @li localPort is passed in as 0
409 * If mode == FALSE (non-blocking):
410 * int secConnect(const char* serverAddr, uint32_t port, *secConnectionType type, uint32_t localPort)
411 * @li ipMode is UNUSED
412 * @li "host" maps to "serverAddr", "connectionType" maps to "type"
413 *
414 * @note The implementation should use the "setsockopt" to set the "tos" value passed
415 * in this API on the created socket.
416 *
417 */
418 cpr_socket_t
419 platSecSocConnect (char *host,
420 int port,
421 int ipMode,
422 boolean mode,
423 unsigned int tos,
424 plat_soc_connect_mode_e connectionMode,
425 uint16_t *localPort) {
426 return 0;
427 }
429 /**
430 * platSecSockIsConnected
431 * Determine the status of a secure connection that was initiated
432 * in non-blocking mode
433 *
434 * @param[in] sock socket descriptor
435 *
436 * @return connection status
437 * @li connection complete: PLAT_SOCK_CONN_OK
438 * @li connection waiting: PLAT_SOCK_CONN_WAITING
439 * @li connection failed: PLAT_SOCK_CONN_FAILED
440 *
441 * @note This API maps to the following HandyIron API:
442 * int secIsConnectionReady (int connDesc)
443 * The "sock" is the connection descriptor.
444 */
445 plat_soc_connect_status_e platSecSockIsConnected (cpr_socket_t sock) {
446 return PLAT_SOCK_CONN_OK;
447 }
448 #endif //#endif !OSX
450 /**
451 * platGenerateCryptoRand
452 * @brief Generates a Random Number
453 *
454 * Generate crypto graphically random number for a desired length.
455 * The function is expected to be much slower than the cpr_rand().
456 * This function should be used when good random number is needed
457 * such as random number that to be used for SRTP key for an example.
458 *
459 * @param[in] buf - pointer to the buffer to store the result of random
460 * bytes requested.
461 * @param[in] len - pointer to the length of the desired random bytes.
462 * When calling the function, the integer's value
463 * should be set to the desired number of random
464 * bytes ('buf' should be of at least this size).
465 * upon success, its value will be set to the
466 * actual number of random bytes being returned.
467 * (realistically, there is a maximum number of
468 * random bytes that can be returned at a time.
469 * if the caller request more than that, the
470 * 'len' will indicate how many bytes are actually being
471 * returned) on failure, its value will be set to 0.
472 *
473 * @return
474 * 1 - success.
475 * 0 - fail.
476 *
477 * @note The intent of this function is to generate a cryptographically strong
478 * random number. Vendors can map this to HandyIron or OpenSSL random number
479 * generation functions.
480 *
481 * @note This API maps to the following HandyIron API:
482 * int secGetRandomData(uint8_t *buf, uint32_t size). Also note that a
483 * "secAddEntropy(...)" may be required the first time to feed entropy data to
484 * the random number generator.
485 */
486 #ifdef LINUX
487 int platGenerateCryptoRand(uint8_t *buf, int *len) {
488 int fd;
489 int rc = 0;
490 ssize_t s;
492 if ((fd = open("/dev/urandom", O_RDONLY)) == -1) {
493 CSFLogDebug( logTag, "Failed to open prng driver");
494 return 0;
495 }
497 /*
498 * Try to read the given amount of bytes from the PRNG device. We do not
499 * handle short reads but just return the number of bytes read from the
500 * device. The caller has to manage this.
501 * E.g. gsmsdp_generate_key() in core/gsm/gsm_sdp_crypto.c
502 */
504 s = read(fd, buf, (size_t) *len);
506 if (s > 0) {
507 *len = s;
508 rc = 1; /* Success */
509 } else {
510 *len = 0;
511 rc = 0; /* Failure */
512 }
515 (void) close(fd);
516 return rc;
517 }
518 #else
519 int platGenerateCryptoRand(uint8_t *buf, int *len) {
520 return 0;
521 }
522 #endif//!LINUX
524 #ifndef OSX
526 /*
527 <Umesh> The version is to regulate certain features like Join, which are added in later releases.
528 This is exchanged during registration with CUCM. It is a sheer luck that join may be working in some cases.
529 In this case Set API you have to store each of those API and return the same value in get.
531 We can go over all platform API’ and see which one are mandatory, we can do this in an email or in a meeting.
532 Please send out list methods for which you need clarification.
533 */
534 static cc_uint32_t majorSIS=1, minorSIS=0, addtnlSIS =0;
535 static char sis_ver_name[CC_MAX_LEN_REQ_SUPP_PARAM_CISCO_SISTAG] = {0};
537 /**
538 * Sets the SIS protocol version
539 *
540 * @param a - major version
541 * @param b - minor version
542 * @param c - additional version information
543 * @param name - version name
544 *
545 * @return void
546 * @note the platform should store this information and provide it when asked via the platGetSISProtocolVer()
547 */
548 void platSetSISProtocolVer(cc_uint32_t a, cc_uint32_t b, cc_uint32_t c, char* name) {
549 majorSIS = a;
550 minorSIS = b;
551 addtnlSIS = c;
553 if (name) {
554 sstrncpy(sis_ver_name, name, csf_countof(sis_ver_name));
555 } else {
556 *sis_ver_name = '\0';
557 }
558 }
560 /**
561 * Provides the SIS protocol version
562 *
563 * @param *a pointer to fill in the major version
564 * @param *b pointer to fill in the minor version
565 * @param *c pointer to fill in the additonal version
566 * @param *name pointer to fill in the version name
567 *
568 * @return void
569 */
570 void
571 platGetSISProtocolVer (cc_uint32_t *a, cc_uint32_t *b, cc_uint32_t *c, char* name) {
573 if (a != nullptr)
574 {
575 *a = majorSIS;
576 }
578 if (b != nullptr)
579 {
580 *b = minorSIS;
581 }
583 if (c != nullptr)
584 {
585 *c = addtnlSIS;
586 }
588 if (name != nullptr)
589 {
590 sstrncpy(name, sis_ver_name, CC_MAX_LEN_REQ_SUPP_PARAM_CISCO_SISTAG);
591 }
593 return;
594 }
596 void debug_bind_keyword(const char *cmd, int32_t *flag_ptr) {
597 return;
598 }
600 void debugif_add_keyword(const char *x, const char *y) {
601 return;
602 }
603 #endif
605 // Keep this when we are building the sipcc library without it, so that we capture logging
606 int debugif_printf(const char *_format, ...) {
607 va_list ap;
608 va_start(ap, _format);
609 CSFLogDebugV( logTag, _format, ap);
610 va_end(ap);
611 return 1; // Fake a "happy" return value.
612 }
614 }