TOC 
DKIM Working GroupD. Otis
Internet-DraftTrend Micro
Intended status: Standards TrackOctober 08, 2009
Expires: April 11, 2010 


DKIM Third-Party Authorization Label
draft-otis-dkim-tpa-label-00

Status of this Memo

This Internet-Draft is submitted to IETF in full conformance with the provisions of BCP 78 and BCP 79.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF), its areas, and its working groups. Note that other groups may also distribute working documents as Internet-Drafts.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as “work in progress.”

The list of current Internet-Drafts can be accessed at http://www.ietf.org/ietf/1id-abstracts.txt.

The list of Internet-Draft Shadow Directories can be accessed at http://www.ietf.org/shadow.html.

This Internet-Draft will expire on April 11, 2010.

Copyright Notice

Copyright (c) 2009 IETF Trust and the persons identified as the document authors. All rights reserved.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents in effect on the date of publication of this document (http://trustee.ietf.org/license-info). Please review these documents carefully, as they describe your rights and restrictions with respect to this document.

Abstract

TPA-label is a DNS-based prefix mechanism for DKIM policy related records as a means to authorize Third-Party domains, such as mailing-lists. This mechanism allows first-party domains to autonomously authorize a range of third-party domains using scalable, individual DNS transactions. This authorization extends the scope of DKIM policy assertions as a means to supplant more difficult to administer mechanisms. Alternatives for facilitating third-party authorizations currently necessitate coordination between two or more domains to synchronously set up selector/key DNS records, DNS zone delegations, or the regular exchange of public/private keys.

Checking DKIM policies may occur when a From header email-address is not within the domain of a valid DKIM signature. When a Third-Party signature is found, TPA-Labels offer an efficient means for email address domains to authorize specific third-party signing domains.

Requirements Language

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119] (Bradner, S., “Key words for use in RFCs to Indicate Requirement Levels,” March 1997.).



Table of Contents

1.  Introduction
2.  Evaluating Signing Domains
3.  Authorization Scope
4.  TPA-Label Tag Definitions
5.  Scope
    5.1.  From (Author) Header Field
    5.2.  MailFrom Parameter
    5.3.  Other Originating Header Fields
    5.4.  SMTP Host domains
    5.5.  NO-TPA
6.  Authorized Signing Domain
7.  Use of TPA-Label Resource Records
8.  IANA Considerations
9.  Security Considerations
10.  Acknowledgements
11.  References
    11.1.  Normative References
    11.2.  Informative References
Appendix A.  DNS Example of TPA-Label policy record placement
Appendix B.  C code for label generation
§  Author's Address




 TOC 

1.  Introduction

This document describes how any email-address domain publishing DKIM policy records such as those defined in [RFC5617] (Allman, E., Fenton, J., Delany, M., and J. Levine, “DomainKeys Identified Mail (DKIM) Author Domain Signing Practices (ADSP),” August 2009.) can also autonomously authorize [RFC4871] (Allman, E., Callas, J., Delany, M., Libbey, M., Fenton, J., and M. Thomas, “DomainKeys Identified Mail (DKIM) Signatures,” May 2007.) signing by specific third-party domains. Recommended or suggested actions for DKIM receivers are not included, and are considered "out-of-scope" for this document. The receiver is assumed to better understand their environment's impact upon the performance of DKIM signatures and how results are best utilized.

TPA-Labels authorize signing domains as a means to permit compliance with DKIM policies such those defined by [RFC5617] (Allman, E., Fenton, J., Delany, M., and J. Levine, “DomainKeys Identified Mail (DKIM) Author Domain Signing Practices (ADSP),” August 2009.). TPA-Label authorized domains are to be considered equivalent to the authorizing domain for the application of DKIM policies. The TXT records associated with these TPA-Labels start with the 'dkim' tag defined by [RFC5617] (Allman, E., Fenton, J., Delany, M., and J. Levine, “DomainKeys Identified Mail (DKIM) Author Domain Signing Practices (ADSP),” August 2009.) in addition to assertions that are specifically for TPA-Labels as defined within this document. This mechanism can eliminate the complex coordination of selector/key DNS records, DNS delegation, or exchanges of public/private keys between two or more domains that would otherwise be required to facilitate otherwise transparent authorizations.

