Compilation and Execution in C Language

Once you have written the program you need to type it and instruct the machine to execute it. To type your C program you need another program called Editor. Once the program has been typed it needs to be converted to machine language (0s and 1s) before the machine can execute it. To carry out this conversion we need another program called Compiler. Compiler vendors provide an Integrated Development Environment (IDE) which consists of an Editor as well as the Compiler.
There are several such IDEs available in the market targeted towards different operating systems. For example, Turbo C, Turbo C++ and Microsoft C are some of the popular compilers that work under MS-DOS; Visual C++ and Borland C++ are the compilers that work under Windows, whereas gcc compiler works under Linux. Note that Turbo C++, Microsoft C++ and Borland C++ software also contain a C compiler bundled with them. If you are a beginner you would be better off using a simple compiler like Turbo C or Turbo C++. Once you have mastered the language elements you can then switch over to more sophisticated compilers like Visual C++ under Windows or gcc under Linux. Most of the programs in this book would work with all the compilers. Wherever there is a deviation I would point it out that time.
Assuming that you are using a Turbo C or Turbo C++ compiler here are the steps that you need to follow to compile and execute your first C program…

Start the compiler at C> prompt. The compiler (TC.EXE is usually present in C:\TC\BIN directory).
Select New from the File menu.
Type the program.
Save the program using F2 under a proper name (say Program1.c).
Use Ctrl + F9 to compile and execute the program.
Use Alt + F5 to view the output.
Note that on compiling the program its machine language equivalent is stored as an EXE file (Program1.EXE) on the disk. This file is called an executable file. If we copy this file to another machine we can execute it there without being required to recompile it. In fact the other machine need not even have a compiler to be able to execute the file.
A word of caution! If you run this program in Turbo C++ compiler, you may get an error — “The function printf should have a prototype”. To get rid of this error, perform the following steps and then recompile the program.
Select ‘Options’ menu and then select ‘Compiler | C++ Options’. In the dialog box that pops up, select ‘CPP always’ in the ‘Use C++ Compiler’ options.
Again select ‘Options’ menu and then select ‘Environment | Editor’. Make sure that the default extension is ‘C’ rather than ‘CPP’.

The First C Program

Armed with the knowledge about the types of variables, constants & keywords the next logical step is to combine them to form instructions. However, instead of this, we would write our first C program now. Once we have done that we would see in detail the instructions that it made use of.
Before we begin with our first C program do remember the following rules that are applicable to all C programs:
(a)
Each instruction in a C program is written as a separate statement. Therefore a complete C program would comprise of a series of statements.

