AnyConnect Secure Mobility Client  5.1.11.388
ClientIfcBase.h
1 /**************************************************************************
2 * Copyright (c) 2006, 2021-2025 Cisco Systems, Inc.
3 * All Rights Reserved. Cisco Highly Confidential.
4 ***************************************************************************
5 *
6 * File: ClientIfcBase.h
7 * Author: Chris Fitzgerald
8 * Date: 08/2007
9 *
10 ***************************************************************************
11 * Client Interface Base class implementation for the Client API.
12 ***************************************************************************/
13 
14 #ifndef _CLIENTIFCBASE_
15 #define _CLIENTIFCBASE_
16 
17 #include <list>
18 #include <vector>
19 #include <memory>
20 
21 #include "ClientIfcCommon.h"
22 #include "api.h"
23 
24 #if defined(ANYCONNECT_USE_SNAK)
25 #include "SNAK_CertPlugin.h"
26 #endif
27 
28 #if defined(HOST_DATA_SUPPORTED)
29 class IHostData;
30 #endif
31 
32 class ConnectPromptInfo;
33 class MsgWithArg;
34 class VPNStats;
35 class PreferenceInfo;
36 class ProxyIfc;
37 class CIpcMessage;
38 class CertObj;
39 class HostEntry;
40 class ClientIfcInternal;
41 
42 #if defined(VPNAPI_TRANSMIGRATION_SUPPORTED)
43 class CSharedAccessLock;
44 #endif
45 
46 #if defined(VPNAPI_EVENT_NOTIFICATION_SUPPORTED)
47 class CEventNotificationTlv;
48 #endif
49 
50 #if defined(CREDENTIAL_PREFILL_SUPPORTED)
51 class CredentialPrefill;
52 #endif
53 
54 #if (defined(ANYCONNECT_USE_SNAK) || defined(PLATFORM_APPLE_SSLVPN)) && !defined(PLATFORM_WIN_APP)
55 class ManagedCertificate;
56 #endif
57 
58 #if defined(PROGRAM_DATA_IMPORT_SUPPORTED)
59 class IACImporterAsync;
60 class IACImporterAsyncCB;
61 #endif
62 
63 class VPN_VPNAPI ClientIfcBase
64 {
65  friend class EventMgr;
66  friend class ClientIfcInternal;
67 
68 protected:
69 
70  ClientIfcBase();
71  virtual ~ClientIfcBase();
72 
73  /**
74  * Callback used to deliver new statistics related to the VPN
75  * connection.
76  *
77  * When a connection is active, a new set of statistics is
78  * delivered each second.
79  *
80  * @see resetStats(), stopStats() and startStats()
81  *
82  */
83  virtual void StatsCB(VPNStats &stats) = 0;
84 
85 
86  /**
87  * Callback used to deliver VPN state and state change string.
88  * The stateString delivered by this method is localized.
89  *
90  * See the ::VPNState enum found in api.h for set of valid states.
91  */
92  virtual void StateCB(const VPNState state,
93  const VPNSubState subState,
94  const tstring stateString) = 0;
95 
96 
97  /**
98  * If a banner needs to be acknowledged, this CB delivers the banner
99  * to the client.
100  *
101  * NOTE: Connection establishment will block until the method
102  * setBannerResponse() is called.
103  *
104  * In a GUI, a banner would typically be displayed in a modal dialog
105  * with an accept or decline button selection.
106  *
107  * @see setBannerResponse() to set the user response to the banner.
108  */
109  virtual void BannerCB(const tstring &banner) = 0;
110 
111  /**
112  * If a pre-connect reminder needs to be acknowledged, this CB delivers
113  * the pre-connect reminder to the client.
114  *
115  * NOTE: Connection establishment will block until the method
116  * setPreConnectReminderResponse() is called.
117  *
118  * In a GUI, a pre-connect reminder would typically be displayed in a modal
119  * dialog with an OK button selection.
120  *
121  * @see setPreConnectReminderResponse() to set the user acknowledgement to
122  * the pre-connect reminder message.
123  */
124  virtual void PreConnectReminderCB(const tstring &rtstrPreConnectReminder);
125 
126  /**
127  * Messages are delivered via the NoticeCB and can come from multiple
128  * sources. There are four message types (error, warning, info and
129  * status). See the ::MessageType enum in api.h for the list.
130  *
131  * Clients using the API as an embedded application (not
132  * user visible) might want to further characterize
133  * messages. One option here is to use the AnyConnect message
134  * catalog and assign message codes as the translations for
135  * various messages. An application could then track messages based
136  * on its own error code scheme.
137  */
138  virtual void NoticeCB(const tstring &notice,
139  const MessageType type,
140  const bool bSensitive = false) = 0;
141 
142 #if defined(PLATFORM_APPLE_SSLVPN) || defined(PLATFORM_ANDROID) || defined(PLATFORM_CHROMEBOOK)
143  virtual void CertBannerCB(const tstring &certBannerSummary,
144  const uint32_t nCertBannerCertLen,
145  const uint8_t *pCertBannerCertDer,
146  const std::list<tstring> &confirmReasons,
147  const std::list<CertConfirmReason> &confirmReasonEnums,
148  bool bImportAllowed = true) = 0;
149 #endif
150 
151  /**
152  * This CB would likely occur only during a connection when it was
153  * detected that the software needed to be upgraded, or when Start
154  * Before Logon (SBL) is being used.
155  *
156  * Unlike the other callback methods, this method provides a default
157  * implementation (calling the system's exit() function).
158  * If clients of the API wish to override this behavior, they are
159  * responsible for ensuring that the current running process exits with
160  * the return code specified by returnCode.
161  *
162  * <b>Caution</b>: IF YOU OVERRIDE THIS METHOD AND DO NOT EXIT WITH
163  * THE PROPER CODE SOFTWARE UPDATE FUNCTIONALITY IN YOUR CLIENT WILL
164  * BREAK
165  */
166  virtual void ExitNoticeCB(const tstring &tstrNotice,
167  const int returnCode);
168 
169 
170  /**
171  * Under normal operating conditions, this CB is called as soon
172  * as the attach method completes. In case the service (vpn agent)
173  * is not ready, this CB is not called until it is.
174  *
175  * Any API calls made prior to this CB being called will result in a
176  * NoticeCB error message.
177  */
178  virtual void ServiceReadyCB() = 0;
179 
180 
181 
182  /**
183  * This method supports prompting for single or multiple values. All
184  * prompts are considered mandatory.
185  *
186  * The ConnectPromptInfo object contains a list of PromptEntry
187  * instances. The labels and their default values (if any) can be
188  * found in these instances. After the data has been collected from the user
189  * it can be set into these same instances. When ready, the client
190  * application should call the method UserSubmit() to have the
191  * responses read by the API.
192  */
193  virtual void UserPromptCB(ConnectPromptInfo &ConnectPrompt) = 0;
194 
195 
196  /**
197  * Use this method to provide Window Manager hints to GUI
198  * applications. To receive these hints, the application must
199  * identify itself as a GUI in the attach method. In addition, this
200  * method should be overridden to receive any generated events.
201  *
202  * Event that can be received include those indicating that a user is
203  * starting a second instance of the GUI application. This information
204  * can be used to tell the already running application to un-minimize
205  * itself and let the new program know that it should Quit (since a GUI
206  * is already running).
207  */
208  virtual void WMHintCB(const WMHint hint,
209  const WMHintReason reason);
210 
211 
212  /**
213  * This method is useful when the connection to the secure gateway
214  * has been established as part of a web-launch of the VPN tunnel.
215  *
216  * If the client application wishes to be notified of the secure
217  * gateway to which the VPN has been established, this method should
218  * be overridden.
219  *
220  * If the client application is started and a tunnel is already active,
221  * this method also delivers the name of the secure gateway host.
222  */
223  virtual void deliverWebLaunchHostCB(const tstring &activeHost);
224 
225  /**
226  * This method is called when the preference to block untrusted
227  * servers is enabled and the current VPN server being connected
228  * to is untrusted. Clients should present an error to the user
229  * notifying them that the current connection to rtstrUntrustedServer
230  * is being blocked. The client should also provide a way for the
231  * user to change the preference to block untrusted servers.
232  *
233  * The user response must be indicated using setCertBlockedResponse
234  */
235  virtual void CertBlockedCB(const tstring &rtstrUntrustedServer) = 0;
236 
237  /**
238  * This method is called when connections to untrusted VPN servers
239  * is allowed by policies and the current VPN server being connected
240  * to is untrusted. Clients should present a warning to the user
241  * notifying them that the current connection to rtstrUntrustedServer
242  * is unsafe. The reason the VPN server is untrusted is provided in
243  * rltstrCertErrors. The client should provide a way for the user to
244  * connect once, connect and always trust or cancel the connection.
245  * If bAllowImport is set to false then the always trust option should
246  * not be presented to users.
247  *
248  * The user response must be indicated using setCertWarningResponse
249  */
250  virtual void CertWarningCB(const tstring &rtstrUntrustedServer,
251  const std::list<tstring> &rltstrCertErrors,
252  bool bAllowImport) = 0;
253 
254 #if defined(PLATFORM_WIN_APP)
255  /**
256  * Same as above but also passes the Server certificate DER for details display
257  */
258  virtual void CertWarningCB(const tstring &rtstrUntrustedServer,
259  const std::list<tstring> &rltstrCertErrors,
260  const std::vector<uint8_t> &rvServerCertDER,
261  bool bAllowImport) = 0;
262 #endif
263 
264  /**
265  * This method should be overridden by the client application to
266  * exercise some control over the delivery of events from the other
267  * protected methods in this class.
268  *
269  * This might be necessary in cases where a GUI/CLI is being written and
270  * the data from this API needs to be delivered in the GUI/CLI or main
271  * thread. In this case, you should override this method and when it
272  * is called by the API post an event to your event queue (message
273  * pump, etc.). After this event executes in your GUI/CLI or main thread,
274  * call the method ClientIfc::ProcessEvents to have events delivered
275  * to your client application.
276  */
277  virtual void EventAvailable();
278 
279 #if defined(MANUAL_PKCS12_IMPORT_SUPPORTED)
280  virtual void ImportPKCS12ResultCB(const std::vector<uint8_t> &certHash,
281  const tstring &tstrError);
282 #endif
283 #if defined(PLATFORM_ANDROID)
284  virtual void ClientCertificateCB(std::vector< std::pair<uint32_t, uint8_t*> > certList) = 0;
285  virtual void AgentDetachedCB();
286 #endif
287 
288 #if defined(VPNAPI_EVENT_NOTIFICATION_SUPPORTED)
289  /**
290  * Internal callback between ClientIfcBase and ClientIfc.
291  */
292  virtual void EventNotificationInternalCB(
293  const std::shared_ptr<CEventNotificationTlv>& spEventNtfctnTlv) = 0;
294 #endif
295 
296 
297  /**
298  * Internal methods for use by ClientIfc.
299  */
300 
301  void ResetQuarantinedReconnect();
302 
303  void ClientIfcTransmigration();
304 
305 public:
306 
307  bool attach(const ClientType clientType = ClientType_GUI,
308  const bool requestFullCapabilities = true,
309  const bool suppressAutoConnect = true,
310  const bool bSuppressEventAvailableCB = false);
311 
312  void detach();
313 
314  void ProcessEvents();
315 
316  bool hasFullCapabilities();
317 
318  bool isConnected(bool bSilent = false);
319 
320  bool isAvailable();
321 
322  std::list<tstring> getHostNames();
323 
324  std::list<HostEntry> getHostEntries();
325 
326  tstring getDefaultHostName();
327 
328  bool connect(
329 #if defined(HOST_DATA_SUPPORTED)
330  const IHostData& host);
331 #else
332  tstring host);
333 #endif
334 
335  bool connect(
336 #if defined(HOST_DATA_SUPPORTED)
337  const IHostData& host,
338 #else
339  tstring host,
340 #endif
341  unsigned int origin);
342 
343  bool setNewTunnelGroup(const tstring & group);
344 
345  void disconnect();
346 
347  void cancel();
348 
349  void resetStats();
350 
351  void getState();
352 
353  VPNState getCurrentVPNState();
354  VPNSubState getCurrentVPNSubState();
355  VPNSubState getPreviousVPNSubState();
356 
357  STATE getCurrentState();
358 
359  tstring getStateText();
360  static tstring getNoticeTypeText(MessageType msgType);
361 
362  static tstring getStateText(VPNState state,
363  VPNSubState subState = VPNSS_NORMAL,
364  NETENV_STATE netEnvState = NES_NETWORK_ACCESSIBLE,
365  const tstring& tstrConnectedHost = tstring());
366 
367  void setNetworkStates(NETENV_STATE netEnvState,
368  NETCTRL_STATE netCtrlState,
369  NETWORK_TYPE netType,
370  bool bACBrowserForCPRemediation,
371  bool bUpdateUI);
372  void refreshOperatingModeForCurrentNetStates();
373  NETENV_STATE getCurrentNetEnvState();
374  NETENV_STATE getPreviousNetEnvState();
375  NETCTRL_STATE getCurrentNetCtrlState();
376  NETWORK_TYPE getCurrentNetType();
377  bool isACBrowserForCPRemediation();
378 
379  static tstring getNetCtrlText(NETCTRL_STATE netCtrlState);
380  static tstring getNetEnvText(NETENV_STATE netEnvState,
381  bool bSimple = false);
382  static tstring getNetTypeText(NETWORK_TYPE netType);
383  static tstring getQuarantinedStatusText();
384  static tstring getNetworkStatusSimpleText(const NETENV_STATE netEnvState,
385  const NETCTRL_STATE netCtrlState);
386 
387  // can't be static due to requiring operating mode information
388  tstring getNetworkStatusText(const VPNState state,
389  const VPNSubState subState,
390  const NETENV_STATE netEnvState,
391  const NETCTRL_STATE netCtrlState);
392 
393  PreferenceInfo& getPreferences();
394 
395  bool savePreferences();
396 
397  void startStats();
398 
399  void stopStats();
400 
401  void UserSubmit();
402 
403  void setBanner(const tstring &banner);
404  void setBannerResponse(bool bResponse);
405 
406  void setPreConnectReminder(const tstring &tstrPreConnectReminder);
407  void setPreConnectReminderResponse();
408 
409  bool getUserResponse();
410  bool isUserResponseSet();
411 
412  void setCertBlocked(const tstring &tstrUntrustedServer);
413  void setCertWarning(const tstring &rtstrUntrustedServer,
414  const std::list<tstring> &rltstrCertErrors,
415  bool bAllowImport);
416 #if defined(PLATFORM_WIN_APP)
417  void setCertWarning(const tstring &rtstrUntrustedServer,
418  const std::list<tstring> &rltstrCertErrors,
419  const std::vector<uint8_t>& rvServerCertDER,
420  bool bAllowImport);
421 #endif
422  bool getCertImportResponse();
423 
424 #if defined(PLATFORM_APPLE_SSLVPN) || defined(PLATFORM_ANDROID) || defined(PLATFORM_CHROMEBOOK)
425  void setCertBanner(tstring tstrCertBannerSummary,
426  uint32_t nCertBannerCertLen,
427  const uint8_t *pCertBannerCertDer,
428  const std::list<tstring> &confirmReasons,
429  const std::list<CertConfirmReason> &confirmReasonEnums,
430  bool bImportAllowed);
431 
432  void setCertBannerResponse(bool bResponse, bool bImportCert);
433  void importServerCert(std::vector<uint8_t> certData);
434  bool setFipsMode(bool bEnableFips);
435 #if defined(PLATFORM_ANDROID)
436  bool setStrictMode(bool bEnableStrictMode);
437  bool setRevocationEnabled(bool bRevocationEnabled);
438  bool IsRevocationEnabled();
439 #endif // currently supported only for android
440 #endif
441 
442  void setUserPrompt(ConnectPromptInfo &ConnectPrompt);
443 
444 #if defined(PLATFORM_ANDROID)
445  void setClientCertResponse(std::vector< std::pair<uint32_t, uint8_t*> > &derList);
446  void setAgentDetached();
447  bool getClientCertificates();
448 #endif
449 
450 #if defined(PLATFORM_APPLE_SSLVPN) || defined(PLATFORM_ANDROID)
451  void setSCEPEnrollInProgress(bool bInProgress);
452  bool isSCEPEnrollInProgress();
453 #endif
454 
455 #if defined(MANUAL_PKCS12_IMPORT_SUPPORTED)
456  void setImportPKCS12Result(const std::vector<uint8_t> &certHash, const tstring &tstrError);
457  bool requestImportPKCS12(const std::vector<uint8_t> &data);
458  std::vector<uint8_t> importPKCS12WithPassword(const std::vector<uint8_t> &data, const tstring &password);
459 #endif
460 
461  void setCertBlockedResponse(bool bUnlock);
462  void setCertWarningResponse(bool bConnect, bool bImportCert);
463 
464  void insertStateToConnectPrompt(ConnectPromptInfo &ConnectPrompt);
465 
466  void ExitNotice(const tstring &tstrNotice, const int code = 0);
467 
468  void notice(const tstring &tstrNotice,
469  const MessageType type = MsgType_Info,
470  bool bClearLastMsg = false,
471  bool bForce = false,
472  bool bStateMsg = false,
473  bool bSensitiveMsg = false);
474 
475  void notice(MsgWithArg &notice,
476  const MessageType type = MsgType_Info,
477  bool bClearLastMsg = false,
478  bool bForce = false,
479  bool bStateMsg = false,
480  bool bSensitiveMsg = false);
481 
482  void getStats(void);
483 
484  void setStats(VPNStats &stats);
485 
486  void exportStats(const tstring &tstrFilePath);
487 
488  void initState(VPNState state,
489  VPNState previousState,
490  VPNSubState subState);
491 
492  void setState(VPNState state,
493  VPNState previousState,
494  VPNSubState subState = VPNSS_NORMAL,
495  bool bUpdateStateMsg = true,
496  bool bOnlyUpdateUI = false);
497 
498 #if defined(PROGRAM_DATA_IMPORT_SUPPORTED)
499  IACImporterAsync *createACImporter(IACImporterAsyncCB *pCallback);
500 #endif
501 
502  void setWMHint(WMHint hint,
503  WMHintReason reason);
504 
505  bool isLastConnectType (const ConnectPromptType connPromptType);
506 
507  bool isOperatingMode(OperatingMode opMode);
508  void setOperatingMode(OperatingMode opMode);
509  void unsetOperatingMode(OperatingMode opMode);
510 
511  bool CanRemediateCaptivePortal();
512  bool policyAllowsCaptivePortalRemediation();
513 
514  bool isEventShutdown();
515 
516  bool isUsingEventModel();
517 
518  time_t getLastDisconnectTime();
519 
520  ConnectPromptInfo getConnectPromptInfo();
521  void resetConnectPromptPasswordData();
522 
523  void setStandaloneConnection(bool isStandalone);
524 
525  void deliverActiveHost(const tstring &activeHost,
526  ConnectProtocolType vpnProtocol = PROTOCOL_TYPE_UNKNOWN,
527  bool bActiveHostFriendlyName = false);
528 
529  bool isVPNServiceReady();
530 
531  // reset last disconnect time indicator.
532  //
533  void resetLastDisconnectTime(time_t time = 1);
534 
535  void processMinimize();
536 
537  // cert enrollment
538  void setEnrollClientCert(CertObj* pCert);
539 
540  // Show user banner for cert import warning on linux
541  // SCEPIfc to ConnectMgr
542  void linuxCertImportWarnUser();
543 
544  // Response to cert warning on linux
545  // ConnectMgr to SCEPIfc
546  void linuxCertImportWarnUserResponse(bool bAccept);
547 
548  void setDefaultHost(tstring &host);
549 
550 #if defined(HOST_DATA_SUPPORTED)
551  void setDefaultHostProfile(const IHostData &hostProfile);
552  IHostData* getDefaultHostData();
553 #endif
554 
555  void setLastVpnError(VPNError vpnError);
556  VPNError getLastVpnError();
557 
558 #if defined(PLATFORM_ANDROID)
559  bool requestClientCertificates();
560 #endif
561 
562  bool requestImportLocalization(const tstring tstrLocale,
563  const std::vector<unsigned char> &MoFileData);
564 
565  // Start the Automatic Headend Selection operation
566  void startAHS(const unsigned int uiReason,
567  const ProxyIfc& proxy);
568  // statusReturnCode is a long to match the current type of STATUSCODE.
569  // It is not using a STATUSCODE directly so that we do not have to
570  // expose the header files for STATUSCODEs to ClientIfcBase.h
571  void AHSSelectedHost(const unsigned int uiReason,
572  const std::vector<tstring> &headendList,
573  const long statusReturnCode,
574  const tstring& extraInfo);
575  std::vector<tstring> getAHSHostList();
576  unsigned int getAHSState();
577  bool isAHSHasRun();
578  bool IsAHSCachingRestricted();
579 
580  bool suppressConnectionErrorPopups();
581 
582  tstring getCaptivePortalDetectedMsg();
583 
584  void setProxyAuthPrompts(ProxyIfc* pProxy,
585  const tstring& promptMsg);
586 
587 #if defined(INTERPROCESS_COMMUNICATION_SUPPORTED)
588  bool handleIpcMessage(CIpcMessage *pIpcMessage);
589 #if defined(VPNAPI_EVENT_NOTIFICATION_SUPPORTED)
590  void signalDisconnectedToEventNtfctnThread();
591 #endif
592 #endif
593  bool IsCsdTokenVerified() const;
594 
595 #if defined(PLATFORM_APPLE_SSLVPN) || defined(PLATFORM_ANDROID)
596  virtual void SCEPEnrollStartCB();
597  virtual void SCEPEnrollExitCB();
598 #endif
599 
600  void activateConnectMgrTunnelInitiationCompletionEvent();
601  bool isConnectRequestActive();
602  bool isConnectRequestCleanup();
603 #if defined(PLATFORM_ANDROID) || defined(PLATFORM_CHROMEBOOK)
604  bool deleteProfileByName(const tstring &profileName);
605  tstring getProfileContents(const tstring &profileName);
606  bool importProfile(const tstring &profileName, const tstring &profileContents);
607 #endif
608 
609  bool syncProfileChange(const tstring &profileName);
610 
611 #if defined(CREDENTIAL_PREFILL_SUPPORTED)
612  bool hasPrefilledCredentials();
613  bool prefillCredentials(ConnectPromptInfo &connectPrompt);
614  void setPrefilledCredentials(CredentialPrefill *prefill);
615 #endif
616 
617 #if defined(PLATFORM_ANDROID) || defined(PLATFORM_APPLE_SSLVPN)
618  std::list<ManagedCertificate *> enumerateCertificates(CertificateType certType);
619  bool deleteCertificates(CertificateType certType, const std::list<std::string> &idList);
620  bool deleteServerCertificates(const std::list<std::string> &idList);
621 #endif
622 
623 #if defined(ANYCONNECT_USE_SNAK) && !defined(PLATFORM_WIN_APP)
624  std::list<ManagedCertificate *> enumerateSNAKCertificates(SNAK_CertType certType);
625  SNAK_CertType getSNAKCertType(CertificateType certType);
626  bool deleteClientCertificates(const std::list<std::string> &idList);
627 #endif
628 
629 #if defined(PLATFORM_APPLE_SSLVPN)
630  bool canUseBackupServers();
631 #endif
632 
633  tstring getConnectHost();
634 
635  tstring getMgmtTunnelHostname();
636 
637  VPN_TUNNEL_SCOPE getVpnTunnelScope();
638 
639  bool isStandaloneConnection();
640 
641  void sendSSoLogoutPrompt(ConnectPromptInfo &cpi);
642 
643  void setExternalSSOLogoutUrlFromAgent(const tstring& logoutUrl);
644 
645 private:
646 
647  //
648  // Private Member Data
649  //
650 
651 #if defined(VPNAPI_TRANSMIGRATION_SUPPORTED)
652  std::shared_ptr<CSharedAccessLock> m_spClientIfcInternalPtrSharedAccessLock;
653 #endif
654  std::unique_ptr<ClientIfcInternal> m_upClientIfcInternal;
655 
656 
657  //
658  // Private Member Methods
659  //
660 
661  // Prevent copying by declaring but not defining copy constructor and operator= methods.
662  //
663  ClientIfcBase(const ClientIfcBase& other);
664  ClientIfcBase& operator=(const ClientIfcBase& other);
665 };
666 
667 #endif // _CLIENTIFCBASE_
Definition: api.h:113
ConnectPromptType
Definition: api.h:235
Definition: PreferenceInfo.h:26
WMHintReason
Definition: api.h:211
VPNState
Definition: api.h:146
Definition: ClientIfcBase.h:63
#define tstring
Definition: api.h:35
WMHint
Definition: api.h:192
Definition: ConnectPromptInfo.h:37
MessageType
Definition: api.h:108
OperatingMode
Definition: api.h:538
VPNSubState
Definition: api.h:170
VPNError
Definition: api.h:590
Definition: VPNStats.h:35