<?xml version="1.0" encoding="US-ASCII"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!ENTITY RFC2119  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml'>
<!ENTITY RFC4648  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.4648.xml'>
<!ENTITY RFC4686  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.4686.xml'>
<!ENTITY RFC4871  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.4871.xml'>
<!ENTITY RFC5234  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.5234.xml'>
<!ENTITY RFC5321  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.5321.xml'>
<!ENTITY RFC5322  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.5322.xml'>
<!ENTITY RFC5451  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.5451.xml'>
<!ENTITY RFC5617  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.5617.xml'>
<!ENTITY FIPS.180-2.2002  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml2/reference.FIPS.180-2.2002'>
]>

<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
<?rfc compact="yes" ?>
<?rfc subcompact="yes" ?>
<?rfc toc="yes" ?>
<?rfc tocindent="yes" ?>
<?rfc symrefs="yes" ?>
<?rfc sortrefs="yes" ?>
<?rfc iprnotified="yes" ?>
<?rfc autobreaks="no"?>
<?rfc strict="yes" ?>

<rfc category="std" docName="draft-otis-dkim-tpa-label-02" ipr="trust200902">
  <front>
    <title abbrev="TPA-Label">DKIM Third-Party Authorization Label</title>

    <author fullname="Douglas Otis" initials="D." surname="Otis">
      <organization>Trend Micro</organization>
      <address>
        <postal>
          <street>10101 N. De Anza Blvd</street>
          <city>Cupertino</city>
          <region>CA</region>
          <code>95014</code>
          <country>USA</country>
        </postal>
        <phone>+1.408.257-1500</phone>
        <email>doug_otis@trendmicro.com</email>
      </address>
    </author>

    <date month="October" year="2009"/>
    <area>Internet Area</area>
    <workgroup>DKIM Working Group</workgroup>
    <keyword>DKIM-TPA-Label</keyword>
    <keyword>Draft</keyword>

    <abstract>
      <t>A TPA-Label is a DNS-based prefix for DKIM policy records that acts as a scheme for domains
        to authorize acceptable third-party signatures for messages containing their domain within
        the From header. This scheme allows Author 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
        schemes. Alternatives for facilitating third-party authorizations currently necessitate the
        coordination between two or more domains to synchronously set up selector/key DNS records,
        DNS zone delegations, and/or the regular exchange of public/private keys.</t>

      <t>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-Label transactions
        offer an efficient means for Author Domains to authorize specific third-party signing
          domains.<vspace blankLines="1"/></t>
    </abstract>

    <note title="Requirements Language">
      <t>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
          <xref target="RFC2119"/>.</t>
    </note>
  </front>

  <middle>
    <section title="Introduction">
      <t>This document describes how any Author Domain publishing DKIM policy records, such as those
        defined in <xref target="RFC5617"/>, can also autonomously authorize <xref target="RFC4871"
        /> signing by specific third-party domains. TPA-Label listed domains offer secondary policy
        compliance options when no valid Author Domain Signature is present within the message.
        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 the transactional
        results are best utilized.</t>

      <t>TPA-Labels authorize third-party signing domains as a means to extend DKIM policy
        compliance options defined by <xref target="RFC5617"/>. TPA-Label listed domains are to be
        considered equivalent to the authorizing Author Domain in the application of DKIM policies.
        The TXT records associated with TPA-Labels start with the 'dkim' tag as defined by <xref
          target="RFC5617"/>, and may contain tags specifically defined for TPA-Labels. This scheme
        can eliminate the complex coordination of selector/key DNS records, DNS delegation, or
        exchanges of public/private keys between two or more domains otherwise required to
        facilitate transparent authorizations.</t>

      <t>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. However, in the case of third-party signatures, the 'i='
        value will not directly reflect an email-address found within the From header, but would be
        in the form of an alias.</t>

      <t>TPA-Labels convey which third-party domains are authoritative. However, 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 submitting entities have demonstrated receipt of messages
        sent to the From header address contained within the domain's signed messages.<vspace
          blankLines="100"/></t>
    </section>

    <section title="Language and Terminology">
      <section title="Terms Imported from the DKIM ADSP Record Specification">
        <section title="Author Domain">
          <t>An "Author Domain" is everything to the right of the "@" in an Author Address
            (excluding the "@" itself).</t>
        </section>

        <section title="Author Domain Signature">
          <t>An "Author Domain Signature" is a Valid Signature in which the domain name of the DKIM
            signing entity, i.e., the 'd=' tag in the DKIM-Signature header field, is the same as
            the domain name in the Author Address. Following <xref target="RFC5321"/>, domain name
            comparisons are case insensitive.</t>
        </section>
      </section>

      <section title="Terms Defined by this Specification">
        <section title="TPA-Label Listed Domain">
          <t>TPA-Label Listed Domain, TPA-LLD, is the domain referenced as authorization to act on
            behalf of the Author Domain.</t>
        </section>

        <section title="Author's Domain Acceptable Third-Party Signature">
          <t>An "Author's Domain Acceptable Third-Party Signature" is a Valid Signature in which the
            domain name of the DKIM signing entity, i.e., the 'd=' tag in the DKIM-Signature header
            field, is the domain name referenced in the TPA-Label published by the Author Domain
            with a scope of 'F'. Following <xref target="RFC5321"/>, domain name comparisons as well
            as TPA-Labels are case insensitive.</t>
        </section>
      </section>
    </section>

    <section title="Evaluating Signing Domains">
      <t>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.</t>

      <t>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 Author Domain,
        message acceptance might become dependent upon an scheme that helps receivers to correlate
        DKIM signing domains and SMTP clients with domains that have been authorized to sign or
        transmit messages carrying the Author Domain.</t>

      <t>Appropriate abuse reporting is facilitated when signing domains correspond with domains
        administering SMTP Clients publicly transmitting messages. This correspondence between SMTP
        Client hosts with DKIM signing domains and Author Domains can be affirmed by the TPA-LLD
        scheme. A correspondence with SMTP Client hosts help determine which should be monitored for
        consistent IP address use. Relationships established between email related domains and
        stable hosts by the TPA-LLD scheme can provide improved message acceptance and reporting
        criteria.</t>

      <t>A receiver's 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 new or previously held domain names. Receivers may seek to limit a
        DKIM verification process, since acquiring policy records or DKIM keys may inadvertently
        leak valuable information that could 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 be limited to known trustworthy domains. Signing
        domains having good reputations referenced by a TPA-LLD might provide a means to safely
        extend limited verification resources to otherwise unknown Author Domains or SMTP
        Clients.</t>
    </section>

    <section title="Authorization Scope">
      <t>Without the TPA-LLD scheme, an authorization effort will likely involve sharing a number of
        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-LLD scheme permits the
        DKIM signature header to clarify who signed the message and on whose behalf, while also
        permitting greater control by the Author Domain.</t>

      <t>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. In addition, to better secure services that might depend upon DKIM keys,
        the TPA-LLD scheme allows Author Domains an ability to limit the scope of their
        authorizations, without being mistaken for having authenticated the entity submitting the
        message, or for running ancillary services that may make use of DKIM public keys.</t>

      <t>When an Author Domain is not within the DKIM signing domain, the TPA-LLD scheme safely
        extends policy compliance where a DNS publication is only required by the Author 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 messages contain authenticated identities
        either. The TPA-LLD scheme plays the role of only providing acceptable signatures which
        might be suitable for non-critical messages, where the goal would be to improve delivery
        acceptance, such as those from specific mailing-lists.</t>
    </section>

    <section title="TPA-Label Tag Definitions">
      <t>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 <xref target="RFC5617"/>, TPA-Label
        syntax descriptions use the form described in Augmented BNF for Syntax Specifications <xref
          target="RFC5234"/>. The "base32" function is defined in <xref target="RFC4648"/> and the
        "sha-1" hash function is defined in <xref target="FIPS.180-2.2002"/>. The TPA-Label TXT
        resource records follow the tag-value syntax described in section 4.2.1 of <xref
          target="RFC5617"/> and section 3.2 of <xref target="RFC4871"/>. Unrecognized tags and tags
        with illegal values MUST be ignored. In the ABNF below, the WSP token is inherited from
          <xref target="RFC5322"/>. The ALPHA and DIGIT tokens are imported from <xref
          target="RFC5234"/>. 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 as indicated by the ABNF
        definition. In addition, no newline character, (0x0A), should be appended to the end of the
        domain name, as might occur with command line generation of SHA1 values. Command line
        appended newlines can be avoided by using the 'echo -n" option, for example.<vspace
          blankLines="1"/></t>
      <t>The tags used in TPA-Label resource records are as follows:</t>
      <figure title="">
        <artwork name="" type="" height="" width="" xml:space="preserve">
  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))) 
    </artwork>
      </figure>
      <texttable title="TPA-Label Extended Parameters">
        <ttcol align="center">Tag</ttcol>
        <ttcol align="left">Function</ttcol>
        <c>scope=</c>
        <c>Authorization Scope List (as-list)</c>
        <!--  -->
        <c>tpa=</c>
        <c>Authorized Domains List (ad-list)</c>
        <!--  -->
      </texttable>

      <texttable title="TPA-Label Scope Values">
        <ttcol align="center" width="10%">Scope Values</ttcol>
        <ttcol align="left">Field or Parameter</ttcol>
        <c>F</c>
        <c>From (Author) Header</c>
        <!--  -->
        <c>O</c>
        <c>Other than From (Author) Headers</c>
        <!--  -->
        <c>M</c>
        <c>MailFrom</c>
        <!--  -->
        <c>H</c>
        <c>SMTP Host</c>
        <!--  -->
        <c>L</c>
        <c>List-ID</c>
        <!--  -->
        <c>NO-TPA</c>
        <c>All</c>
        <!--  -->
      </texttable>

      <t>The receiver obtains domain authorizations with a DNS query for an IN class TXT TPA-Label
        resource record located below the ADSP record location specified in <xref target="RFC5617"/>
        section 4.3. The TPA-Label is generated by processing the domain found within the DKIM
        signature's "d=" parameter (does not include the trailing period). A TPA-Label is published
        below the normal ADSP policy record, for example below
        "._adsp.domainkey.&lt;email-address domain&gt;". The existence of a TPA-Label
        provides authorization for the listed domain.</t>

      <t>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-Label resource record may be
        located at these domains:<list>
          <t/>
          <t>&lt;tpa-label&gt;._adsp._domainkey.&lt;email-address domain&gt;.</t>
        </list>
        <vspace blankLines="1"/></t>
    </section>
    <section title="Scope">
      <t>scope= Authorization Scope List (Optional). This tag defines a list of scoping assertions
        for various email-address locations within the message.</t>
      <t>
        <list>
          <t>scope = "F" / "O" / "M" / "H" / "L" / "NO-TPA"</t>
          <t>as-list = "scope" [WSP] "=" [WSP] scope 0*([WSP] ":" [WSP] scope)</t>
        </list>
      </t>

      <section title="TPA-Label Listed Domain Authorization">
        <section title="From (Author) Header Field">
          <t>The "F" scope asserts that messages carrying the Author Domain within the From header
            field are authorized to be signed by the TPA-LLD.<vspace blankLines="1"/></t>
        </section>
      </section>

      <section title="Use of Domain Authorization">
        <section title="Other Originating Header Fields">
          <t>The "O" scope asserts that messages with Sender or Resent-* header fields with
            email-address domains within the TPA-LLD are also authorized.<vspace blankLines="1"
            /></t>
        </section>

        <section title="MailFrom Parameter">
          <t>This "M" scope asserts that an email-address domain that is within a TPA-LLD used in
            the <xref target="RFC5321"/> MAIL command is also authorized.<vspace blankLines="1"
            /></t>
        </section>

        <section title="SMTP Host domains">
          <t>The "H" scope asserts that host names given in <xref target="RFC5321"/> EHLO or HELO
            commands within TPA-LLD are also authorized. This scope might be used to better ensure
            DKIM signatures within messages from these hosts are validated.<vspace blankLines="1"
            /></t>
        </section>
      </section>

      <section title="NO-TPA">
        <t>The "NO-TPA" scope asserts that the authorizing domain does not publish TPA-Labeled
          policy records. This scope is intended to be used in normal <xref target="RFC5617"/> ADSP
          records as a means to inhibit subsequent TPA-Label transactions.<vspace blankLines="1"
          /></t>
      </section>
    </section>
    <section title="Authorized Signing Domain">
      <t>tpa= Authorized Signing Domain list (Optional). This tag, if present, MUST repeat all or
        portions of the domain encoded within the TPA-Label. This option ensures the 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.</t>
      <t>
        <list>
          <t>ad = [ANY] domain</t>
          <t>ad-list = "tpa" [WSP] "=" [WSP] ad 0*([WSP] ":" [WSP] ad)</t>
          <t>
            <vspace blankLines="1"/>
          </t>
        </list>
      </t>
    </section>
    <section title="Use of TPA-Label Resource Records">
      <t>Use of TPA-Label resource record assertions need not be subsequent to the discovery of the
        policy record specified by <xref target="RFC5617"/>. When an acceptable Author Domain
        Signature was not discovered, and the From domain's <xref target="RFC5617"/> resource record
        contains the "scope" tag then:</t>
      <t>
        <list>
          <t>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:<vspace blankLines="1"/><list style="symbols">

              <t>When a TPA-Label TXT resource record referenced from the Author Domain has a scope
                tag of "F", and the TPA-LLD represents the domain of the DKIM signing entity, then
                the message is considered signed with an Author's Domain Acceptable Third-Party
                  Signature.<vspace blankLines="1"/></t>

              <t>When a TPA-Label TXT resource record within the Author Domain has a scope tag of
                "O", and the email-address domain within the Sender, or Resent-* headers are within
                the TPA-LLD, use of these headers by this domain is authorized by the Author's
                  Domain.<vspace blankLines="1"/></t>

              <t>When a TPA-Label TXT resource record within the Author Domain has a scope tag of
                "M", and the email-address domain within the <xref target="RFC5321"/> MAIL command
                is within the TPA-LLD, use of this command by this domain is authorized by the
                Author's Domain.<vspace blankLines="1"/></t>

              <t>When a TPA-Label TXT resource record within the Author Domain has a scope tag of
                "H", and a host domain given by <xref target="RFC5321"/> EHLO or HELO command is
                within the TPA-LLD, the SMTP client is authorized by the Author's Domain.<vspace
                  blankLines="1"/></t>

              <t>When a TPA-Label TXT resource record within the Author Domain has a scope tag of
                "L", and a host domain given by <xref target="RFC5321"/> EHLO or HELO command is
                within the TPA-LLD, the SMTP client is authorized by the Author's Domain.<vspace
                  blankLines="1"/></t>

              <t>When no TPA-Label TXT resource record is found or published, and a valid
                Third-party signature is acceptable to the verifier, then the message is considered
                signed by a Verifier Acceptable Third-Party Signature.</t>
            </list></t>
        </list>
      </t>
    </section>
    <section title="Authentication-Results Header Extended Results">
      <t>To accomodate the results derived from TPA-Label processing, section 2.2 of <xref
          target="RFC5451"/> needs to expand the 'ptype' list to include "tpa-label". The table in
        section 6.2 of <xref target="RFC5451"/> needs to include a 'ptype' of "tpa-label" with "lld"
        and "scope" properties. When 'scope' contains 'H', the 'iprev' results should also be
        included, in addition to 'dkim' results.</t>
    </section>

    <section anchor="IANA" title="IANA Considerations">
      <t>A registry has been established for DKIM policy record tags for RFC5617 which will need
        updated with the tags "tpa" and "scope".</t>
      <t>Note to RFC Editor: this section may be removed on publication as an RFC.</t>
    </section>
    <section anchor="Security" title="Security Considerations">
      <t>This draft extends signing policies related to <xref target="RFC4871"/>. 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 <xref target="RFC4686"/>.</t>

      <t>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.</t>

      <t>Use of the TPA-Label rather than simply listing the authorized domain ensures the maximal
        domain name size used with SMTP is reduced by less than 20%, rather than by an amount
        greater than 50% when attempting to include two domain names. The typical domain name size
        has been steadily increasing. This increase has been caused domain names that encode
        international character sets, and perhaps soon will be spurred by the expanse of TLDs having
        larger labels.<vspace blankLines="100"/></t>
    </section>
    <section anchor="Acknowledgements" title="Acknowledgements">
      <t>Daniel Black, Frank Ellermann, and Wietse Venema.<vspace blankLines="5"/></t>
    </section>
  </middle>

  <back>
    <references title="Normative References"> &RFC2119; &RFC4648; &RFC4871;
      &RFC5234; &RFC5321; &RFC5322; &RFC5451; &RFC5617; &FIPS.180-2.2002; </references>

    <references title="Informative References"> &RFC4686; </references>

    <section title="DNS Example of TPA-Label policy record placement" toc="default">
      <figure title="">
        <artwork name="" type="" height="" width="" xml:space="preserve">
 ####          
 # Policies for Example.com email domain using example.com, isp.com,
 # and example.com.isp.com as signing domains.
 ####

 #### 5322.From authorization for 3P domains ####
 #### Normal ADSP record indicating use of TPA-Labels ####
 
                                _adsp._domainkey.example.com.  IN TXT 
    "dkim=all; scope=F:O:M;"

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

 #### 5322.From/Originator/MailFrom authorization for 3P domains ####

 ## "example.com.isp.com" TPA-Label ##
 _6MEHLQLKWAL5HQREXWDN2TBXAJ6VZ44B._adsp._domainkey.example.com.  IN TXT
    "dkim=all; tpa=*.isp.com; scope=F:O:M;" 
        </artwork>
      </figure>
      <t>
        <vspace blankLines="100"/>
      </t>
    </section>
    <section title="C code for label generation">
      <t>The following utility can be compiled as tpa-label.c using the following:</t>
      <t>gcc -lcrypto tpa-label.c -o tpa-label</t>
      <figure title="">
        <artwork name="" type="" height="" width="" xml:space="preserve">
