idnits 2.17.1 draft-mcgrew-tls-proxy-server-00.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- No issues found here. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year == Line 319 has weird spacing: '...gorithm bul...' -- The document date (July 4, 2011) is 4680 days in the past. Is this intentional? -- Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines. Checking references for intended status: Informational ---------------------------------------------------------------------------- ** Obsolete normative reference: RFC 2818 (Obsoleted by RFC 9110) ** Obsolete normative reference: RFC 4366 (Obsoleted by RFC 5246, RFC 6066) ** Obsolete normative reference: RFC 5246 (Obsoleted by RFC 8446) -- Obsolete informational reference (is this intentional?): RFC 2616 (Obsoleted by RFC 7230, RFC 7231, RFC 7232, RFC 7233, RFC 7234, RFC 7235) Summary: 3 errors (**), 0 flaws (~~), 2 warnings (==), 3 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 Internet Engineering Task Force D. McGrew 3 Internet-Draft P. Gladstone 4 Intended status: Informational Cisco Systems 5 Expires: January 5, 2012 July 4, 2011 7 TLS Proxy Server Extension 8 draft-mcgrew-tls-proxy-server-00 10 Abstract 12 Transport Layer Security (TLS) is commonly used to protect HTTP and 13 other protocols. HTTP is often proxied, for instance, to allow an 14 application-layer firewall to inspect the HTTP traffic between the 15 client and the server. A TLS session cannot protect traffic between 16 the client and server when an HTTP proxy is present. Separate TLS 17 sessions can be run between the client and the proxy, on one side, 18 and the proxy and the server on the other side. This provides the 19 needed security, as long as the client, server, and proxy device use 20 appropriate and consistent security policies. However, this last 21 part is problematic; how can a proxy know if a client trusts a 22 server? At present, TLS provides no mechanism to coordinate 23 policies. 25 This note defines a TLS extension that allows a TLS proxy to provide 26 a TLS client with all of information about the TLS server that the 27 client needs to make a well-informed access control decision. 29 Status of this Memo 31 This Internet-Draft is submitted in full conformance with the 32 provisions of BCP 78 and BCP 79. 34 Internet-Drafts are working documents of the Internet Engineering 35 Task Force (IETF). Note that other groups may also distribute 36 working documents as Internet-Drafts. The list of current Internet- 37 Drafts is at http://datatracker.ietf.org/drafts/current/. 39 Internet-Drafts are draft documents valid for a maximum of six months 40 and may be updated, replaced, or obsoleted by other documents at any 41 time. It is inappropriate to use Internet-Drafts as reference 42 material or to cite them other than as "work in progress." 44 This Internet-Draft will expire on January 5, 2012. 46 Copyright Notice 48 Copyright (c) 2011 IETF Trust and the persons identified as the 49 document authors. All rights reserved. 51 This document is subject to BCP 78 and the IETF Trust's Legal 52 Provisions Relating to IETF Documents 53 (http://trustee.ietf.org/license-info) in effect on the date of 54 publication of this document. Please review these documents 55 carefully, as they describe your rights and restrictions with respect 56 to this document. Code Components extracted from this document must 57 include Simplified BSD License text as described in Section 4.e of 58 the Trust Legal Provisions and are provided without warranty as 59 described in the Simplified BSD License. 61 Table of Contents 63 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3 64 1.1. Requirements Language . . . . . . . . . . . . . . . . . . 4 65 2. Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . 4 66 3. Operation . . . . . . . . . . . . . . . . . . . . . . . . . . 5 67 3.1. ProxyInfoExtension . . . . . . . . . . . . . . . . . . . . 8 68 3.2. ProxyInfoExtension . . . . . . . . . . . . . . . . . . . . 9 69 4. Discussion . . . . . . . . . . . . . . . . . . . . . . . . . . 9 70 5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 10 71 6. Security Considerations . . . . . . . . . . . . . . . . . . . 10 72 7. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 12 73 8. References . . . . . . . . . . . . . . . . . . . . . . . . . . 12 74 8.1. Normative References . . . . . . . . . . . . . . . . . . . 12 75 8.2. Informative References . . . . . . . . . . . . . . . . . . 13 76 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 13 78 1. Introduction 80 Transport Layer Security (TLS) RFC 5246 [RFC5246] is commonly used to 81 protect HTTP [RFC2616] as described in [RFC2818]. In many scenarios 82 an HTTP proxy is used, for instance, to allow caching, to provide 83 anonymity to a client, or to provide security by using an 84 application-layer firewall to inspect the HTTP traffic on behalf of 85 the client. A TLS session cannot protect traffic between the client 86 and server when a proxy is present. It is possible to have separate 87 TLS sessions between the client and the proxy, on one side, and the 88 proxy and the server on the other side, as show in Figure 1 . This 89 technique provides the appropriate cryptographic security (see below 90 for a discussion of why some other alternatives are less attractive). 91 But there is a problem: the presence of the proxy removes the 92 client's knowledge about the server. Without this knowledge, the 93 client has no way to decide what trust, if any, it should have in the 94 server. This is most problematic when the client trusts multiple 95 different servers for different applications, or trusts servers from 96 different domains. 98 Client Proxy Server 99 TLS Session #1 TLS Session #2 100 <------------> <-------------> 101 HTTP 102 <-----------------------------------> 104 A proxied HTTPS session, with two independent TLS sessions. 106 Figure 1 108 A further issue is that the client cannot determine the security 109 level of the TLS session between the proxy and the server. For 110 instance, a client can negotiate a high security ciphersuite between 111 itself and the proxy, but it will have no way of knowing what 112 ciphersuite is in use between the client and the server, which could 113 be using the obsolete 56-bit Data Encryption Standard (DES) cipher. 115 Another point of difficulty is the fact that there can be multiple 116 proxies on a particular path. To solve the security issues 117 introduced by TLS proxies in a way that is generally applicable, it 118 is necessary to accommodate scenarios involving multiple proxies. 120 We propose a solution in this note, by describing a TLS extension 121 that can be used by a proxy to provide information to a TLS client 122 about the TLS server. When this extension is used, the client is 123 well informed about the proxy as well as the server, and can make a 124 knowledgeable access control decision about the server, using the 125 same processes that it uses when the proxy is not present. The data 126 in the extension are signed by the proxy in order to bind the 127 information about the server to a particular session between the 128 client and the proxy. When there are multiple proxies, the client is 129 informed about all of them. This extension also works for DTLS. 131 A separate issue is the provisioning of the proxy with information 132 about what servers (or rather, which certificates) should be trusted. 133 If the laptop has installed certificates that are specific to its 134 organization or to a particular domain, how can the proxy know to 135 trust these certificates on behalf of the laptop? 137 1.1. Requirements Language 139 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 140 "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 141 document are to be interpreted as described in RFC 2119 [RFC2119]. 143 2. Motivation 145 The following motivating example describes a typical situation with a 146 TLS proxy, as in Figure 1. A laptop trusts the server A for a 147 particular banking application, and trusts server B for a social 148 media application, and can authenticate both servers by using 149 standard PKIX certificate checking [RFC5280] and locally stored root 150 certificates. Or rather, the client trusts a set of root 151 certificates, and uses them to authenticate the TLS servers that it 152 connects with. The laptop also trusts the proxy, and has a 153 certificate by which it can authenticate the proxy. When making a 154 connection directly with B, the laptop can authenticate the server as 155 being trusted (that is, the server's public key appears in a 156 certificate that has been signed by the appropriate trusted 157 certificate authority), and it can also check the authorizations of 158 that server (that is, B is authorized to provide the social media 159 service, but not any other services such as banking). If the web 160 traffic from the laptop goes through an HTTP proxy, then the proxy 161 will need to know that it should trust both A and B to act as TLS 162 servers. Assuming that it does have this knowledge, it will proxy 163 TLS connections from both A and B. However, when the client attempts 164 to establish an HTTPS connection to A through the proxy, it has no 165 way of knowing what security checks the proxy has applied to the 166 connection between the proxy and A. The client cannot tell whether 167 the trusted certificate that it associates with A was used on the 168 connection between the proxy and A. The inability of the client to be 169 confident of the identity of the actual server forces the client to 170 trust all TLS servers indiscriminately. 172 This obstacle could be overcome by pushing the client's policy (that 173 is, information about what servers it trusts for what applications) 174 onto the proxy, so that the proxy can make well-informed decisions on 175 behalf of the client. However, this alternative has significant 176 drawbacks: it requires that the proxy obtain and store a significant 177 amount of information about each client, and it requires the 178 construction of a syntax by which the client's policy can be 179 expressed and understood. In contrast, our solution moves the 180 information about the server to the client, which does not require 181 the communication or storage of any security policy between the 182 client and server. 184 3. Operation 186 In this note, a TLS proxy is a device that acts as a TLS server in 187 one session and acts as a TLS client in another session, and passes 188 all of the data from one session to the other, possibly modifying it 189 in the process. That is, it is a non-transparent proxy, in the terms 190 of [RFC2616]. 192 TLS Session #1 TLS Session #2 193 Client <------------> Proxy <-------------> Server 195 Session #1 Session #2 Session #3 196 Client <---------> Proxy #1 <--------> Proxy #2 <---------> Server 198 A TLS session with a single proxy (top) and a TLS session with two 199 proxies (bottom). 201 Figure 2 203 The essential idea is as follows. When a TLS proxy is contacted by a 204 client, it does not respond to the client until it completes a TLS 205 session with the server. It then sends the client an assertion about 206 the server and the session, signed with the same private key that it 207 uses in its role as the TLS proxy server. When the client receives 208 this assertion, it checks the data in the assertion to determine 209 whether or not it trusts the server. The assertion is carried in a 210 ProxyInfoExtension, which is defined below. 212 This extension carries all of the information that is available to a 213 TLS client about a TLS server; thus the client can use existing 214 authorization checking processes. The client will need to verify the 215 hostname and/or address, and check to see if the certificate has been 216 revoked. The client authenticates the proxy server as usual during 217 the TLS session. This ensures that the client trusts the proxy, and 218 because of the signature on the assertion, it should trust the server 219 certificate carried in the assertion. The proxy need not perform any 220 checking on the server certificate, because this check is done by the 221 client. Of course, by completing a TLS exchange with the server, the 222 proxy verifies that the server holds the private key associated with 223 that certificate. 225 It is required that proxies which implement this extension and 226 support TLS Session Resumption handle TLS Session Resumptions (from 227 the client) by requiring TLS Session Resumption with the server. In 228 particular, a TLS session that is resumed with a client SHOULD 229 correspond to the proxy successfully resuming the TLS session with 230 the same server. When a client resumes a session with a proxy, the 231 proxy SHOULD attempt to resume the corresponding session with the 232 server. 234 Because there may be more than one proxy in any path, the TLS 235 extension carries a list of assertions. 237 On receiving a ClientHello from the client, the proxy: 239 1. Checks for a ProxyInfoExtension in the ClientHello; if there is 240 no such extension, then the following steps cannot be performed 241 and are omitted, 243 2. Establishes a TLS session with the server (session #2 in 244 Figure 1); a ProxyInfoExtension is included in that session, 246 3. Constructs a ProxyInfo structure by populating it with 247 information about the server and the current session with that 248 server; if the sever sends back a ProxyInfoExtension, then the 249 ProxyInfo structure is included as the next_proxy_info, 251 4. Signs the ProxyInfo structure with the public key corresponding 252 to the server certificate it uses in session #1, 254 5. Completes the session with the client (session #1 in Figure 1) 255 and provides the ProxyInfoExtension in that session, 257 The proxy MAY 259 Perform revocation checking on the certificate chain of the server 260 in session #2, and indicate that it has done this in the extension 261 by setting performed_revocation_checking to "true". 263 Note that the entity acting in the role of the server in session #2 264 could be a proxy, but in the above it is referred to as a server 265 because that is the role that it performs in that TLS session. 267 When TLS is used in HTTPS, the proxy MUST perform the Server Identity 268 checks described in Section 3.1 of [RFC2818]. 270 The normal operation of the proxy is to accept the (extended) 271 ClientHello from the client and then send a ClientHello to the 272 server. It is recommended that the TLS Proxy support commonly 273 deployed TLS extensions (as defined in [RFC4366] et al). Any TLS 274 extensions present on the original ClientHello MUST be examined and 275 either ignored, processed or forwarded (possibly after modification) 276 to the TLS server as part of the new ClientHello. 278 The client: 280 1. Includes a ProxyInfoExtension in the ClientHello message, 282 2. Checks for ProxyInfoExtension in the ServerHello message; if 283 there is no such extension, then the TLS processing continues as 284 usual; otherwise, 286 3. Processes the ProxyInfo extension by checking the validity of the 287 digitally-signed struct, then performing the usual server 288 authentication and authorization checking on the 289 server_certificate_list in the ProxyInfo, 291 4. Checks the revocation_checking_performed flag in the ProxyInfo; 292 if it is "false", then the client SHOULD perform revocation 293 checking on the server_certificate_list, 295 5. Checks the ProxyInfoFlag in the next_proxy_info field; if it is 296 not_empty, then the client returns to step 3 and performs that 297 processing on the next_proxy_info. 299 In order to maintain backwards compatibility for existing TLS 300 clients, the TLS proxies MUST (by default) perform certificate 301 validation for the certificates that they receive from the server. 302 The use of the ProxyInfoExtension in the extended ClientHello is an 303 indication by the client to request the alternate processing defined 304 by this note. In particular, if this extension is present in the 305 extended ClientHello, then the TLS proxy should not use its own 306 private key to dynamically generate a certificate. 308 The proxy will relay the data between the client and peer data 309 connections. End-to-end flow control is maintained by the relay 310 process: if the relay process is no longer able to write data to the 311 destination of the relayed data, the relay process stops reading data 312 from the source. 314 3.1. ProxyInfoExtension 316 The syntax of the ProxyInfo extension is as follows 317 struct { 318 PRFAlgorithm prf_algorithm; 319 BulkCipherAlgorithm bulk_cipher_algorithm; 320 CipherType cipher_type; 321 uint8 enc_key_length; 322 uint8 block_length; 323 uint8 fixed_iv_length; 324 uint8 record_iv_length; 325 MACAlgorithm mac_algorithm; 326 uint8 mac_length; 327 uint8 mac_key_length; 328 CompressionMethod compression_algorithm; 329 } ConnectionSecurityParameters; 331 enum { empty, not_empty } ProxyInfoFlag; 333 struct { 334 select (ProxyInfoFlag) { 335 case empty: 336 /* zero length body */ 337 case not_empty: 338 digitally-signed struct { 339 ConnectionSecurityParameters connection_parameters; 340 ASN.1Cert server_certificate_list<0..2^8-1>; 341 Boolean revocation_checking_performed; 342 ProxyInfo next_proxy_info; 343 } SignedProxyInfo; 344 } 345 } ProxyInfo; 347 struct { 348 ProxyInfo proxy_info; 349 } ProxyInfoExtension; 351 In this extension, . 353 The ProxyInfo structure is defined recursively, so that the signature 354 of each proxy authenticates the information provided by the proxies 355 that follow it on the path. The ProxyInfo contains the 356 ProxyInfoFlag, which indicates whether or not the ProxyInfo is empty 357 (in which case it contains no other fields) or not (in which case it 358 contains a SignedProxyInfo structure). The SignedProxyInfo structure 359 is signed with the public key that the proxy uses in its role as the 360 TLS server (in session #1). That structure contains the 361 connection_parameters that describe the security of session #2, and 362 the certificate chain of the server from session #2 in the 363 server_certificate_list. If the proxy has performed revocation 364 checking on that certificate chain, it indicates this by setting the 365 Boolean revocation_checking_performed. If the server in session #2 366 was actually a proxy itself, and it provides a ProxyInfo struct, then 367 that struct is included in the next_proxy_info field. Otherwise, the 368 next_proxy_info field contains an empty ProxyInfo. 370 enum { 371 /* ... */ 372 proxy_info(TBD1), (65535) 373 } ExtensionType; 375 3.2. ProxyInfoExtension 377 4. Discussion 379 The ProxyInfo extension could contain information about the checking 380 that the proxy performed on the server and its certificate. For 381 example, if the DNS name of the server matched the subjectAltName, 382 this fact could be indicated. It may be desirable to enumerate the 383 ways in which the server can match its certificate, to allow the 384 proxy to indicate to the client which of those ways was positive for 385 a particular server. 387 A potential issue with the ProxyInfo extension is that it can be 388 large, because the certificate chains that it carries can be large. 389 Roughly speaking, the amount of certificate data presented to the 390 client is proportional to the number of proxies on the path. It is 391 undesirable to require that so much data be sent, but on the other 392 hand, the client does need all of the data in order to make a well- 393 informed access control decision. It appears that the data is the 394 minimum required, in the sense that removing any of the data would 395 make it impossible for the client to assess the security of the 396 entire path. 398 The proxy is required to do the authentication checking on the 399 signatures created by the server, but not the authorization checking 400 or revocation checking. The responsibility for authorization 401 checking is not put onto the proxy because it does not know the 402 security policy of the client; in particular, the proxy does not know 403 which servers the client trusts for which applications. The 404 responsibility for revocation checking is not put onto the proxy 405 because that process is better left to the client. The client can 406 perform revocation checking on all of the certificate lists for all 407 of the proxies and the server in parallel, whereas if each proxy 408 performed the revocation checking, those processes would necessarily 409 be serial. Since revocation checking can take a significant amount 410 of time, the serial approach could add a significant amount of 411 latency to the TLS session, and potentially trigger retransmissions. 412 The parallel approach not only reduces the overall latency, but it 413 moves it outside of the client's retransmission timer for the 414 ClientHello message. 416 The ProxyInfo extension could convey the IP address of the server, or 417 other network layer information such as the DNS name. However, it is 418 not clear that this information is needed, so it was not included. 420 The ProxyInfo extension only provides information about proxies to 421 the client; it does not provide any information to the server about 422 either the client or other proxies on the path. This is acceptable 423 when there are no client certificates in use, which is (regrettably) 424 common in practice. It would be possible to generalize the ideas in 425 this note to also provide information to the server about the client 426 and other proxies on the path. Nonetheless, that goal is out of 427 scope for this note. 429 5. IANA Considerations 431 This document requests IANA to update its registry of TLS extension 432 types to assign an entry, referred herein as proxy_info, with the 433 number TBD1. 435 6. Security Considerations 437 In a situation with a proxy and a cryptographic protocol, the 438 appropriate security goals are to 440 preserve the security of the cryptographic protocol, 442 make the client aware of the proxy, able to authenticate the 443 proxy, and able to check that the device acting as a proxy is 444 authorized to act in that role, 446 allow the client to make access control decisions that are as 447 well-informed as when the proxy is not present. 449 The idea in this note meets these goals. 451 We briefly describe some alternative approaches that do not meet 452 these security goals. First, we consider the proliferation of 453 private keys. In order to allow one device to act as a proxy for a 454 server, the private key of the server could be shared with the proxy. 455 This practice may be workable when there is a one-to-one 456 correspondence between proxies and servers, but it substantially 457 increases the security risk. If a proxy contains multiple private 458 keys, it becomes an attractive target for an attacker. Second, we 459 consider the session-key proliferation approach in which there is 460 only a single TLS session, negotiated between the client and server, 461 and the proxy participates in the session because either the client 462 or the server has passed the secret session keys to the proxy (using 463 some secure channel). If the proxy is completely passive, and it 464 only decrypts traffic from the TLS session and never modifies the 465 data in that session, then this method can be secure. However, if 466 the proxy rewrites the data inside the session, or originates 467 messages, then the security of the TLS protocol will be undermined. 468 Message authentication can be subverted because an attacker can 469 intercept a message sent by the server, and forward it on to the 470 client, bypassing the proxy. By interleaving messages sent by the 471 proxy with ones sent by the server, an attacker can potentially 472 confuse a client, and can certainly cause a denial of service. 473 Confidentiality may be undermined as well; if RC4 or AES-GCM is in 474 use, information about the plaintext will be leaked due to keystream 475 reuse. Session-key proliferation is not secure when the proxy needs 476 to edit the session. Most proxies do need to edit the session, and 477 we regard it as potentially hazardous to construct a TLS proxy along 478 these lines. Suppose that such a proxy were implemented because it 479 was anticipated that the application proxy would be read-only, but 480 then a future revision to the application protocol or the goals of 481 the application proxy made it necessary to have the proxy edit the 482 application session. If the session-key proliferation approach had 483 been used, the implementer would be in the awkward position of having 484 to choose between implementing a completely new approach that 485 preserved security, and in risking the security of the application. 487 With the ProxyInfo extension, there is no protection against the 488 proxy lying about the security characteristics of the onward 489 connection. However, in any proxying scenario, it is necessary to 490 trust the proxy, just as a client must trust the server. For 491 instance, any proxy (not just one using the ProxyInfo extension) 492 could choose to forward the plaintext from the session to untrusted 493 third parties, and violate the trust of the client. It is the 494 responsibility of the client to decide whether or not a particular 495 device should be trusted to act in the role of proxy. The ProxyInfo 496 proposal has the benefit of making the presence of the proxy obvious, 497 and allows the client to refuse to deal with untrusted proxies. 499 Many clients use password-based authentication within a TLS tunnel. 500 When a proxy is present, it can learn plaintext passwords, and it can 501 gain the information needed to perform offline dictionary attacks 502 against authentication systems that use challenge-response methods. 503 This is a highly undesirable aspect of TLS proxying. The ProxyInfo 504 extension does nothing to directly help this issue. However, it does 505 indirectly improve the situation, because it empowers the client with 506 information that enables it to reject proxies and servers that it 507 should not trust. Since the TLS authentication (including both sever 508 and proxy authentication) takes place before the password-based 509 authentication, the client can protect itself by rejecting sessions 510 with inappropriate proxies, or inappropriate servers on the path 511 beyond the proxy. 513 In theory, the cryptographic proxying scenario could be considered as 514 multiparty security negotiation and key establishment. It may be 515 interesting to investigate such ideas because they can allow for more 516 equitable negotiation of session parameters, and additional security 517 properties. This note focuses on compatibility with existing 518 specifications and implementations, so these considerations are 519 beyond its scope. 521 7. Acknowledgements 523 Thanks are due to Dan Wing for suggestions and fruitful discussion. 525 8. References 527 8.1. Normative References 529 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 530 Requirement Levels", BCP 14, RFC 2119, March 1997. 532 [RFC2818] Rescorla, E., "HTTP Over TLS", RFC 2818, May 2000. 534 [RFC4366] Blake-Wilson, S., Nystrom, M., Hopwood, D., Mikkelsen, J., 535 and T. Wright, "Transport Layer Security (TLS) 536 Extensions", RFC 4366, April 2006. 538 [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security 539 (TLS) Protocol Version 1.2", RFC 5246, August 2008. 541 [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., 542 Housley, R., and W. Polk, "Internet X.509 Public Key 543 Infrastructure Certificate and Certificate Revocation List 544 (CRL) Profile", RFC 5280, May 2008. 546 8.2. Informative References 548 [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., 549 Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext 550 Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999. 552 Authors' Addresses 554 David A. McGrew 555 Cisco Systems 556 510 McCarthy Blvd. 557 Milpitas, CA 95035 558 US 560 Phone: (408) 525 8651 561 Email: mcgrew@cisco.com 562 URI: http://www.mindspring.com/~dmcgrew/dam.htm 564 Philip Gladstone 565 Cisco Systems 566 1414 Mass Ave 567 Boxborough, MA 01719 568 US 570 Email: pgladstone@cisco.com