Tuesday, 10 April 2012

WI - Security


Key requirements for C2 security rating
- A Secure logon facility
- Discretionary access control
- Security Auditing
- Object reuse protection

Windows also meets two requirements of B-level security
- Trusted path functionality (Ctrl+Alt+Del)
- Trusted facility management

2 Security System Components
These are the core components and databases that implement Windows Security

1. Security reference monitor (SRM) that is responsible for defining the access token data structure to represent a security context, performing security access checks on objects, manipulating priviledges (user rights), and generating any resulting security audit messages.

2. Local security authority subsystem (lsass) is responsible for local system security policy, user authentication, and sending security audit messages to the Event log.

3. Lsass policy database. A database that contains the local system security policy settings, this is stored in HKLM\SECURITY. It includes such information as what domains are entrusted to authenticate logon attempts, who has permission to access the system and how (interactive, network, and service logons), who is assigned which privileges, and what kind of security auditing is to be performed. The Lsass policy database also stores "secrets" that include logon information used for caching domain logons and Windows service user-account logons.

4. Security accounts manager (SAM) service. A set of subroutines responsible for managing the database that contains user names and groups defined on the local machine. The SAM service, which is implemented in samsrv.dll, runs in the Lsass process.

5. SAM database. A database that on systems not functioning as domain controllers contains the defined local users and groups, along with their passwords and other attributes. On domain controllers, the SAM stores the system’s administrator recovery account definition and password. This database is stored in the registry under HKLM\SAM.

6. Active Directory A directory service that contains a database that stores information about objects in a domain. The Active Directory server, implemented as %SystemRoot%\System32\Ntdsa.dll, runs in the Lsass process.

7. Authentication packages These include dynamic-link libraries (DLLs) that run both in the context of the Lsass process and client processes and that implement Windows authentication policy. An authentication DLL is responsible for checking whether a given user name and password match, and if so, returning to the Lsass information detailing the user’s security identity, which Lsass uses to generate a token.

8. Interactive logon manager (Winlogon) A user-mode process running %System-Root%\System32\Winlogon.exe that is responsible for responding to the SAS and for managing interactive logon sessions. Winlogon creates a user’s first process when the user logs on, for example.

9. Logon user interface (LogonUI) A user-mode process that presents users with the user interface they can use to authenticate themselves on the system. Uses credential providers to query user credentials through various methods.

10. Credential providers (CPs) In-process COM objects that run in the LogonUI process (started on demand by Winlogon when the SAS is performed) and used to obtain a user’s name and password, smartcard PIN, or biometric data (such as a fingerprint). The standard CPs are %SystemRoot%\System32\authui.dll and %SystemRoot%\System32\SmartcardCredentialProvider.dll

11. Network logon service (Netlogon) A Windows service (%SystemRoot%\System32\Netlogon.dll) that sets up the secure channel to a domain controller, over which security requests—such as an interactive logon (if the domain controller is running Windows NT 4) or LAN Manager and NT LAN Manager (v1 and v2) authentication validation—are sent.

12. Kernel Security Device Driver (KSecDD) A kernel-mode library of functions that implement the local procedure call (LPC) interfaces that other kernel-mode security components, including the Encrypting File System (EFS), use to communicate with Lsass in user mode. KSecDD is located in %SystemRoot%\System32\Drivers\Ksecdd.sys.



SRM, which runs in kernel mode, and Lsass, which runs in user mode, communicate using ALPC facility.

During system initialization, the SRM creates a port, named SeRmCommandPort, to which Lsass connects. When the Lsass process starts, it creates an ALPC port named SeLsaCommandPort. The SRM connects to this port, resulting in the creation of private communication ports. The SRM creates a shared memory section for messages longer than 256 bytes, passing a handle in the connect call. Once the SRM and Lsass connect to each other during system initialization, they no longer listen on their respective connect ports. Therefore, a later user process has no way to connect successfully to either of these ports for malicious purposes—the connect request will never complete.




3. Protecting Objects

Object protection and access logging is the essence of discretionary access control and auditing. The objects that can be protected on Windows include files, devices, mailslots, pipes (named and anonymous), jobs, processes, threads, events, keyed events, event pairs, mutexes, semaphores, shared memory sections, I/O completion ports, LPC ports, waitable timers, access tokens, volumes, window stations, desktops, network shares, services, registry keys, printers, and Active Directory objects.


The Windows object manager plays a key role in enforcing object security.

3.1 Access Checks

A thread should specify what access its needs on an object, when opened, so that object manager can validate them through SRM.

Mutexes, events, and semaphores rely on default security.

The essence of the SRM's security model is an equation that takes three inputs: the security identity of a thread, the access that a thread wants to an object, and the security settings of the object.

Security Identifiers (SIDs)
Windows uses SIDs. Users have SIDs, and so do local and domain groups, local computers, domains and domain users. It is a 48 bit identifier authority value and a variable number of 32-bit subauthority or relative identifier (RID) values.

The authority value identifies the agent that issued the SID, Subauthority values identify trustees relative to the issuing authority.

RIDs for user accounts and groups start at 1000 and increase in increments of 1 for each new user or group.




Winlogon creates a unique logon SID for each interactive logon session. A typical use of a logon SID is in an access control entry (ACE) that allows access for the duration of a client’s logon session. The SID for a logon session is S-1-5-5-0, and the RID is randomly generated.



Integrity Levels:

integrity levels can override discretionary access to differentiate a process and objects running as and owned by the same user, offering the ability to isolate code and data within a user account.