Trust is an essential requisite before the DKIM signature header field's 'i=' semantics provide valuable advisory information. This advisory information is in regard to the "on-behalf-of" identity as a means to enable safer message annotations and to better ensure trusted identities are recognized. In the case of third-party signatures, the i= value will not directly reflect an email-address found witin the From header, but would be in the form of an alias.

TPA-Labels convey which third-party domains are authoritative. Third-party domains are unable to utilize DKIM signature's 'i=' semantics to directly assert which identifiers on whose behalf a signature was added. As such, no third-party domain should be authorized unless it is trusted to ensure that submitting entities have demonstrated receipt of messages sent to the From header address contained within message being signed.



 TOC 

2.  Evaluating Signing Domains

Regulatory agencies are unable to control Internet abuse by curtailing access. Unlike IPv4 addresses, there is virtually no limit on the number of domain-names available. Registrar pricing of domain-names need to remain uniform. Otherwise, fees based upon the intrinsic value of a name could cause name holders to become extortion targets. High initial costs for domain-names are also unlikely to represent a deterrent, largely due to high levels of payment fraud.

In addition, DKIM can not directly identify the domain transmitting the message, and can not prevent abusive message replay. Abusive message replay may prove indistinguishable from bulk mailings of various types. Since abuse may be beyond the control of the signing domain, message acceptance will likely remain dependent upon the reputation of the SMTP client's IP address and associated hosts, and perhaps that of the identity represented within the 'i=' parameter found within the DKIM signature header. Abuse reporting facilitated by DKIM signatures should therefore first select signing domains that correspond with domains administering the SMTP Client publicly transmitting the message. As such, correspondence between the SMTP Client host and the DKIM signing domain might also be affirmed by TPA-Label authorizations.

The receiver's domain evaluation process will confront many domains with unknown reputations. New domains are constantly being introduced where registrars are unable to prevent bad actors from controlling either a new or previously held domain names. The receiver may seek to limit the DKIM verification process, since acquiring policy records or DKIM keys may inadvertently leak valuable information that benefit bad actors. Processing all DKIM signatures may also inundate a receiver's limited resources. As a result, validating DKIM signatures and obtaining related resource records might become limited to known trustworthy domains. Signing domains authorized with TPA-Labels by domains having good reputations might then provide a means to safely extend limited verification resources.



 TOC 

3.  Authorization Scope

Without using TPA-Labels, an authorization effort will likely involve sharing details between the domain owner, and one or more email and DNS providers. Since there are many ways in which such authorizations can be accomplished, it is unlikely there will be consistent or standardized formats developed to exchange necessary, and at times, sensitive information. In addition, when there is a security breach, the wrong party might be held accountable for content they may have never seen nor logged. The TPA-Label authorization scheme permits the content of the DKIM signature header to clarify who signed the message and on whose behalf, while also permitting greater control by the authorizing domain.

TPA-Label resource records replace domain delegations, selector/key record mirroring, or key exchanges. Significant amounts of detail is associated with selector/key records. These details include user limitations, suitable services, key resource record's Time-To-Live, revocation and update procedures, and how the DKIM Signature header field's 'i=' semantics are to be applied. The TPA-Labeled policy records allow authorizing domains an improved ability to limit the scope of their authorizations, without being mistaken for having authenticated the entity submitting the message.

When a signing domain differs from that of a domain within the header email-address, TPA-Label resource records safely extend policy compliance where DNS publication is only required by the email-address domain even when signing domains and the email-address domains differ. While offering only valid signatures will not ensure all possible spoofing is prevented, messages signed in this manner should not receive annotations indicating there are authenticated identities either. Authorizing domains to play the role of only providing acceptable signatures may be suitable for non-critical messages, where the goal might be to improve delivery acceptance, such as those from mailing-lists.



 TOC 

4.  TPA-Label Tag Definitions

