"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.11/smtp-gssapi.h" (8 Aug 2018, 10079 Bytes) of package /linux/misc/s-nail-14.9.11.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "smtp-gssapi.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 14.9.10_vs_14.9.11.

    1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
    2  *@ Implementation of SMTP GSS-API authentication according to RFC 4954.
    3  *@ TODO GSS-API should also be joined into "a VFS".
    4  *
    5  * Copyright (c) 2014 - 2018 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
    6  * SPDX-License-Identifier: BSD-4-Clause
    7  */
    8 
    9 /* Derived from `imap_gssapi.h', which is:
   10  *
   11  * Copyright (c) 2004 Gunnar Ritter.
   12  * All rights reserved.
   13  *
   14  * Redistribution and use in source and binary forms, with or without
   15  * modification, are permitted provided that the following conditions
   16  * are met:
   17  * 1. Redistributions of source code must retain the above copyright
   18  *    notice, this list of conditions and the following disclaimer.
   19  * 2. Redistributions in binary form must reproduce the above copyright
   20  *    notice, this list of conditions and the following disclaimer in the
   21  *    documentation and/or other materials provided with the distribution.
   22  * 3. All advertising materials mentioning features or use of this software
   23  *    must display the following acknowledgement:
   24  *    This product includes software developed by Gunnar Ritter
   25  *    and his contributors.
   26  * 4. Neither the name of Gunnar Ritter nor the names of his contributors
   27  *    may be used to endorse or promote products derived from this software
   28  *    without specific prior written permission.
   29  *
   30  * THIS SOFTWARE IS PROVIDED BY GUNNAR RITTER AND CONTRIBUTORS ``AS IS'' AND
   31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   33  * ARE DISCLAIMED.  IN NO EVENT SHALL GUNNAR RITTER OR CONTRIBUTORS BE LIABLE
   34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   40  * SUCH DAMAGE.
   41  */
   42 /*
   43  * Partially derived from sample code in:
   44  *
   45  * GSS-API Programming Guide
   46  * Part No: 816-1331-11
   47  * Sun Microsystems, Inc. 4150 Network Circle Santa Clara, CA 95054 U.S.A.
   48  *
   49  * (c) 2002 Sun Microsystems
   50  */
   51 /*
   52  * Copyright 1994 by OpenVision Technologies, Inc.
   53  * 
   54  * Permission to use, copy, modify, distribute, and sell this software
   55  * and its documentation for any purpose is hereby granted without fee,
   56  * provided that the above copyright notice appears in all copies and
   57  * that both that copyright notice and this permission notice appear in
   58  * supporting documentation, and that the name of OpenVision not be used
   59  * in advertising or publicity pertaining to distribution of the software
   60  * without specific, written prior permission. OpenVision makes no
   61  * representations about the suitability of this software for any
   62  * purpose.  It is provided "as is" without express or implied warranty.
   63  * 
   64  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
   65  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
   66  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
   67  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
   68  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
   69  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
   70  * PERFORMANCE OF THIS SOFTWARE.
   71  */
   72 
   73 #ifdef HAVE_GSSAPI
   74 #ifndef GSSAPI_REG_INCLUDE
   75 # include <gssapi/gssapi.h>
   76 # ifdef GSSAPI_OLD_STYLE
   77 #  include <gssapi/gssapi_generic.h>
   78 #  define GSS_C_NT_HOSTBASED_SERVICE   gss_nt_service_name
   79 #  define m_DEFINED_GCC_C_NT_HOSTBASED_SERVICE
   80 # endif
   81 #else
   82 # include <gssapi.h>
   83 #endif
   84 
   85 static void _smtp_gssapi_error1(char const *s, OM_uint32 code, int typ);
   86 static void _smtp_gssapi_error(char const *s, OM_uint32 maj_stat,
   87                OM_uint32 min_stat);
   88 
   89 static void
   90 _smtp_gssapi_error1(char const *s, OM_uint32 code, int typ)
   91 {
   92    OM_uint32 maj_stat, min_stat;
   93    gss_buffer_desc msg = GSS_C_EMPTY_BUFFER;
   94    OM_uint32 msg_ctx = 0;
   95    NYD_ENTER;
   96 
   97    do {
   98       maj_stat = gss_display_status(&min_stat, code, typ, GSS_C_NO_OID,
   99             &msg_ctx, &msg);
  100       if (maj_stat == GSS_S_COMPLETE) {
  101          n_err(_("GSS error: %s / %.*s\n"),
  102             s, (int)msg.length, (char*)msg.value);
  103          gss_release_buffer(&min_stat, &msg);
  104       } else {
  105          n_err(_("GSS error: %s / unknown\n"), s);
  106          break;
  107       }
  108    } while (msg_ctx);
  109    NYD_LEAVE;
  110 }
  111 
  112 static void
  113 _smtp_gssapi_error(char const *s, OM_uint32 maj_stat, OM_uint32 min_stat)
  114 {
  115    NYD_ENTER;
  116    _smtp_gssapi_error1(s, maj_stat, GSS_C_GSS_CODE);
  117    _smtp_gssapi_error1(s, min_stat, GSS_C_MECH_CODE);
  118    NYD_LEAVE;
  119 }
  120 
  121 static bool_t
  122 _smtp_gssapi(struct sock *sp, struct sendbundle *sbp, struct smtp_line *slp)
  123 {
  124    struct str in, out;
  125    gss_buffer_desc send_tok, recv_tok;
  126    gss_name_t target_name;
  127    gss_ctx_id_t gss_context;
  128    OM_uint32 maj_stat, min_stat, ret_flags;
  129    int conf_state;
  130    enum{
  131       a_F_NONE,
  132       a_F_RECV_TOK = 1u<<0,
  133       a_F_SEND_TOK = 1u<<1,
  134       a_F_TARGET_NAME = 1u<<2,
  135       a_F_GSS_CONTEXT = 1u<<3
  136    } f;
  137    bool_t ok;
  138    NYD_ENTER;
  139 
  140    ok = FAL0;
  141    f = a_F_NONE;
  142 
  143    if(INT_MAX - 1 - 4 <= sbp->sb_ccred.cc_user.l)
  144       goto jleave;
  145 
  146    send_tok.value = n_autorec_alloc(
  147          (send_tok.length = sbp->sb_url.url_host.l + 5) +1);
  148    memcpy(send_tok.value, "smtp@", 5);
  149    memcpy((char*)send_tok.value + 5, sbp->sb_url.url_host.s,
  150       sbp->sb_url.url_host.l +1);
  151    maj_stat = gss_import_name(&min_stat, &send_tok, GSS_C_NT_HOSTBASED_SERVICE,
  152          &target_name);
  153    f |= a_F_TARGET_NAME;
  154    if (maj_stat != GSS_S_COMPLETE) {
  155       _smtp_gssapi_error(savestrbuf(send_tok.value, send_tok.length),
  156          maj_stat, min_stat);
  157       goto jleave;
  158    }
  159 
  160    gss_context = GSS_C_NO_CONTEXT;
  161    maj_stat = gss_init_sec_context(&min_stat,
  162          GSS_C_NO_CREDENTIAL,
  163          &gss_context,
  164          target_name,
  165          GSS_C_NO_OID,
  166          GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
  167          0,
  168          GSS_C_NO_CHANNEL_BINDINGS,
  169          GSS_C_NO_BUFFER,
  170          NULL,
  171          &send_tok,
  172          &ret_flags,
  173          NULL);
  174    f |= a_F_SEND_TOK | a_F_GSS_CONTEXT;
  175    if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) {
  176       _smtp_gssapi_error("initializing GSS context", maj_stat, min_stat);
  177       goto jleave;
  178    }
  179 
  180    _OUT(NETLINE("AUTH GSSAPI"));
  181    _ANSWER(3, FAL0, FAL0);
  182    while (maj_stat == GSS_S_CONTINUE_NEEDED) {
  183       /* Pass token obtained from first gss_init_sec_context() call */
  184       if(b64_encode_buf(&out, send_tok.value, send_tok.length,
  185             B64_SALLOC | B64_CRLF) == NULL)
  186          goto jleave;
  187       gss_release_buffer(&min_stat, &send_tok);
  188       f &= ~a_F_SEND_TOK;
  189       _OUT(out.s);
  190       _ANSWER(3, FAL0, TRU1);
  191 
  192       out.s = NULL;
  193       in.s = slp->dat;
  194       in.l = slp->datlen;
  195       if(!b64_decode(&out, &in))
  196          goto jebase64;
  197       recv_tok.value = out.s;
  198       recv_tok.length = out.l;
  199       maj_stat = gss_init_sec_context(&min_stat,
  200             GSS_C_NO_CREDENTIAL,
  201             &gss_context,
  202             target_name,
  203             GSS_C_NO_OID,
  204             GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
  205             0,
  206             GSS_C_NO_CHANNEL_BINDINGS,
  207             &recv_tok,
  208             NULL,
  209             &send_tok,
  210             &ret_flags,
  211             NULL);
  212       n_free(out.s);
  213       f |= a_F_SEND_TOK;
  214       if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) {
  215          _smtp_gssapi_error("initializing context", maj_stat, min_stat);
  216          goto jleave;
  217       }
  218    }
  219 
  220    gss_release_name(&min_stat, &target_name);
  221    f &= ~a_F_TARGET_NAME;
  222 
  223    /* Pass token obtained from second gss_init_sec_context() call */
  224    if(b64_encode_buf(&out, send_tok.value, send_tok.length,
  225          B64_SALLOC | B64_CRLF) == NULL)
  226       goto jleave;
  227    _OUT(out.s);
  228 
  229    gss_release_buffer(&min_stat, &send_tok);
  230    f &= ~a_F_SEND_TOK;
  231 
  232    _ANSWER(3, FAL0, TRU1);
  233    out.s = NULL;
  234    in.s = slp->dat;
  235    in.l = slp->datlen;
  236    if(!b64_decode(&out, &in)){
  237 jebase64:
  238       if(out.s != NULL)
  239          n_free(out.s);
  240       n_err(_("Invalid base64 encoding from GSSAPI server\n"));
  241       goto jleave;
  242    }
  243    recv_tok.value = out.s;
  244    recv_tok.length = out.l;
  245    maj_stat = gss_unwrap(&min_stat, gss_context, &recv_tok, &send_tok,
  246          &conf_state, NULL);
  247    n_free(out.s);
  248    gss_release_buffer(&min_stat, &send_tok);
  249    /*f &= ~a_F_SEND_TOK;*/
  250    if (maj_stat != GSS_S_COMPLETE) {
  251       _smtp_gssapi_error("unwrapping data", maj_stat, min_stat);
  252       goto jleave;
  253    }
  254 
  255    /* First octet: bit-mask with protection mechanisms (1 = no protection
  256     *    mechanism).
  257     * Second to fourth octet: maximum message size in network byte order.
  258     * Fifth and following octets: user name string */
  259    in.s = n_autorec_alloc((send_tok.length = 4 + sbp->sb_ccred.cc_user.l) +1);
  260    memcpy(in.s + 4, sbp->sb_ccred.cc_user.s, sbp->sb_ccred.cc_user.l +1);
  261    in.s[0] = 1;
  262    in.s[1] = 0;
  263    in.s[2] = in.s[3] = (char)0xFF;
  264    send_tok.value = in.s;
  265    maj_stat = gss_wrap(&min_stat, gss_context, 0, GSS_C_QOP_DEFAULT, &send_tok,
  266          &conf_state, &recv_tok);
  267    f |= a_F_RECV_TOK;
  268    if (maj_stat != GSS_S_COMPLETE) {
  269       _smtp_gssapi_error("wrapping data", maj_stat, min_stat);
  270       goto jleave;
  271    }
  272 
  273    if(b64_encode_buf(&out, recv_tok.value, recv_tok.length,
  274          B64_SALLOC | B64_CRLF) == NULL)
  275       goto jleave;
  276    _OUT(out.s);
  277    _ANSWER(2, FAL0, FAL0);
  278 
  279    ok = TRU1;
  280 jleave:
  281    if(f & a_F_RECV_TOK)
  282       gss_release_buffer(&min_stat, &recv_tok);
  283    if(f & a_F_SEND_TOK)
  284       gss_release_buffer(&min_stat, &send_tok);
  285    if(f & a_F_TARGET_NAME)
  286       gss_release_name(&min_stat, &target_name);
  287    if(f & a_F_GSS_CONTEXT)
  288       gss_delete_sec_context(&min_stat, &gss_context, GSS_C_NO_BUFFER);
  289    NYD_LEAVE;
  290    return ok;
  291 }
  292 
  293 # ifdef m_DEFINED_GCC_C_NT_HOSTBASED_SERVICE
  294 #  undef GSS_C_NT_HOSTBASED_SERVICE
  295 # endif
  296 #endif /* HAVE_GSSAPI */
  297 
  298 /* s-it-mode */