Every process has an integrity level that is represented in the process's token and propagated according to following rules:
1. A process inherits the integrity level of its parent.
2. If the file object for the executable image to which the child process belongs has an integrity level and the parent's integrity level is medium or higher, the child process will inherit the lower of the two.
3. A parent process can also create child process with an explicit integrity level

Objects also have an integrity level that is stored as part of their security descriptor, in a structure called the mandatory label. The objects have implicit integrity level which is medium.


Apart from an integrity level, objects also have a mandatory policy, which defines the actual level of protection that’s applied based on the integrity level check. Three types are possible, shown in Table below. The integrity level and the mandatory policy are stored together in the same ACE.



Tokens

The SRM uses an object called a token (or access token) to identify the security context of a process or thread. A security context consists of information that describes the privileges, accounts, and groups associated with the process or thread. Tokens also include information such as the session ID, the integrity level, and UAC virtualization state.

The security mechanism in Windows use two components to determine what objects can be accessed and what secure operations can be performed. One component comprises the token's user account SID and group SID fields. The SRM uses SID fields to determine if the process or thread can obtain the requested access to a securable object.
The second component  is the privilege array. A token's privilege array is the list of rights associated with the token.

Token's type distinguishes a primary token from impersonation token. Impersonation tokens carry an impersonation level that signifies what type of impersonation is active in the token.

A token also include a mandatory policy for the process or thread how MIC will behave when processing this token.  There are two policies.
1. TOKEN_MANDATORY_NO_WRITE_UP. It is enabled by default.
2. TOKEN_MANDATORY_NEW_PROCESS_MIN. It is also enabled by default.

The field in a token are immutable.

Impersonation
Thread-control data structure contain optional entry for an impersonation token. However, thread's primary token, which represents the thread's real security credentials, is always accessible in process's control structure.

Restricted Tokens:
Restricted token is created from primary or impersonation token using Create-RestrictedToken function. It is copy of it with following possible modifications.
1. Privileges can be removed from the token's privilege array.
2. SIDs in the token can be marked as deny-only.
3. SIDs in the token can be marked as restricted.

Filtered Admin Token 
A filtered admin token as following characteristics.
1. The integrity level is set to medium.
2. The administrator and administrator like SIDs are marked as deny-only to prevent security holes if the group was removed altogether.
3. All privileges are stripped except Change Notify, Shutdown, Undock, Increase Working Set, and Time Zone.

Security Description and Access Control
Security descriptor is the data structure that specifies who can perform what actions on the object.
Security descriptor consists of following attributes:
1. Revision number: The version number that SRM security model used to create the descriptor.
2. Flags optional modifiers that define the behaviour or characteristics of the descriptor.
3. Owner SID
4. Group SID
5. Discretionary access control list (DACL) specifies who has what access to the object.
6. System access control list (SACL) specifies which operations by which users should be logged in the security audit log and the explicit integrity level of an object.

Access control list (ACL) is made up of a header and zero or more access control entry (ACE) structures. There are two types of ACLs: DACL and SACL. In DACL, each ACE contains a SID and access mask (and set of flags). Eight types of ACEs can appear in DACL.: access allowed, access denied, allowed-object, denied-object, allowed-callback, denied-callback, allowed-object-callback, denied-object-callback.

Accumulation of access rights granted by individual ACEs forms the set of access rights granted by an ACL. If no DACL is present in a security descriptor, everyone has the access to the object. If the DACL empty (that is, it has 0 ACE), no user has access to the object.
The ACEs used in DACL also have a set of  flags that control and specify characteristics  of the ACE related to inheritance.

A SACL contains two types of ACEs: System audit ACEs  and system audit-object ACEs. These ACEs specify which operations performed on the object by specific users or groups should be audited.

If a SACL is null, no auditing takes place on the object.

The inheritance flags that apply to DACL ACEs also apply to system audit and system audit-object ACEs.

To determine which DACL to assign to a new object, the security system uses first applicable rule  of the following assignment rules.

1. If the caller explicitly provides a security descriptor  when the object is created, the security systems applies it to the object. If the object has a name and resides in a container object (for example, a named event object in the \BaseNamedObjects object manager namespace directory), the system merges any inheritable ACEs (ACEs that might propagate from the object’s container) into the DACL unless the security descriptor has the SE_DACL_PROTECTED flag set, which prevents inheritance.

2. If a caller doesn’t supply a security descriptor and the object has a name, the security system looks at the security descriptor in the container in which the new object name is stored. Some of the object directory’s ACEs might be marked as inheritable, meaning that they should be applied to new objects created in the object directory. If any of these inheritable ACEs are present, the security system forms them into an ACL, which it attaches to the new object.

3. If no security descriptor is specified and the object doesn’t inherit any ACEs, the security system retrieves the default DACL from the caller’s access token and applies it to the new object. Several subsystems on Windows have hard-coded DACLs that they assign on object creation

4. If there is no specified descriptor, no inherited ACEs, and no default DACL, the system creates the object with no DACL, which allows everyone (all users and groups) full access to the object. This rule is the same as the third rule in which a token contains a null default DACL.


The rules the system uses when assigning a SACL to a new object are similar to those used for DACL assignment, with some exceptions. The first is that inherited system audit ACEs don’t propagate to objects with security descriptors marked with the SE_SACL_PROTECTED flag (similar to the SE_DACL_PROTECTED flag, which protects DACLs). Second, if there are no specified security audit ACEs and there is no inherited SACL, no SACL is applied to the object. This behavior is different from that used to apply default DACLs because tokens don’t have a default SACL.