Every TPA-Label TXT resource record MUST start with an outbound signing-practices tag, so the first four characters of the record are lowercase "dkim", followed by optional whitespace and "=". In addition to tags defined by [RFC5617] (Allman, E., Fenton, J., Delany, M., and J. Levine, “DomainKeys Identified Mail (DKIM) Author Domain Signing Practices (ADSP),” August 2009.), TPA-Label syntax descriptions use the form described in Augmented BNF for Syntax Specifications [RFC5234] (Crocker, D. and P. Overell, “Augmented BNF for Syntax Specifications: ABNF,” January 2008.). The "base32" function is defined in [RFC4648] (Josefsson, S., “The Base16, Base32, and Base64 Data Encodings,” October 2006.) and the "sha-1" hash function is defined in [FIPS.180‑2.2002] (National Institute of Standards and Technology, “Secure Hash Standard,” August 2002.). The TPA-Label TXT resource records follow the tag-value syntax described in section 4.2.1 of [RFC5617] (Allman, E., Fenton, J., Delany, M., and J. Levine, “DomainKeys Identified Mail (DKIM) Author Domain Signing Practices (ADSP),” August 2009.) and section 3.2 of [RFC4871] (Allman, E., Callas, J., Delany, M., Libbey, M., Fenton, J., and M. Thomas, “DomainKeys Identified Mail (DKIM) Signatures,” May 2007.). Unrecognized tags and tags with illegal values MUST be ignored. In the ABNF below, the WSP token is inherited from [RFC5322] (Resnick, P., Ed., “Internet Message Format,” October 2008.). The ALPHA and DIGIT tokens are imported from [RFC5234] (Crocker, D. and P. Overell, “Augmented BNF for Syntax Specifications: ABNF,” January 2008.). The function "lcase" converts upper-case ALPHA characters to lower-case. The function "sha-1" returns a hash that is converted to a base32 character set. The terminating period is not included in domain-name conversions. In addition, a newline character (0x0A) is appended to the end of the string to match a command line generation of SHA1 values. The tags used in TPA-Labeled policy records are as follows:

  asterisk = %x2A ; "*"
  dash = %x2D ; "-"
  dot = %x2E ; "."
  underscore = %x5F ; "_"
  ANY = asterisk dot ; "*."
  dns-char = ALPHA / DIGIT / dash
  id-prefix = ALPHA / DIGIT
  label = id-prefix [*61dns-char id-prefix]
  sldn = label dot label
  base-char = (dns-char / underscore)
  domain = *(label dot) sldn
  tpa-label = underscore base32( sha-1( lcase(signing-domain)))


TagFunction
scope= Authorization Scope List (as-list)
tpa= Authorized Domains List (ad-list)

 TPA-Label Extended Parameters 



Scope ValuesField or Parameter
F From (Author) Header
O Other than From (Author) Headers
M MailFrom
H SMTP Host
NO-TPA All

 TPA-Label Scope Values 

The receiver obtains the TPA-Label record for the email-address domain using a DNS query for an IN class TXT resource record. The TPA-Label is created by processing the domain found within the signature's "d=" parameter (does not include the trailing period). The TPA-Label would be placed below the normal policy records, for example "._adsp.domainkey.<email-address domain>". These labels would then be used to access the TPA-Labeled policy TXT records. Character-strings contained within the TXT resource record are concatenated into forming a single string. A character-string is a single length octet followed by that number of characters treated as binary information. As an example, a TPA-Labeled policy record may be located at these domains:

<tpa-label>._adsp._domainkey.<email-address domain>.





 TOC 

5.  Scope

scope= Authorization Scope List (Optional). This tag defines a list of scoping assertions for various email-address locations within the message.

scope = "F" / "O" / "M" / "H" / "NO-TPA"

as-list = "scope" [WSP] "=" [WSP] scope 0*([WSP] ":" [WSP] scope)



 TOC 

5.1.  From (Author) Header Field

The "F" scope asserts that messages carrying the email-address domain within the From header field are authorized to be signed by the tpa listed domain.



 TOC 

5.2.  MailFrom Parameter

This "M" scope asserts that messages carrying the email-address domain within the MailFrom parameter are also authorized to be signed by the authorized domain.



 TOC 

5.3.  Other Originating Header Fields

