"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.7/smtp-gssapi.h" (16 Feb 2018, 9931 Bytes) of package /linux/misc/s-nail-14.9.7.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.6_vs_14.9.7.

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