The system uses the following rules for propagating inheritable ACEs:
1.If a child object with no DACL inherits an ACE, the result is a child object with a DACL containing only the inherited ACE.
2. If a child object with an empty DACL inherits an ACE, the result is a child object with a DACL containing only the inherited ACE.
3. For objects in Active Directory only, if an inheritable ACE is removed from a parent object, automatic inheritance removes any copies of the ACE inherited by child objects.
4. For objects in Active Directory only, if automatic inheritance results in the removal of all ACEs from a child object’s DACL, the child object has an empty DACL rather than no DACL.


The order of ACEs in an ACL is an important aspect of the Windows security model.

Determining Access
Two methods are used for determining access to an object:
1. The mandatory integrity check, which determines whether the integrity level of the caller is high enough to access the resource, based on the resource’s own integrity level and its mandatory policy.
2. The discretionary access check, which determines the access that a specific user account has to an object.


With the default integrity policy, processes can open any object—with the exception of process, thread, and token objects—for read access as long as the object’s DACL grants them read access.


user interface Privilege isolation (uiPi)

The Windows messaging subsystem also honors integrity levels to implement UIPI. The subsystem does this by preventing a process from sending window messages to the windows owned by a process having a higher integrity level, with the following informational messages being exceptions:
■ WM_NULL
■ WM_MOVE
■ WM_SIZE
■ WM_GETTEXT
■ WM_GETTEXTLENGTH
■ WM_GETHOTKEY
■ WM_GETICON
■ WM_RENDERFORMAT
■ WM_DRAWCLIPBOARD
■ WM_CHANGECBCHAIN
■ WM_THEMECHANGED


After the integrity check is complete, and assuming the mandatory policy allows access to the object based on the caller’s integrity, one of two algorithms is used for the discretionary check to an object, which will determine the final outcome of the access check:


1. One to determine the maximum access allowed to the object, a form of which is exported to user mode with the Windows GetEffectiveRightsFromAcl function. This is also used when a program specifies a desired access of MAXIMUM_ALLOWED, which is what the legacy APIs that don’t have a desired access parameter use.

2. One to determine whether a specific desired access is allowed, which can be done with the Windows AccessCheck function or the AccessCheckByType function.

The first algorithm examines the entries in the DACL as follows:
1. If the object has no DACL (a null DACL), the object has no protection and the security system grants all access.
2. If the caller has the take-ownership privilege, the security system grants write-owner access before examining the DACL.
3. If the caller is the owner of the object, the system looks for an OWNER_RIGHTS SID and uses that SID as the SID for the next steps. Otherwise, read-control and write-DACL access rights are granted.
4. For each access-denied ACE that contains a SID that matches one in the caller’s access token, the ACE’s access mask is removed from the granted-access mask.
5. For each access-allowed ACE that contains a SID that matches one in the caller’s access token, the ACE’s access mask is added to the granted-access mask being computed, unless that access has already been denied.
The preceding description applies only to the kernel-mode form of the algorithm. The Windows version implemented by GetEffectiveRightsFromAcl differs in that it doesn’t perform step 2, and it considers a single user or group SID rather than an access token.

Owner Rights


The Owner Rights SID exists for two main reasons: improving service hardening in the operating system, and allowing more flexibility for specific usage scenarios.


Whenever a service creates an object at run time, the Owner SID associated with that object is the account the service is running in (such as local system or local service) and not the actual service SID. This means that any other service in the same account would have access to the object by being an owner. The Owner Rights SID prevents that unwanted behavior.


The second algorithm is used to determine whether a specific access request can be granted, based on the caller’s access token. Each open function in the Windows API that deals with securable objects has a parameter that specifies the desired access mask, which is the last component of the security equation. To determine whether the caller has access, the following steps are performed:

1. If the object has no DACL (a null DACL), the object has no protection and the security system grants the desired access.
2. If the caller has the take-ownership privilege, the security system grants write-owner access if requested and then examines the DACL. However, if write-owner access was the only access requested by a caller with take-ownership privilege, the security system grants that access and never examines the DACL.



3. If the caller is the owner of the object, the system looks for an OWNER_RIGHTS SID and uses that SID as the SID for the next steps. Otherwise, read-control and write-DACL access rights are granted. If these rights were the only access rights that the caller requested, access is granted without examining the DACL
4. Each ACE in the DACL is examined from first to last. An ACE is processed if one of the following conditions is satisfied:

  1. The ACE is an access-deny ACE, and the SID in the ACE matches an enabled SID (SIDs can be enabled or disabled) or a deny-only SID in the caller’s access token. 
  2. The ACE is an access-allowed ACE, and the SID in the ACE matches an enabled SID in the caller’s token that isn’t of type deny-only.
  3. It is the second pass through the descriptor for restricted-SID checks, and the SID in theACE matches a restricted SID in the caller’s access token.
  4. The ACE isn’t marked as inherit-only.
5. If it is an access-allowed ACE, the rights in the access mask in the ACE that were requested are granted; if all the requested access rights have been granted, the access check succeeds. If it is an access-denied ACE and any of the requested access rights are in the denied-access rights, access is denied to the object.
6. If the end of the DACL is reached and some of the requested access rights still haven’t been granted, access is denied.
7. If all accesses are granted but the caller’s access token has at least one restricted SID, the system rescans the DACL’s ACEs looking for ACEs with access-mask matches for the accesses the user is requesting and a match of the ACE’s SID with any of the caller’s restricted SIDs. Only if both scans of the DACL grant the requested access rights is the user granted access to the object.