The statements in a program must appear in the same order in which we wish them to be executed; unless of course the logic of the problem demands a deliberate ‘jump’ or transfer of control to a statement, which is out of sequence.
Blank spaces may be inserted between two words to improve the readability of the statement. However, no blank spaces are allowed within a variable, constant or keyword.
All statements are entered in small case letters.
C has no specific rules for the position at which a statement is to be written. That’s why it is often called a free-form language.
Every C statement must end with a ;. Thus ; acts as a statement terminator.
Let us now write down our first C program. It would simply calculate simple interest for a set of values representing principle, number of years and rate of interest.
/* Calculation of simple interest */
/* Author gekay Date: 25/05/2004 */
main( )
{
int p, n ;
float r, si ;
p = 1000 ;
n = 3 ;
r = 8.5 ;
/* formula for simple interest */
si = p * n * r / 100 ;
printf ( "%f" , si ) ;
}
Now a few useful tips about the program...
− Comment about the program should be enclosed within /* */. For example, the first two statements in our program are comments.
− Though comments are not necessary, it is a good practice to begin a program with a comment indicating the purpose of the program, its author and the date on which the program was written.
− Any number of comments can be written at any place in the program. For example, a comment can be written before the statement, after the statement or within the statement as shown below:
/* formula */ si = p * n * r / 100 ;
si = p * n * r / 100 ; /* formula */
si = p * n * r / /* formula */ 100 ;
− Sometimes it is not so obvious as to what a particular statement in a program accomplishes. At such times it is worthwhile mentioning the purpose of the statement (or a set of statements) using a comment. For example:
/* formula for simple interest */
si = p * n * r / 100 ;
− Often programmers seem to ignore writing of comments. But when a team is building big software well commented code is almost essential for other team members to understand it.
− Although a lot of comments are probably not necessary in this program, it is usually the case that programmers tend to use too few comments rather than too many. An adequate number of comments can save hours of misery and suffering when you later try to figure out what the program does.
− The normal language rules do not apply to text written within /* .. */. Thus we can type this text in small case, capital or a combination. This is because the comments are solely given for the understanding of the programmer or the fellow programmers and are completely ignored by the compiler.
− Comments cannot be nested. For example,
/* Cal of SI /* Author sam date 01/01/2002 */ */
is invalid.
− A comment can be split over more than one line, as in,
/* This is
a jazzy
comment */
Such a comment is often called a multi-line comment.
− main( ) is a collective name given to a set of statements. This name has to be main( ), it cannot be anything else. All statements that belong to main( ) are enclosed within a pair of braces { } as shown below.
main( )
{
statement 1 ;
statement 2 ;
statement 3 ;
}
− Technically speaking main( ) is a function. Every function has a pair of parentheses ( ) associated with it. We would discuss functions and their working in great detail in Chapter 5.
− Any variable used in the program must be declared before using it. For example,
int p, n ;
float r, si ;
− Any C statement always ends with a ;
For example,
float r, si ;
r = 8.5 ;
− In the statement,
si = p * n * r / 100 ;
* and / are the arithmetic operators. The arithmetic operators available in C are +, -, * and /. C is very rich in operators. There are about 45 operators available in C. Surprisingly there is no operator for exponentiation... a slip, which can be forgiven considering the fact that C has been developed by an individual, not by a committee.
− Once the value of si is calculated it needs to be displayed on the screen. Unlike other languages, C does not contain any instruction to display output on the screen. All output to screen is achieved using readymade library functions. One such function is printf( ). We have used it display on the screen the value contained in si.
The general form of printf( ) function is,
printf ( "", ) ;
can contain,
%f for printing real values
%d for printing integer values
%c for printing character values
In addition to format specifiers like %f, %d and %c the format string may also contain any other characters. These characters are printed as they are when the printf( ) is executed.
Following are some examples of usage of printf( ) function:
printf ( "%f", si ) ;
printf ( "%d %d %f %f", p, n, r, si ) ;
printf ( "Simple interest = Rs. %f", si ) ;
printf ( "Prin = %d \nRate = %f", p, r ) ;
The output of the last statement would look like this...
Prin = 1000
Rate = 8.5
What is ‘\n’ doing in this statement? It is called newline and it takes the cursor to the next line. Therefore, you get the output split over two lines. ‘\n’ is one of the several Escape Sequences available in C. These are discussed in detail in Chapter 11. Right now, all that we can say is ‘\n’ comes in handy when we want to format the output properly on separate lines.
printf( ) can not only print values of variables, it can also print the result of an expression. An expression is nothing but a valid combination of constants, variables and operators. Thus, 3, 3 + 2, c and a + b * c – d all are valid expressions. The results of these expressions can be printed as shown below:
printf ( "%d %d %d %d", 3, 3 + 2, c, a + b * c – d ) ;
Note that 3 and c also represent valid expressions.

C Keywords

Keywords are the words whose meaning has already been explained to the C compiler (or in a broad sense to the computer). The keywords cannot be used as variable names because if we do so we are trying to assign a new meaning to the keyword, which is not allowed by the computer. Some C compilers allow you to construct variable names that exactly resemble the keywords. However, it would be safer not to mix up the variable names and the keywords. The keywords are also called ‘Reserved words’.
There are only 32 keywords available in C. Figure 1.5 gives a list of these keywords for your ready reference. A detailed discussion of each of these keywords would be taken up in later chapters wherever their use is relevant.
auto
double
int
struct
break
else
long
switch
case
enum
register
typedef
char
extern
return
union
const
float
short
unsigned
continue
for
signed
void
default
goto
sizeof
volatile
do
if
static
while