The "O" scope asserts that messages carrying the email-address domain within the Sender or Resent-* header fields are authorized to be signed by the authorized domain.



 TOC 

5.4.  SMTP Host domains

The "H" scope asserts that messages transmitted by SMTP hosts have been authorized. This scope might be used to better ensure DKIM signatures are validated.



 TOC 

5.5.  NO-TPA

The "NO-TPA" scope asserts that domain does not publish TPA-Labeled policy records.



 TOC 

6.  Authorized Signing Domain

tpa= Authorized Signing Domain list (Optional). This tag repeats all or portions of the domain encoded within the TPA-Label. This option ensures proper handling of possible hash collisions. When a domain is prefixed with the "*." ANY label, then all subdomains of this domain are to be considered included within the list.

ad = [ANY] domain

ad-list = "tpa" [WSP] "=" [WSP] ad 0*([WSP] ":" [WSP] ad)





 TOC 

7.  Use of TPA-Label Resource Records

Use of TPA-Label resource record assertions need not be are subsequent to the discovery of the policy record specified by [RFC5617] (Allman, E., Fenton, J., Delany, M., and J. Levine, “DomainKeys Identified Mail (DKIM) Author Domain Signing Practices (ADSP),” August 2009.). When an acceptable First-Party signature was not discovered, and the From domain's [RFC5617] (Allman, E., Fenton, J., Delany, M., and J. Levine, “DomainKeys Identified Mail (DKIM) Author Domain Signing Practices (ADSP),” August 2009.) resource record contains the "scope" tag then:

When one or more valid Third-Party Signatures are present in the message, and a scope tag exists within the normal policy record, and the scope tag does not contain "NO-TPA", then:



 TOC 

8.  IANA Considerations

A registry has been established for DKIM policy record tags for RFC5617 which will need updated with the tags "tpa" and "scope".

Note to RFC Editor: this section may be removed on publication as an RFC.



 TOC 

9.  Security Considerations

This draft extends signing policies related to [RFC4871] (Allman, E., Callas, J., Delany, M., Libbey, M., Fenton, J., and M. Thomas, “DomainKeys Identified Mail (DKIM) Signatures,” May 2007.). Security considerations are mostly related to attempts on the part of malicious senders to represent themselves as other senders, often in an attempt to defraud either the recipient or the alleged originator. Additional security considerations regarding DKIM signing practices may be found in the DKIM threat analysis [RFC4686] (Fenton, J., “Analysis of Threats Motivating DomainKeys Identified Mail (DKIM),” September 2006.).

The use of the SHA-1 hash algorithm does not represent a security concern. The hash simply ensures a deterministic domain-name size is achieved. Unexpected collisions can be detected and handled by using the extended TPA-Label "tpa=" option.



 TOC 

10.  Acknowledgements

Frank Ellermann and Wietse Venema.







 TOC 

11.  References



 TOC 

11.1. Normative References

[FIPS.180-2.2002] National Institute of Standards and Technology, “Secure Hash Standard,” FIPS PUB 180-2, August 2002.
[RFC2119] Bradner, S., “Key words for use in RFCs to Indicate Requirement Levels,” BCP 14, RFC 2119, March 1997 (TXT, HTML, XML).
[RFC4648] Josefsson, S., “The Base16, Base32, and Base64 Data Encodings,” RFC 4648, October 2006 (TXT).
[RFC4871] Allman, E., Callas, J., Delany, M., Libbey, M., Fenton, J., and M. Thomas, “DomainKeys Identified Mail (DKIM) Signatures,” RFC 4871, May 2007 (TXT).
[RFC5234] Crocker, D. and P. Overell, “Augmented BNF for Syntax Specifications: ABNF,” STD 68, RFC 5234, January 2008 (TXT).
[RFC5321] Klensin, J., “Simple Mail Transfer Protocol,” RFC 5321, October 2008 (TXT).
[RFC5322] Resnick, P., Ed., “Internet Message Format,” RFC 5322, October 2008 (TXT, HTML, XML).
[RFC5617] Allman, E., Fenton, J., Delany, M., and J. Levine, “DomainKeys Identified Mail (DKIM) Author Domain Signing Practices (ADSP),” RFC 5617, August 2009 (TXT).


 TOC 