Because it wouldn’t be efficient for the security system to process the DACL every time a process uses a handle, the SRM makes this access check only when a handle is opened, not each time the handle is used. Thus, once a process successfully opens a handle, the security system can’t revoke the access rights that have been granted, even if the object’s DACL changes. Also keep in mind that because kernel-mode code uses pointers rather than handles to access objects, the access check isn’t performed when the operating system uses objects. In other words, the Windows executive “trusts” itself in a security sense.

The authZ aPi


The AuthZ Windows API implements the same security model as the security reference monitor, but it implements the model totally in user mode in the %SystemRoot%\System32\Authz.dll library. This gives applications that want to protect their own private objects, such as database tables, the ability to leverage the Windows security model without incurring the cost of user-mode to kernel-mode transitions that they would make if they relied on the security reference monitor.

4. Account Rights and Privileges



A privilege is the right of an account to perform a particular system-related operation, such as shutting down the computer or changing the system time. An account right grants or denies the account to which it’s assigned the ability to perform a particular type of logon, such as a local logon or interactive logon, to a computer.

4.1 Account Rights

Account rights are not enforced by the security reference monitor, nor are they stored in tokens.


Windows applications can add and remove user rights from an account by using the LsaAddAccountRights and LsaRemoveAccountRights functions, and they can determine what rights are assigned to an account with LsaEnumerateAccountRights.

4.2 Privileges

Unlike user rights, which are enforced in one place by the LSA, different privileges are defined by different
components and enforced by those components.
Unlike account rights, privileges can be enabled and disabled.

Table of privileges