Note that compiler vendors (like Microsoft, Borland, etc.) provide their own keywords apart from the ones mentioned above. These include extended keywords like near, far, asm, etc. Though it has been suggested by the ANSI committee that every such compiler specific keyword should be preceded by two underscores (as in __asm ), not every vendor follows this rule.

Types of C Variables

As we saw earlier, an entity that may vary during program execution is called a variable. Variable names are names given to locations in memory. These locations can contain integer, real or character constants. In any language, the types of variables that it can support depend on the types of constants that it can handle. This is because a particular type of variable can hold only the same type of constant. For example, an integer variable can hold only an integer constant, a real variable can hold only a real constant and a character variable can hold only a character constant.
The rules for constructing different types of constants are different. However, for constructing variable names of all types the same set of rules apply. These rules are given below.
Rules for Constructing Variable Names

A variable name is any combination of 1 to 31 alphabets, digits or underscores. Some compilers allow variable names whose length could be up to 247 characters. Still, it would be safer to stick to the rule of 31 characters. Do not create unnecessarily long variable names as it adds to your typing effort.
The first character in the variable name must be an alphabet or underscore.
No commas or blanks are allowed within a variable name.
No special symbol other than an underscore (as in gross_sal) can be used in a variable name.
Ex.: si_int
m_hra
pop_e_89
These rules remain same for all the types of primary and secondary variables. Naturally, the question follows... how is C able to differentiate between these variables? This is a rather simple
matter. C compiler is able to distinguish between the variable names by making it compulsory for you to declare the type of any variable name that you wish to use in a program. This type declaration is done at the beginning of the program. Following are the examples of type declaration statements:
Ex.: int si, m_hra ;
float bassal ;
char code ;
Since, the maximum allowable length of a variable name is 31 characters, an enormous number of variable names can be constructed using the above-mentioned rules. It is a good practice to exploit this enormous choice in naming variables by using meaningful variable names.
Thus, if we want to calculate simple interest, it is always advisable to construct meaningful variable names like prin, roi, noy to represent Principle, Rate of interest and Number of years rather than using the variables a, b, c.

Types of C Constants

Types of C Constants
C constants can be divided into two major categories:

Primary Constants
Secondary Constants
These constants are further categorized as shown in Figure 1.4.
At this stage we would restrict our discussion to only Primary Constants, namely, Integer, Real and Character constants. Let us see the details of each of these constants. For constructing these different types of constants certain rules have been laid down. These rules are as under:
Rules for Constructing Integer Constants
An integer constant must have at least one digit.

It must not have a decimal point.
It can be either positive or negative.
If no sign precedes an integer constant it is assumed to be positive.
No commas or blanks are allowed within an integer constant.
The allowable range for integer constants is -32768 to 32767.
Truly speaking the range of an Integer constant depends upon the compiler. For a 16-bit compiler like Turbo C or Turbo C++ the range is –32768 to 32767. For a 32-bit compiler the range would be even greater. Question like what exactly do you mean by a 16-bit or a 32-bit compiler, what range of an Integer constant has to do with the type of compiler and such questions are discussed in detail in Chapter 16. Till that time it would be assumed that we are working with a 16-bit compiler.
Ex.: 426
+782
-8000
-7605
Rules for Constructing Real Constants
Real constants are often called Floating Point constants. The real constants could be written in two forms—Fractional form and Exponential form.
Following rules must be observed while constructing real constants expressed in fractional form:

A real constant must have at least one digit.
It must have a decimal point.
It could be either positive or negative.
Default sign is positive.
No commas or blanks are allowed within a real constant.
Ex.: +325.34
426.0
-32.76
-48.5792
The exponential form of representation of real constants is usually used if the value of the constant is either too small or too large. It however doesn’t restrict us in any way from using exponential form of representation for other real constants.

In exponential form of representation, the real constant is represented in two parts. The part appearing before ‘e’ is called mantissa, whereas the part following ‘e’ is called exponent.
Following rules must be observed while constructing real constants expressed in exponential form:

The mantissa part and the exponential part should be separated by a letter e.
The mantissa part may have a positive or negative sign.
Default sign of mantissa part is positive.
The exponent must have at least one digit, which must be a positive or negative integer. Default sign is positive.
Range of real constants expressed in exponential form is -3.4e38 to 3.4e38.
Ex.: +3.2e-5
4.1e8
-0.2e+3
-3.2e-5
Rules for Constructing Character Constants
A character constant is a single alphabet, a single digit or a single special symbol enclosed within single inverted commas. Both the inverted commas should point to the left. For example, ’A’ is a valid character constant whereas ‘A’ is not.
The maximum length of a character constant can be 1 character.
Ex.: 'A'
'I'
'5'
'='

Getting Started with C

Communicating with a computer involves speaking the language the computer understands, which immediately rules out English as the language of communication with computer. However, there is
language. The classical method of learning English is to first learn the alphabets used in the language, then learn to combine these alphabets to form words, which in turn are combined to form sentences and sentences are combined to form paragraphs. Learning C is similar and easier. Instead of straight-away learning how to write programs, we must first know what alphabets, numbers and special symbols are used in C, then how using them constants, variables and keywords are constructed, and finally how are these combined to form an instruction. A group of instructions would be combined later on to form a program. This is illustrated in the Figure 1.1.
The C Character Set
A character denotes any alphabet, digit or special symbol used to represent information. Figure 1.2 shows the valid alphabets, numbers and special symbols allowed in C.
Constants, Variables and Keywords
The alphabets, numbers and special symbols when properly combined form constants, variables and keywords. Let us see what are ‘constants’ and ‘variables’ in C. A constant is an entity that doesn’t change whereas a variable is an entity that may change.
In any program we typically do lots of calculations. The results of these calculations are stored in computers memory. Like human memory the computer memory also consists of millions of cells. The calculated values are stored in these memory cells. To make the retrieval and usage of these values easy these memory cells (also called memory locations) are given names. Since the value stored in each location may change the names given to these locations are called variable names. Consider the following example.
Here 3 is stored in a memory location and a name x is given to it. Then we are assigning a new value 5 to the same memory location x. This would overwrite the earlier value 3, since a memory location can hold only one value at a time. This is shown in Figure 1.3.
Since the location whose name is x can hold different values at different times x is known as a variable. As against this, 3 or 5 do not change, hence are known as constants.

What is C

C is a programming language developed at AT & T’s Bell Laboratories of USA in 1972. It was designed and written by a man named Dennis Ritchie. In the late seventies C began to replace the more familiar languages of that time like PL/I, ALGOL, etc. No one pushed C. It wasn’t made the ‘official’ Bell Labs language. Thus, without any advertisement C’s reputation spread and its pool of users grew. Ritchie seems to have been rather surprised that so many programmers preferred C to older languages like FORTRAN or PL/I, or the newer ones like Pascal and APL. But, that's what happened.
Possibly why C seems so popular is because it is reliable, simple and easy to use. Moreover, in an industry where newer languages, tools and technologies emerge and vanish day in and day out, a language that has survived for more than 3 decades has to be really good.
An opinion that is often heard today is – “C has been already superceded by languages like C++, C# and Java, so why bother to learn C today”. I seriously beg to differ with this opinion. There are several reasons for this:

I believe that nobody can learn C++ or Java directly. This is because while learning these languages you have things like classes, objects, inheritance, polymorphism, templates, exception handling, references, etc. do deal with apart from knowing the actual language elements. Learning these complicated concepts when you are not even comfortable with the basic language elements is like putting the cart before the horse. Hence one should first learn all the language elements very thoroughly using C language before migrating to C++, C# or Java. Though this two step learning process may take more time, but at the end of it you will definitely find it worth the trouble.
C++, C# or Java make use of a principle called Object Oriented Programming (OOP) to organize the program. This organizing principle has lots of advantages to offer. But even while using this organizing principle you would still need a good hold over the language elements of C and the basic programming skills.
Though many C++ and Java based programming tools and frameworks have evolved over the years the importance of C is still unchallenged because knowingly or unknowingly while using these frameworks and tools you would be still required to use the core C language elements—another good reason why one should learn C before C++, C# or Java.
Major parts of popular operating systems like Windows, UNIX, Linux is still written in C. This is because even today when it comes to performance (speed of execution) nothing beats C. Moreover, if one is to extend the operating system to work with new devices one needs to write device driver programs. These programs are exclusively written in C.
Mobile devices like cellular phones and palmtops are becoming increasingly popular. Also, common consumer devices like microwave oven, washing machines and digital cameras are getting smarter by the day. This smartness comes from a microprocessor, an operating system and a program embedded in this devices. These programs not only have to run fast but also have to work in limited amount of memory. No wonder that such programs are written in C. With these constraints on time and space, C is the language of choice while building such operating systems and programs.
You must have seen several professional 3D computer games where the user navigates some object, like say a spaceship and fires bullets at the invaders. The essence of all such games is speed. Needless to say, such games won't become popular if they takes a long time to move the spaceship or to fire a bullet. To match the expectations of the player the game has to react fast to the user inputs. This is where C language scores over other languages. Many popular gaming frameworks have been built using C language.
At times one is required to very closely interact with the hardware devices. Since C provides several language elements that make this interaction feasible without compromising the performance it is the preferred choice of the programmer.
I hope that these are very convincing reasons why one should adopt C as the first and the very important step in your quest for learning programming languages.

Integrating Types and Specifications for Secure Software Development

Integrating Types and Specifications for Secure Software Development
Greg Morrisett
Harvard University,
Cambridge, Massachussetts, 02138, USA
greg@eecs.harvard.edu
http://www.eecs.harvard.edu/~greg
Abstract. Today, the majority of security errors in software systems
are due to implementation errors, as opposed to flaws in fundamental
algorithms (e.g., cryptography). Type-safe languages, such as Java, help
rule out a class of these errors, such as code-injection through buffer overruns.
But attackers simply shift to implementation flaws above the level
of the primitive operations of the language (e.g., SQL-injection attacks).
Thus, next-generation languages need type systems that can express and
enforce application-specific security policies.
Keywords: dependent types, verification, software-security.

Overview
In theory, there is no difference between theory and practice. But, in
practice, there is.
Jan L. A. van de Snepscheut

Web Security