11.2. Informative References

[RFC4686] Fenton, J., “Analysis of Threats Motivating DomainKeys Identified Mail (DKIM),” RFC 4686, September 2006 (TXT).


 TOC 

Appendix A.  DNS Example of TPA-Label policy record placement

 ####
 # Policies for Example.com email domain using example.com, isp.com,
 # and example.com.isp.com as signing domains.
 ####

 #### 5322.From authorization for TP domains ####
                                _adsp._domainkey.example.com.  IN TXT
    "dkim=all; scope=F:O:M;"

 ## "isp.com" TPA-Label ##
 _HGSSD3SNMI6635J5743VDJHAJKMPMFIF._adsp._domainkey.example.com. IN TXT
    "dkim=all; tpa=isp.com; scope=F;"

 #### 5322.From/Originator/MailFrom authorization for TP domains ####

 ## "example.com.isp.com" TPA-Label ##
 _ZZHFFXWCFI7RPDDQDIGYHPBTAA7VWITU._adsp._domainkey.example.com.  IN TXT
    "dkim=all; tpa=*.isp.com; scope=F:O:M;"



 TOC 

Appendix B.  C code for label generation

The following utility can be compiled as tpa-label.c using the following:

gcc -lcrypto tpa-label.c -o tpa-label

/*
 * TPA-Label generation utility
 * Copyright (C) 2009 The IETF Trust & and the persons identified as
 * the document authors.  All rights reserved.
 * Redistributions of source code must retain the above copyright
 * notice and the following disclaimer.
 *
 * This document is subject to the rights, licenses and restrictions
 * contained in BCP 78, and except as set forth therein, the authors
 * retain all their rights.
 * This document and the information contained herein are provided on an
 * "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
 * OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
 * THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
 * THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
 * WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
 */

#include <stdio.h>
#include <sys/types.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <openssl/sha.h>

#define TPA_LABEL_VERSION   100
#define MAX_DOMAIN_NAME     256
#define MAX_FILE_NAME       1024

static char base32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
static char sign_on[] =
{"%s v%d.%02d Copyright (C) (2009) The IETF Trust & Douglas Otis\n"};
char err_cmd[] =\
 "ERR: Command error with [%s]\n";
char use_txt[]=\
 "Usage: TPA-Label [-i domain_input_file] [-o label_output_file][-v]\n";
char help_txt[]=\
"The options are as follows:\n"\
"-i  domain name input. Defaults to stdin. Removes trailing '.'\n"\
"-o  TPA-Label output.  Defaults to stdout.\n"\
"-v  Specifies Verbose Mode.\n\n";

static void usage(void);
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