Privilege
User Right
Privilege Usage
SeAssignPrimaryTokenPrivilege
Replace a process- level token
Checked for by various components, such as NtSetInformationJob, that set a process's token.
SeAuditPrivilege
Generate security audits
Required to generate events for the Security event log with the ReportEvent API.
SeBackupPrivilege
Backup files and directories
Causes NTFS to grant the following access to any file or directory, regardless of the security descriptor that's present:READ_CONTROLACCESS_SYSTEM_SECURITYFILE_GENERIC_READFILE_TRAVERSENote that when opening a file for backup, the caller must specify the FILE_FLAG_BACKUP_SEMANTICS flag.
SeChangeNotifyPrivilege
Bypass traverse checking
Used by NTFS to avoid checking permissions on intermediate directories of a multilevel directory lookup. Also used by file systems when applications register for notification of changes to the file system structure.
SeCreateGlobalPrivilege
Create global objects
Required for a process to create section and symbolic link objects in the directories of the Object Manager namespace that are assigned to a different session than the caller.
SeCreatePagefilePrivilege
Create a pagefile
Checked for by NtCreatePagingFile, which is the function used to create a new paging file.
SeCreatePermanentPrivilege
Create permanent shared objects
Checked for by the object manager when creating a permanent object (one that doesn't get deallocated when there are no more references to it).
SeCreateTokenPrivilege
Create a token object
NtCreateToken, the function that creates a token object, checks for this privilege.
SeDebugPrivilege
Debug programs
If the caller has this privilege enabled, the Process Manager allows access to any process using NtOpenProcess, regardless of the process's security descriptor.
SeEnableDelegationPrivilege
Enable computer and user accounts to be trusted for delegation
Used by Active Directory services to delegate authenticated credentials.
SeImpersonatePrivilege[2]
Impersonate a client after authentication
The Process Manager checks for this when a thread wants to use a token for impersonation and the token represents a different user than that of the thread's process token.
SeIncreaseBasePriorityPrivilege
Increase scheduling priority
Checked for by the Process Manager and is required to raise the priority of a process.
SeIncreaseQuotaPrivilege
Windows 2000:Increase quotas Windows XP/ Windows Server 2003: Adjust memory quotas for a process
Enforced when changing the Registry's quota (Windows 2000 only), a process's working set thresholds, and a process's paged and nonpaged pool quotas.
SeLoadDriverPrivilege
Load and unload device drivers
Checked for by the NtLoadDriver and NtUnload- Driver driver functions.
SeLockMemoryPrivilege
Lock pages in memory
Checked for by NtLockVirtualMemory, the kernel implementation of VirtualLock.
SeMachineAccountPrivilege
Add workstations to the domain
Checked for by the Security Accounts Manager on a domain controller when creating a machine account in a domain.
SeManageVolumePrivilege
Perform volume maintenance tasks
Enforced by file system drivers during a volume open operation, which is required to perform disk checking and defragmenting activities.
SeProfileSingleProcessPrivilege
Profile single process
Checked for by prefetcher's function that returns prefetch information for an individual process.
SeRemoteShutdownPrivilege
Force shutdown from a remote system
Winlogon checks that remote callers of the InitiateSystemShutdown function have this privilege.
SeRestorePrivilege
Restore files and directories
This privilege causes NTFS to grant the following access to any file or directory, regardless of the security descriptor that's present:WRITE_DAC WRITE_OWNER ACCESS_SYSTEM_SECURITY FILE_GENERIC_WRITE FILE_ADD_FILE FILE_ADD_SUBDIRECTORY DELETENote that when opening a file for restore, the caller must specify the FILE_FLAG_BACKUP_SEMANTICS flag.
SeSecurityPrivilege
Manage auditing and security log
Required to access the SACL of a security descriptor, read and clear the security event log.
SeShutdownPrivilege
Shut down the system
This privilege is checked for by NtShutdownSystem and NtRaiseHardError, which presents a system error dialog box on the interactive console.
SeSyncAgentPrivilege
Synchronize directory service data
Required to use the LDAP directory synchronization services and allows the holder to read all objects and properties in the directory, regardless of the protection on the objects and properties.
SeSystemEnvironmentPrivilege
Modify firmware environment variables
Required by NtSetSystemEnvironmentValue and NtQuerySystemEnvironmentValue to modify and read firmware environment variables using the HAL.
SeSystemProfilePrivilege
Profile system performance
Checked for by NtCreateProfile, the function used to perform profiling of the system. This is used by the Kernprof tool, for example.
SeSystemtimePrivilege
Change the system time
Required to change the time or date.
SeTakeOwnership
Take ownership of files and other object
Required to take ownership of an object without being granted discretionary access.
SeTcbPrivilege
Act as part of the operating system
Checked for by the Security Reference Monitor when the session ID is set in a token, by the Plug and Play Manager for Plug and Play event creation and management, the Windows 2000 implementation of LogonUser, BroadcastSystemMessageEx when called with BSM_ALLDESKTOPS, and LsaRegisterLogonProcess.
SeUndockPrivilege
Remove computer from a docking station
Checked for by the user-mode Plug and Play Manager when either a computer undock is initiated or a device eject request is made.


4.3 Super Privileges

5 Security Auditing

Two privileges, SeSecurityPrivilege and SeAuditPrivilege, relate to auditing. A process must have the SeSecurityPrivilege privilege to manage the security Event Log and to view or set an object’s SACL. Processes that call audit system services, however, must have the SeAuditPrivilege privilege to successfully generate an audit record.
The audit policy of the local system controls the decision to audit a particular type of security event. The audit policy, also called the local security policy, is one part of the security policy Lsass maintains on the local system, and it is configured with the Local Security Policy Editor

6 Logon
6.1 Winlogon Initialization

During system initialization, before any user applications are active, Winlogon performs the following steps to ensure that it controls the workstation once the system is ready for user interaction:

1. Creates and opens an interactive window station (for example, \Sessions\1\Windows \WindowStations\WinSta0 in the object manager namespace) to represent the keyboard, mouse, and monitor. Winlogon creates a security descriptor for the station that has one and only one ACE  containing only the System SID. This unique security descriptor ensures that no other process can access the workstation unless explicitly allowed by Winlogon.

2. Creates and opens two desktops: an application desktop (\Sessions\1\Windows\WinSta0 \Default, also known as the interactive desktop) and a Winlogon desktop (\Sessions\1\Windows \WinSta0\Winlogon, also known as the secure desktop). The security on the Winlogon desktop is created so that only Winlogon can access that desktop. The other desktop allows both Winlogon and users to access it. This arrangement means that any time the Winlogon desktop is active, no other process has access to any active code or data associated with the desktop. Windows uses this feature to protect the secure operations that involve passwords and locking and unlocking the desktop.

3. Before anyone logs on to a computer, the visible desktop is Winlogon’s. After a user logs on, pressing Ctrl+Alt+Delete switches the desktop from Default to Winlogon and launches LogonUI. (This explains why all the windows on your interactive desktop seem to disappear when you press Ctrl+Alt+Delete and then return when you dismiss the Windows Security dialog box.) Thus, the SAS always brings up a secure desktop controlled by Winlogon.

4. Establishes an ALPC connection with Lsass’s LsaAuthenticationPort. This connection will be used for exchanging information during logon, logoff, and password operations and is made by calling LsaRegisterLogonProcess.

5. It initializes and registers a window class data structure that associates a Winlogon procedure with the window it subsequently creates.

6. It registers the Winlogon RPC message server, which listens for SAS notifications from Win32k. This measure prevents Trojan horse programs from gaining control of the screen when the SAS is entered.

7. It registers the window so that the procedure associated with this window gets called if a user logs off or if the screen saver times out. The Windows subsystem checks to verify that the process requesting notification is the Winlogon process.

6.2 User Logon Steps























Monday, 9 April 2012

C++

C++ Primer : By Stanley B. Lippman, Josée Lajoie

Chapter 4 : Expressions

The operations applied to the operands are represented by operators.
Operators that act on one operand are unary operators, such as the address-of (&) and dereference (*) operators, whereas operators that act on two operands, such as the addition and subtraction operators, are binary operators.

When two or more operators are combined, the expression is referred to as a compound expression.

The Standard C++ header file limits provides information about an implementation's representation of the built-in types, such as the minimum and maximum value that a type can represent. In addition, the Standard C header files climits and cfloat, also available within a C++ compilation system, define preprocessor macros that provide similar information.

If an implicit type conversion is not possible, the assignment is flagged as an error at compile-time.

The sizeof operator is evaluated at compile-time and so is considered a constant expression.

A comma expression is a series of expressions separated by commas. These expressions are evaluated from left to right. The result of a comma expression is the value of the rightmost expression.

In C++, multiplication and division have a higher precedence than addition. Multiplication and division have the same precedence, however, so that they are evaluated from left to right.

Precedence can be overridden by the use of parentheses, which mark subexpressions. Innermost parentheses are evaluated before outer pairs.

Chapter 5. Statements

The smallest independent unit in a C++ program is a statement. A compound statement is a sequence of simple statements surrounded by a pair of curly braces.

A goto statement may not jump forward over a declaration statement that is not enclosed within a statement block. A backward jump over an initialized object definition, however, is not illegal.

The goto statement is the most deprecated feature of modern programming languages.

 

Chapter 7. Functions

A function call can cause one of two things to happen. If the function has been declared inline, the body of the function may be expanded at the point of its call during compilation; if it is not declared inline, the function is invoked at run-time.

A function must be declared to the program before it is called; otherwise, a compile-time error results. A function can be defined only once in a program.

The declaration of a function consists of the function return type, the name of the function, and the parameter list. These three elements are referred to as the function declaration or function prototype. A function can be declared multiple times in a file.

A function type and the built-in array type cannot be specified as a return type. Rather, we must return a pointer to the element type contained within the array.  The pointer addresses the first element of the array being returned. (It is the responsibility of the user handling the return value to know the size of the array.)

Class types and the container types, in contrast, can be returned directly.

A function must specify a return value; a declaration or definition without an explicit return value results in a compile-time error.

 

 

In C++, it is possible to have two functions with the same name and different parameter lists; the functions are then called overloaded functions.

C++ is a strongly typed language. The arguments of every function call are type-checked during compilation.

A reference must be initialized to an object, and, once initialized, it can never be made to refer to another object. A pointer can address a sequence of different objects or address no object at all.

Because a pointer can either address an object or address no object at all, a function cannot safely dereference a pointer before it first confirms that the pointer actually addresses an object.

With a reference parameter, on the other hand, the function does not need to guard against its referring to no object. A reference must refer to an object, even if we wish otherwise.

One important use of reference parameters is to allow us to implement overloaded operators efficiently while keeping their use intuitive.

Arrays in C++ are never passed by value. Rather, an array is passed as a pointer to its first — that is, zeroth — element. The array's size is not relevant to the declaration of the parameter.

When the parameter is a reference to an array type, the array size becomes part of the parameter and argument types, and the compiler checks that the size of the array argument matches the one specified in the function parameter type.

void putValues( int (&arr)[10] );

 

A function declaration can specify default arguments for all or only a subset of its parameters. The rightmost uninitialized parameter must be supplied with a default argument before any default argument for a parameter to its left can be supplied.

A parameter can have its default argument specified only once in a file. A default argument does not have to be a constant expression. Any expression can be used and is evaluated at the time the function is called.

A linkage directive cannot appear within a function body.

 

 

 

 

Chapter 8. Scope and Lifetime

C++ supports three forms of scope: local scope, namespace scope, and class scope. The outermost namespace scope of a program is called global scope or global namespace scope.

Name resolution is the process by which a name used in an expression is associated with a declaration.

An object defined in global scope without an explicit initializer is guaranteed to have its storage initialized to 0.

The keyword extern provides a method for declaring an object without defining it. It can appear multiple times within the same file or within different files of the same program.

The declaration of a global object that specifies both the extern keyword and an explicit initializer is treated as a definition of that object.

The extern keyword can also be specified with a function declaration. Its only effect is to make the implicit "defined elsewhere" nature of the declaration explicit.

In C++, there exists a mechanism by which the type and number of parameters of a function are encoded in the function name. This mechanism is called type-safe linkage. Type-safe linkage helps the implementation catch mismatches between function declarations in different files.

There are three kinds of local objects: automatic objects, register objects, and local static objects.

The storage in which an automatic object resides lasts from the time the function in which it is declared is invoked to the time the function exits. A register object is an automatic object for which fast read and store of the object's value are supported. A local static object resides in storage that lasts for the entire duration of the program.

Array indexes and pointers occurring within a loop are good candidates for register objects.

Using the keyword register is only a hint to the compiler. Some compilers may ignore this hint and use register allocation algorithms to figure out the best candidates to be placed within the available machine registers.

An uninitialized static local object is automatically initialized to 0 by the program. In contrast, automatic objects have arbitrary values unless they are explicitly initialized.

If the operator new() called by the new expression cannot acquire the requested memory, in general it throws an exception called bad_alloc.

An array allocated on the free store cannot be given an initial set of values. An array of built-in type created on the free store must be initialized within a for loop in which the array elements are initialized one by one.

It is not possible to create a const array of elements of built-in type on the free store for the simple reason that it is not possible to initialize the elements of an array of built-in type created with a new expression. All objects created const on the free store must be initialized, and because a const array cannot be initialized (except for array of classes), attempting to create a const array of built-in type with a new expression results in a compile-time error.

 

Form of new expression in which the programmer can request that the object be created in memory that is already allocated called a placement new expression. There is no delete expression to match a placement new expression.


 

Chapter 9. Overloaded Functions

Two functions are overloaded if they have the same name, are declared in the same scope, and have different parameter lists. Function overloading allows multiple functions that provide a common operation on different parameter types to share a common name.

·         If the parameter lists of the two functions differ in either the number or type of their parameters, the two functions are considered to be overloaded.

·         If both the return type and the parameter list of the two function declarations match exactly, the second declaration is treated as a redeclaration of the first. The parameter names are irrelevant when parameter lists are compared.

·         If the parameter lists of the two functions match exactly but the return types differ, the second declaration is treated as an erroneous redeclaration of the first and is flagged at compile-time as an error. A function's return type is not enough to distinguish between two overloaded functions.

·         If the parameter lists of the two functions differ only in their default arguments, the second declaration is treated as a redeclaration of the first.

When a parameter type is const or volatile, the const or volatile qualifier is not taken into account when the declarations of different functions are identified.

However, if const or volatile applies to the type to which a pointer or reference parameter refers, then the const or volatile qualifier is taken into account when the declarations of different functions are identified.

The functions that are members of two distinct namespaces do not overload one another.

The functions introduced by the using declaration overload the other declarations of the functions with the same name already present in the scope where the using declaration appears. If the using declaration introduces a function in a scope that already has a function of the same name with the same parameter list, then the using declaration is in error.

The steps of function overload resolution are the following:

1.       Identify the set of overloaded functions considered for the call and identify the properties of the argument list in the function call. The functions in this set are called candidate functions.

2.       Select the functions from the set of overloaded functions that can be called with the arguments specified in the call, given the number of arguments and their types. The functions thus selected are called the viable functions.

3.       Select the function that best matches the call. This function is called the best viable function.
The best viable function is the function for which the following apply.

a.       The conversions applied to the arguments are no worse than the conversions necessary to call any other viable function.

b.      The conversions on some arguments are better than the conversions necessary for the same arguments when calling the other viable functions.
If the third step of function overload resolution finds no best viable function, then the function call is ambiguous;

The possible conversions can be grouped into three categories: promotions, standard conversions, and user-defined conversions.

Type conversions are ranked as follows: an exact match is better than a promotion, a promotion is better than a standard conversion, and a standard conversion is better than a user-defined conversion.

The possible conversions in the exact match category are the following conversions:

1.       Lvalue-to-rvalue conversion

2.       Array-to-pointer conversion

3.       Function-to-pointer conversion

4.       Qualification conversions
A qualification conversion affects only pointers. It is a conversion that adds const or volatile qualifiers (or both) to the type to which a pointer points.

The first three conversions in the exact match category (lvalue-to-rvalue, array-to-pointer, and function-to-pointer conversions) are often referred to as lvalue transformations.

Even though lvalue transformations and qualification conversions are in the exact match category, an exact match in which only an lvalue transformation is needed is ranked as better than an exact match requiring a qualification conversion.

An exact match can be forced by the use of an explicit cast.

Details of a Promotion

A promotion is one of the following conversions.

·         An argument of type char, unsigned char, or short is promoted to type int. An argument of type unsigned short is promoted to type int if the machine size of an int is larger than that of a short integer; otherwise, it is promoted to type unsigned int.

·         An argument of type float is promoted to type double

·         An argument of an enumeration type is promoted to the first of the following type that can represent all the values of the enumeration constants: int, unsigned int, long, or unsigned long.

·         An argument of type bool is promoted to type int.

Details of a Standard Conversion

There are five kinds of conversions grouped in the category of standard conversion:

1.       The integral conversions: the conversions from any integral type or enumeration type to any other integral type (excluding the conversions that were listed as promotions earlier).

2.       The floating point conversions: the conversions from any floating point type to any other floating point type (excluding the conversions that were listed as promotions earlier).

3.       The floating-integral conversions: the conversions from any floating point type to any integral type or from any integral type to any floating point type.

4.       The pointer conversions: the conversion of the integer value zero to a pointer type and the conversion of a pointer of any type to the type void*.

5.       The bool conversions: the conversions from any integral type, floating point type, enumeration type, or pointer type to the type bool.

The conversions that are grouped in categories 1, 2, and 3 are potentially dangerous conversions, because the target type of the conversion cannot represent all the values that the source type can represent.

All standard conversions are treated as requiring equal work. Closeness of type is not considered. If two viable functions require standard conversions on the argument to match the type of their parameter, the call is ambiguous and it is flagged at compile-time as an error.

Only pointers to data types can be converted to the type void* with a pointer standard conversion. Pointers to functions cannot be converted to the type void* with a standard conversion.

References

The outcome of a match of an argument with a reference parameter is one of the following possibilities.

The argument is an appropriate initializer for the reference parameter. In this case, we say that the argument is an exact match for the parameter.

The argument cannot initialize the reference parameter. In this case, there is a no match situation and the argument cannot be used to call the function.

Both an lvalue-to-rvalue conversion and a reference initialization are considered to be exact matches.

Details of Function Overload Resolution

Candidate Functions

A candidate function is a function that has the same name as the function called. A candidate function will be found in one of the following two ways.

1.       A declaration for the function is visible at the point of the call.

2.       If the type of a function argument is declared within a namespace, the namespace member functions that have the same name as the function called are added to the set of candidate functions.

Viable Functions

A viable function is a function in the set of candidate functions. A viable function is a function for which there exist conversions to convert each argument to the type of the corresponding parameter in the viable function parameter list.

 

 


 

Chapter 10. Function Templates

Function templates provide a mechanism by which we can preserve the semantics of function definitions and function calls without having to bypass C++'s strong type-checking as is done with the macro solution.

The keyword template always begins both a definition and a declaration of a function template. The keyword is followed by a comma-separated list of template parameters bracketed by the less-than (<) and greater-than (>) tokens. This list is the template parameter list. It cannot be empty. A template parameter can be a template type parameter representing a type or a template nontype parameter representing a constant expression.

A template type parameter consists of the keyword class or the keyword typename followed by an identifier. In a function template parameter list, these keywords have the same meaning. They indicate that the parameter name that follows represents a potential built-in or user-defined type.

If an object, function, or type having the same name as the template parameter is declared in global scope, the global scope name is hidden.

An object or type declared within the function template definition cannot have the same name as that of a template parameter.

The name of a template type parameter can be used to specify the return type of the function template.

The name of a template parameter can be used only once within the same template parameter list.

However, the name of a template parameter can be reused across function template declarations or definitions.

The names of the template parameters do not need to be the same across declarations and the definition of the template.

There is no constraint on how many times a template parameter can appear in the function parameter list.

If a function template has more than one template type parameter, each template type parameter must be preceded by the keyword class or the keyword typename.

A function template can be declared inline or extern in the same way as a nontemplate function.

 

 

 

 

Chapter 13: Classes

A name used within a class definition (except in inline member function definitions and default arguments) is resolved as follows:

1.       The declarations of the class members that appear before the use of the name are considered.

2.       If the resolution in step 1 is not successful, the declarations that appear in namespace scope before the class definition are considered.

A name used within the definition of a class member function is resolved as follows:

1.       Declarations in the member function local scopes are considered first.

2.       If the resolution in step 1 is not successful, the declarations for all the class members are considered.

3.       If the resolution in step 2 is not successful, the declarations that appear in namespace scope before the member function definition are considered

An enclosing class has no access privileges to the private members of a nested class unless it is declared as a friend of the nested class. Nor does the nested class have any special access privileges to the private members of its enclosing class.

A nested class can also be defined outside its enclosing class.

 

A name used within a nested class definition.

1.       The declarations of the members of the nested class that appear before the use of the name are considered.

2.       If the resolution in step 1 is not successful, the declarations of the members of the enclosing class that appear before the use of the name are considered.

3.       If the resolution in step 2 is not successful, the declarations that appear in namespace scope before the nested class definition are considered.

Because there is no syntax to define the members of a local class in a namespace scope, a local class is not permitted to declare static data members.


 

Chapter 14. Class Initialization, Assignment, and Destruction

A mechanism inherited from the C language supports an explicit initialization list similar to that used to initialize an array. The values are resolved positionally based on the declaration order of the data members.

Two primary drawbacks to the explicit initialization list are that it can only be applied to class objects for which all the data members are public and that it requires the explicit intervention of the programmer, adding to the possibility of accident or error.

If a class declares a constructor taking one or more parameters, but does not declare a default constructor, every class object definition must provide the required arguments.

The container classes (such as vector, for example) require their class elements to provide either a default constructor or no constructor at all. Similarly, allocation of a dynamic array of class objects also requires either a default constructor or no constructor at all. In practice it is almost always necessary to provide a default constructor if other constructors are being defined as well.

A constructor may not be declared with either the const or volatile keyword.

The explicit modifier informs the compiler not to provide implicit conversions. explicit can only be applied to a constructor.

The compiler first checks to see whether a default constructor for the Account class is defined. One of the following occurs:

1.       The default constructor is defined. It is applied to acct.

2.       The default constructor is defined, but it is nonpublic. The definition of acct is flagged at compile-time as an error: main() has no access privilege.

3.       No default constructor is defined, but one or more constructors requiring arguments is defined. The definition of acct is flagged at compile-time as an error: too few constructor arguments.

4.       No default constructor is defined, nor any other constructor. The definition is legal. acct is uninitialized and no constructor is invoked.

New users often mistakenly believe that the compiler generates and applies a default constructor automatically if one is not present-initializing the class data members.  No default constructor is generated nor is one invoked.  For more complex classes containing class data members or making use of inheritance, this is partially true: A default constructor may be generated, but it does not provide initial values for data members of the built-in or compound types, such as pointers and arrays.

If we want class data members of the built-in and compound types to be initialized, we must do so explicitly in one or a set of constructors. Without doing so, it is next to impossible to distinguish between a valid and uninitialized value associated with the data members of the built-in and compound types of local and dynamically allocated class objects.

The predominant uses of nonpublic constructors in real-world C++ programs are

1.       to prevent the copying of one class object with another object of its class (discussed in the following subsection) and

2.       to indicate that a constructor is intended to be invoked only when the class serves as a base class within an inheritance hierarchy and not as an object to be manipulated directly within the application

Because destructor cannot specify any parameters, it cannot be overloaded.

A destructor is not invoked when either a reference or a pointer to a class object goes out of scope.

In some program situations it is necessary to invoke the destructor explicitly on a particular class object. This comes up most often in conjunction with placement operator new.

An inline destructor can be an unsuspected source of program code bloat because it is inserted at each exit point within a function for each active local class object.

There is no way to provide a set of explicit values with which to initialize the array elements of an array of class objects allocated on the heap.

By default, then, the initialization of an array of class objects allocated on the heap requires two steps: (1) the actual allocation of the array, in which the default constructor, if defined, is applied to each element and (2) the subsequent assignment of each element to a specific value (can make use of placement operator new).


 

Chapter 15. Overloaded Operators and User-Defined Conversions

The following four C++ operators cannot be overloaded: :: .* . ?:

The predefined meaning of an operator for the built-in types may not be changed. For example, the built-in integer addition operation cannot be replaced with an operation that checks for overflow.

// error: cannot redefine built-in operator for ints
int operator+( int, int );

Nor may additional operators be defined for the built-in data types.

The predefined precedence of the operators cannot be overridden.

The predefined arity of the operator must be preserved.

For built-in types, four predefined operators ("+", "-", "*", and "&") serve as both unary and binary operators. Either or both arities of these operators can be overloaded.

How do we decide, then, whether an operator that is not a class member should be made a friend or whether it should use the access member functions? In general, a class implementor should try to minimize the number of namespace functions and operators that have access to the internal representation of a class. If access member functions are provided and they are equally efficient, then it is preferable to use them and isolate the namespace operators from the changes in the class representation, just as it is done with other namespace functions. If the class implementor decides not to provide access member functions for some of the class private members, and if the namespace operators need to refer to these private members to perform their operations, then the use of the friend mechanism becomes necessary.

The return type of the assignment operator is a reference to the String class. Why would we declare this assignment operator to return a reference?

For built-in types, assignment operators can be chained together as follows:

// chain of assignment operators
int iobj, jobj;
iobj = jobj = 63;

 

We would like to preserve this behavior for assignments to objects of our String class, such that the following, for example, is supported:

String verb, noun;
verb = noun = "count";