Security is moving to the application layer. Once, the design of secure operating
systems and Internet security protocols were the main foundations of information
security. According to the then predominant mood, IT systems could be used
securely once secure infrastructures were in place. Remnants of this era can still
be found in claims that one MUST secure operating systems or the Internet to
be able to securely use today’s critical IT infrastructures.
We observe, however, that security mechanisms in end systems are moving
to the application layer of the software stack. The reference monitor has moved
from the operating into web pages (Figure 3). Security components at upper
layers may be effective without support from below. This works as long as direct
access to the lower layers need not be considered as a threat. In parallel, communications
security mechanisms have been moving to the application layer of
the protocol stack. At the point where end system security and communications
security meet, i.e. in the software components running network protocols, we
have seen shared secrets moved up to the application layer to defend against
attacks at the infrastructure layer (Section 3.3), contrary to the conventional
security strategy that tries to embed secrets at a layer as low as possible, e.g. in
tamper resistant hardware.
The security services expected from the infrastructure may thus change over
time. We can also observe that our view of what constitutes the infrastructure
may change over time. The web browser that started as a new application has
today become an essential infrastructure component for Web services.
The Internet is a critical infrastructure because it is the platform for critical
applications. Our primary challenge is the protection of these applications. Security
services provided by the infrastructure may help in this cause, but trust
in these services may also be misplaced when application writers misunderstand
the security properties actually guaranteed.
It is a trivial observation on security engineering that defenders ought to
know where their systems will be attacked. When attacks are launched via the
interface of web applications, the first line of defence should be at that layer.
Attacks may be directed against the application, e.g. fraudulent bank transfers
in an e-banking application. Application-level access control necessarily relates
to principals meaningful for the application. There may be mappings from those
principals to principals known to the infrastructure so that security services from
the infrastructure can support application security. However, in every instance
we must verify that it is not possible for attackers to redefine the binding between
principal names at different system layers. We may thus surmise that it is more
likely to find access control solutions at the application layer, as borne out by
our earlier observations on reference monitors. In this respect, we have secure
applications without a security infrastructure.
Attacks may be directed against the end system hosting the application. Software
vulnerabilities in an application may present the attacker with an opportunity
to step down into the infrastructure. Although software security issues
could be addressed in each application, it would be desirable to have a ‘secure’
computing infrastructure, i.e. an infrastructure that can deal with malformed inputs
forwarded via the applications. In this respect, critical applications benefit
from a computing infrastructure that can protect its own execution integrity.
The primary property required fromthe communications infrastructure is availability.
Security services such as confidentiality, integrity, or authenticity may or
may not be provided by the communications infrastructure. The relativemerits of
delivering these services in the various layers of the network stack have been discussed
extensively in the research literature. The most relevant issue for critical
applications are the choice of relevant principals that can serve as logical endpoints
for application layer transactions, and the authentication of those principals.
We leave the reader with a final challenge. When security is moving to the
application layer, responsibility for security will increasingly rest with application
writers and with end users. At this point in time, neither of the two communities
is well prepared to take on this task, but nor has security research made much
progress in explaining to non-experts the implications of security decisions.
References
1. Arends, R., Austein, R., Larson, M., Massey, D., Rose, S.: DNS security introduction
and requirements. RFC 4033 (March 2005)
2. Arends, R., Austein, R., Larson, M., Massey, D., Rose, S.: Protocol modifications
for the DNS security extensions. RFC 4035 (March 2005)
3. Arends, R., Austein, R., Larson, M., Massey, D., Rose, S.: Resource records for the
DNS security extensions. RFC 4034 (March 2005)
4. Burns, J.: Cross site reference forgery. Technical report, Information Security Partners,
LLC, Version 1.1 (2005)
5. CERT Coordination Center.Malicious HTML tags embedded in client web requests
(2000), http://www.cert.org/advisories/CA-2000-02.html
6. Dean, D., Felten, E.W., Wallach, D.S.: Java security: from HotJava to Netscape
and beyond. In: Proceedings of the 1996 IEEE Symposium on Security and Privacy,
pp. 190–200 (1996)
7. Dierks, T., Rescorla, E.: The TLS protocol – version 1.2, RFC 5246 (August 2008)
8. Gong, L., Dageforde, M., Ellison, G.W.: Inside Java 2 Platform Security, 2nd edn.
Addison-Wesley, Reading (2003)
9. Howard,M., LeBlanc, D.:Writing Secure Code, 2nd edn.Microsoft Press, Redmond
(2002)
10. Jackson, C., Barth, A., Bortz, A., Shao, W., Boneh, D.: Protecting browsers from
DNS rebinding attacks. In: Proceedings of the 14th ACM Conference on Computer
and Communications Security, pp. 421–431 (2007)
11. Kent, S., Seo, K.: Security architecture for the Internet protocol, RFC 4301 (December
2005)
12. Marsh, R., Dispensa, S.: Renegotiating TLS. Technical report, PhoneFactor Inc.,
Malvern (November 2009)
13. One, A.: Smashing the stack for fun and profit. Phrack Magazine 49 (1996)
14. Oppliger, R., Hauser, R., Basin, D.A.: SSL/TLS session-aware user authentication.
IEEE Computer 41(3), 59–65 (2008)
15. Rescorla, E., Ray, M., Dispensa, S., Oskov, N.: Transport layer security (TLS)
renegotiation indication extension, RFC 5746 (February 2010)

Secure Sessions