/*
 * TPA-Label generation utility 
 * Copyright (C) 2009 The IETF Trust &amp; 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 &lt;stdio.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;stddef.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;ctype.h&gt;
#include &lt;unistd.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;errno.h&gt;
#include &lt;openssl/sha.h&gt;

#define TPA_LABEL_VERSION   102
#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 &amp; 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 int 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 file */
                 (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 &amp;&amp; verbose)
    {
        (void) printf(sign_on, "tpa-label utility",
                      TPA_LABEL_VERSION / 100,
                      TPA_LABEL_VERSION % 100);
    }

    for (i = 0; i &lt; MAX_DOMAIN_NAME &amp;&amp; !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 &amp;&amp; in_buf[len - 1] == '.')    /* remove any trailing "." */
    {
        len--;
        in_buf[len] = 0;     /* replace trailing "." with 0 */
    }

    in_buf[len] = 0;         /* terminate string */  
                                
    if (len &lt; 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 &lt; 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 &lt; 4 ; i++)         
    {
        b_5 =  (unsigned long long) sha_res[(i * 5)] &lt;&lt; 32;
        b_5 |= (unsigned long long) sha_res[(i * 5) + 1] &lt;&lt; 24;
        b_5 |= (unsigned long long) sha_res[(i * 5) + 2] &lt;&lt; 16;
        b_5 |= (unsigned long long) sha_res[(i * 5) + 3] &lt;&lt; 8;
        b_5 |= (unsigned long long) sha_res[(i * 5) + 4];
 
        if (verbose)
        {
            printf(" {%010llX}-&gt;", b_5);
        }

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

            if (verbose)
            {
                 printf(" %02X:%c", 
                        (unsigned int)(b_5 &gt;&gt; k) &amp; 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);
}
        </artwork>
      </figure>
    </section>
  </back>
</rfc>