static void
usage(void)
{
    (void) fprintf(stderr, "\n%s%s", use_txt, help_txt);
    exit(1);
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

int
main (int argc, char * argv[])
{
    int  ret_val, in_mode, out_mode, verbose, done, i, j, k;
    char ch;
    unsigned long len;
    unsigned long long b_5;
    char in_fn[MAX_FILE_NAME], out_fn[MAX_FILE_NAME];
    unsigned char in_buf[MAX_DOMAIN_NAME + 2];
    unsigned char sha_res[20], tpa_label[33];
    FILE *in_file, *out_file;

    ret_val = in_mode = out_mode = verbose = done = 0;
    len = 0;

    while ((ch = getopt(argc, argv, "i:o:v")) != -1)
    {
        switch (ch)
        {
            case 'i':
                in_mode = 1;          /* input from file */
                (void) strncpy(in_fn, optarg, sizeof(in_fn));
                in_fn[sizeof(in_fn) - 1] = '\0';
                break;
            case 'o':
                 out_mode = 1;         /* out to time */
                 (void) strncpy(out_fn, optarg, sizeof(out_fn));
                 out_fn[sizeof(out_fn) - 1] = '\0';
                 break;
            case 'v':
                 verbose = 1;
                 break;
            case '?':
            default:
                (void) usage();
                break;
        }
    };

    if (in_mode)
    {
        if ((in_file = fopen(in_fn, "r")) == NULL)
        {
            (void) fprintf(stderr,
                           "ERR: Error opening [%s] input file.\n",
                           in_fn);
            exit(2);
        }
    }
    else
    {
        in_file = stdin;
    }

    if (out_mode)
    {
        if ((out_file = fopen(out_fn, "w")) == NULL)
        {
            (void) fprintf(stderr,
                           "ERR: Error opening [%s] output file.\n",
                           out_fn);
            exit(3);
        }
    }
    else
    {
        out_file = stdout;
    }

    if (out_mode && verbose)
    {
        (void) printf(sign_on, "tpa-label utility",
                      TPA_LABEL_VERSION / 100,
                      TPA_LABEL_VERSION % 100);
    }

    for (i = 0; i < MAX_DOMAIN_NAME && !done; i++)
    {
        if ((ch = fgetc(in_file)) == EOF)
        {
            ch = 0;
        }
        else  if (ch == '\n' || ch == '\r')
        {
            ch = 0;
        }

        in_buf[i] = tolower(ch);

        if (ch == 0)
        {
            len = i;         /* string length */
            done = 1;
        }
    }

    if (!done)
    {
        (void) fprintf(stderr, "ERR: Domain name too long.\n");
        exit (4);
    }

    if (len && in_buf[len - 1] == '.')    /* remove any trailing "." */
    {
        len--;
        in_buf[len] = 0;     /* replace trailing "." with 0 */
    }

    in_buf[len++] = '\n';    /* newline simulates commmand-line use */
    in_buf[len] = 0;         /* terminate string */

    if (len < 2)
    {
        (void)
        fprintf(stderr,
                "ERR: Domain name [%s] too short with %d length.\n",
                in_buf,
                len);
        exit (5);
    }

    SHA1(in_buf, len, sha_res);

    if (verbose)
    {
        printf("Normalized Domain = [%s] %d, SHA-1 = ", in_buf, len);

        for (i = 0; i < 20; i++)
        {
            printf("%02X", sha_res[i]);
        }
        printf("\nTPA-Label: 5 bit intervals left to right.\n");
    }

    /* process sha-1 results 4 times by 40 bits 0 to 160 */

    for (i = 0, j = 0; i < 4 ; i++)
    {
        b_5 =  (unsigned long long) sha_res[(i * 5)] << 32;
        b_5 |= (unsigned long long) sha_res[(i * 5) + 1] << 24;
        b_5 |= (unsigned long long) sha_res[(i * 5) + 2] << 16;
        b_5 |= (unsigned long long) sha_res[(i * 5) + 3] << 8;
        b_5 |= (unsigned long long) sha_res[(i * 5) + 4];

        if (verbose)
        {
            printf(" {%010llX}->", b_5);
        }

        for (k = 35; k >= 0; k-= 5, j++)    /* convert 40 bits (5x8) */
        {
            tpa_label[j] = base32[(b_5 >> k) & 0x1F];

            if (verbose)
            {
                 printf(" %02X:%c",
                        (unsigned int)(b_5 >> k) & 0x1F,
                        tpa_label[j]);
            }
        }
        if (verbose)
        {
            printf ("\n");
        }
    }
    if (verbose)
    {
        printf("\n");
    }

    tpa_label[j] = 0;   /* terminate label string */
    fprintf(out_file, "_%s", tpa_label);
    printf("\n");

    /* close */
    if (out_mode)
    {
        if (fclose (out_file) != 0)
        {
            (void) fprintf(stderr,
                           "ERR: Unable to close %s output file.\n",
                           out_fn);
            ret_val = 6;
        }
    }
    if (in_mode)
    {
        if (fclose (in_file) != 0)
        {
            (void) fprintf(stderr,
                           "ERR: Unable to close %s input file.\n",
                           in_fn);
             ret_val = 7;
        }
    }
    return (ret_val);
}


 TOC 

Author's Address

  Douglas Otis
  Trend Micro
  10101 N. De Anza Blvd
  Cupertino, CA 95014
  USA
Phone:  +1.408.257-1500
Email:  doug_otis@trendmicro.com