Besides operating systems security, communications security has been the second
main pillar of information security. Protocol suites such as SSL/TLS (TLS v1.2,
) or IPsec [11] facilitate the establishment of secure channels between two
parties that are connected via an insecure network. More precisely, the threat
model assumes an attacker that can read, delete, insert, modify, and replay
traffic; direct attacks against end systems are, however, not considered.
In the 1990s distributed applications were ‘secured’ by running the application
over SSL. https is a prime example for this pattern: a secure web page is a
page accessed via an SSL/TLS channel. Application security builds directly on
security services provided by the communications infrastructure.
This approach has two shortcomings. Many end systems are not well secured.
This invalidates one major assumption of the threat model that underpins traditional
communications security. Arguably, it is more realistic to assume that the
communications system is secure but current end systems are not, rather than
the other way round. Section 2 has already hinted at this problem. Secondly,
attempts at linking concurrent sessions established at different protocol layers
may fail.
Consider the following procedure for establishing a mutually authenticated
application layer session between a user and a server that share a secret password.
First, the user’s client establishes an SSL/TLS channel with the server (host).
In this step the client’s browser checks that the distinguished name in the server
certificate matches the host visited and that the certificate is still valid. The user
then sends the password via the SSL/TLS channel; the server authenticates the
user and returns a HTTP cookie to the client. This cookie is included in future
requests issued within the application layer session. The server takes the cookie
as evidence that the requests are coming from the user previously authenticated.
The EAP-TTLS protocol gives a concrete implementation of this authentication
pattern.

Man-in-the-Middle Attacks
A protocol such as EAP-TTLS achieves its goal as long as the SSL/TLS channel
has as its endpoint the server holding the password. This is not guaranteed by
the protocol itself. Server authentication during the SSL/TLS handshake just
guarantees that the server has a valid certificate. It is up to the user to make
sure that the host is the one intended.
This check is not always straightforward; host names are not always indicative
of service offered. Furthermore, there exist various ways of luring users into
connecting to the wrong server. For example, an attack2 targeting traders with
the German Emissions Trading Authority (DEHSt) started from an email purporting
to come from a security manager requesting an upgrade to improved
security standards.
Once a user is lured into establishing an SSL/TLS channel with the attacker,
the attacker can act as a man-in-the-middle establishing its own SSL/TLS channel
with the server. Authentication requests from the server are passed on to the
user; the user’s response is forwarded to the server; the cookie from the server
is sent back to the man-in-the-middle who now can hijack the user’s application
layer session. A possible countermeasure are cookies tied also to the SSL/TLS
channel as proposed in. In the presence of a man-in-the-middle attack client
and server use different SSL/TLS channels and could thus detect that cookies
are not received in the same channel as they had been originally sent.
A man-in-the-middle attack in time is described in. It exploits a particular
usage of SSL/TLS for controlling access to protected resources on a web
server. Here, client and server are in possession of certificates. The client initially
gets anonymous access to a secure web site by establishing an SSL/TLS
channel with server authentication only. When the server receives a request for
a protected resource, SSL/TLS session renegotiation is triggered with a Hello
Request message. In the new session the server asks for client authentication.

In the man-in-the-middle attack (Figure 2) the attacker waits for a session
initiation from the client. The client’s message is suppressed and the attacker
starts its own session with the server. The attacker sends a request for a protected
resource (in Figure 2 a web page is posted to the server) whereupon the
server triggers session renegotiation. From this time on the attacker acts as relay
between client – that is in the process of establishing a new channel – and server
until both have established a new mutually authenticated SSL/TLS channel. A
request sent in this new channel will be attributed correctly to the authenticated
user and executed with that user’s access rights. The attacker’s HTTP request
had been constructed so that it would be a prefix to the next request in the
current session and will now also be executed with that user’s access rights.
Note that RFC 5246 does not promise any link between sessions when defining
TLS renegotiation. Application designers who had used renegotiation to
‘upgrade’ the authentication status of the client had thus assumed a service not
provided by the infrastructure. To address this situation, RFC 5746 [15] defines
a TLS extension where renegotiations are cryptographically tied to the TLS
connections they are being performed over. In this case, the infrastructure has
followed to meet the – initially unwarranted – expectations of an application.