The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/rpc/rpcsec_gss/rpcsec_gss_prot.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2   rpcsec_gss_prot.c
    3   
    4   SPDX-License-Identifier: BSD-3-Clause
    5 
    6   Copyright (c) 2000 The Regents of the University of Michigan.
    7   All rights reserved.
    8   
    9   Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
   10   All rights reserved, all wrongs reversed.
   11   
   12   Redistribution and use in source and binary forms, with or without
   13   modification, are permitted provided that the following conditions
   14   are met:
   15 
   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. Neither the name of the University nor the names of its
   22      contributors may be used to endorse or promote products derived
   23      from this software without specific prior written permission.
   24 
   25   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
   26   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   27   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   28   DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   30   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   31   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
   32   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   33   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   34   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   35   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   36 
   37   $Id: authgss_prot.c,v 1.18 2000/09/01 04:14:03 dugsong Exp $
   38 */
   39 
   40 #include <sys/cdefs.h>
   41 __FBSDID("$FreeBSD$");
   42 
   43 #include <sys/param.h>
   44 #include <sys/systm.h>
   45 #include <sys/kobj.h>
   46 #include <sys/lock.h>
   47 #include <sys/malloc.h>
   48 #include <sys/mbuf.h>
   49 #include <sys/mutex.h>
   50 
   51 #include <rpc/rpc.h>
   52 #include <rpc/rpcsec_gss.h>
   53 
   54 #include "rpcsec_gss_int.h"
   55 
   56 #define MAX_GSS_SIZE    10240   /* XXX */
   57 
   58 #if 0                           /* use the one from kgssapi */
   59 bool_t
   60 xdr_gss_buffer_desc(XDR *xdrs, gss_buffer_desc *p)
   61 {
   62         char *val;
   63         u_int len;
   64         bool_t ret;
   65 
   66         val = p->value;
   67         len = p->length;
   68         ret = xdr_bytes(xdrs, &val, &len, MAX_GSS_SIZE);
   69         p->value = val;
   70         p->length = len;
   71 
   72         return (ret);
   73 }
   74 #endif
   75 
   76 bool_t
   77 xdr_rpc_gss_cred(XDR *xdrs, struct rpc_gss_cred *p)
   78 {
   79         enum_t proc, svc;
   80         bool_t ret;
   81 
   82         proc = p->gc_proc;
   83         svc = p->gc_svc;
   84         ret = (xdr_u_int(xdrs, &p->gc_version) &&
   85             xdr_enum(xdrs, &proc) &&
   86             xdr_u_int(xdrs, &p->gc_seq) &&
   87             xdr_enum(xdrs, &svc) &&
   88             xdr_gss_buffer_desc(xdrs, &p->gc_handle));
   89         p->gc_proc = proc;
   90         p->gc_svc = svc;
   91 
   92         return (ret);
   93 }
   94 
   95 bool_t
   96 xdr_rpc_gss_init_res(XDR *xdrs, struct rpc_gss_init_res *p)
   97 {
   98 
   99         return (xdr_gss_buffer_desc(xdrs, &p->gr_handle) &&
  100             xdr_u_int(xdrs, &p->gr_major) &&
  101             xdr_u_int(xdrs, &p->gr_minor) &&
  102             xdr_u_int(xdrs, &p->gr_win) &&
  103             xdr_gss_buffer_desc(xdrs, &p->gr_token));
  104 }
  105 
  106 static void
  107 put_uint32(struct mbuf **mp, uint32_t v)
  108 {
  109         struct mbuf *m = *mp;
  110         uint32_t n;
  111 
  112         M_PREPEND(m, sizeof(uint32_t), M_WAITOK);
  113         n = htonl(v);
  114         bcopy(&n, mtod(m, uint32_t *), sizeof(uint32_t));
  115         *mp = m;
  116 }
  117 
  118 bool_t
  119 xdr_rpc_gss_wrap_data(struct mbuf **argsp,
  120                       gss_ctx_id_t ctx, gss_qop_t qop,
  121                       rpc_gss_service_t svc, u_int seq)
  122 {
  123         struct mbuf     *args, *mic;
  124         OM_uint32       maj_stat, min_stat;
  125         int             conf_state;
  126         u_int           len;
  127         static char     zpad[4];
  128 
  129         args = *argsp;
  130 
  131         /*
  132          * Prepend the sequence number before calling gss_get_mic or gss_wrap.
  133          */
  134         put_uint32(&args, seq);
  135         len = m_length(args, NULL);
  136 
  137         if (svc == rpc_gss_svc_integrity) {
  138                 /* Checksum rpc_gss_data_t. */
  139                 maj_stat = gss_get_mic_mbuf(&min_stat, ctx, qop, args, &mic);
  140                 if (maj_stat != GSS_S_COMPLETE) {
  141                         rpc_gss_log_debug("gss_get_mic failed");
  142                         m_freem(args);
  143                         return (FALSE);
  144                 }
  145 
  146                 /*
  147                  * Marshal databody_integ. Note that since args is
  148                  * already RPC encoded, there will be no padding.
  149                  */
  150                 put_uint32(&args, len);
  151 
  152                 /*
  153                  * Marshal checksum. This is likely to need padding.
  154                  */
  155                 len = m_length(mic, NULL);
  156                 put_uint32(&mic, len);
  157                 if (len != RNDUP(len)) {
  158                         m_append(mic, RNDUP(len) - len, zpad);
  159                 }
  160 
  161                 /*
  162                  * Concatenate databody_integ with checksum.
  163                  */
  164                 m_cat(args, mic);
  165         } else if (svc == rpc_gss_svc_privacy) {
  166                 /* Encrypt rpc_gss_data_t. */
  167                 maj_stat = gss_wrap_mbuf(&min_stat, ctx, TRUE, qop,
  168                     &args, &conf_state);
  169                 if (maj_stat != GSS_S_COMPLETE) {
  170                         rpc_gss_log_status("gss_wrap", NULL,
  171                             maj_stat, min_stat);
  172                         return (FALSE);
  173                 }
  174 
  175                 /*
  176                  *  Marshal databody_priv and deal with RPC padding.
  177                  */
  178                 len = m_length(args, NULL);
  179                 put_uint32(&args, len);
  180                 if (len != RNDUP(len)) {
  181                         m_append(args, RNDUP(len) - len, zpad);
  182                 }
  183         }
  184         *argsp = args;
  185         return (TRUE);
  186 }
  187 
  188 static uint32_t
  189 get_uint32(struct mbuf **mp)
  190 {
  191         struct mbuf *m = *mp;
  192         uint32_t n;
  193 
  194         if (m->m_len < sizeof(uint32_t)) {
  195                 m = m_pullup(m, sizeof(uint32_t));
  196                 if (!m) {
  197                         *mp = NULL;
  198                         return (0);
  199                 }
  200         }
  201         bcopy(mtod(m, uint32_t *), &n, sizeof(uint32_t));
  202         m_adj(m, sizeof(uint32_t));
  203         *mp = m;
  204         return (ntohl(n));
  205 }
  206 
  207 static void
  208 m_trim(struct mbuf *m, int len)
  209 {
  210         struct mbuf *n;
  211         int off;
  212 
  213         if (m == NULL)
  214                 return;
  215         n = m_getptr(m, len, &off);
  216         if (n) {
  217                 n->m_len = off;
  218                 if (n->m_next) {
  219                         m_freem(n->m_next);
  220                         n->m_next = NULL;
  221                 }
  222         }
  223 }
  224 
  225 bool_t
  226 xdr_rpc_gss_unwrap_data(struct mbuf **resultsp,
  227                         gss_ctx_id_t ctx, gss_qop_t qop,
  228                         rpc_gss_service_t svc, u_int seq)
  229 {
  230         struct mbuf     *results, *message, *mic;
  231         uint32_t        len, cklen;
  232         OM_uint32       maj_stat, min_stat;
  233         u_int           seq_num, conf_state, qop_state;
  234 
  235         results = *resultsp;
  236         *resultsp = NULL;
  237         
  238         message = NULL;
  239         if (svc == rpc_gss_svc_integrity) {
  240                 /*
  241                  * Extract the seq+message part. Remember that there
  242                  * may be extra RPC padding in the checksum. The
  243                  * message part is RPC encoded already so no
  244                  * padding.
  245                  */
  246                 len = get_uint32(&results);
  247                 message = results;
  248                 results = m_split(results, len, M_WAITOK);
  249                 if (!results) {
  250                         m_freem(message);
  251                         return (FALSE);
  252                 }
  253 
  254                 /*
  255                  * Extract the MIC and make it contiguous.
  256                  */
  257                 cklen = get_uint32(&results);
  258                 if (!results) {
  259                         m_freem(message);
  260                         return (FALSE);
  261                 }
  262                 KASSERT(cklen <= MHLEN, ("unexpected large GSS-API checksum"));
  263                 mic = results;
  264                 if (cklen > mic->m_len) {
  265                         mic = m_pullup(mic, cklen);
  266                         if (!mic) {
  267                                 m_freem(message);
  268                                 return (FALSE);
  269                         }
  270                 }
  271                 if (cklen != RNDUP(cklen))
  272                         m_trim(mic, cklen);
  273 
  274                 /* Verify checksum and QOP. */
  275                 maj_stat = gss_verify_mic_mbuf(&min_stat, ctx,
  276                     message, mic, &qop_state);
  277                 m_freem(mic);
  278                 
  279                 if (maj_stat != GSS_S_COMPLETE || qop_state != qop) {
  280                         m_freem(message);
  281                         rpc_gss_log_status("gss_verify_mic", NULL,
  282                             maj_stat, min_stat);
  283                         return (FALSE);
  284                 }
  285         } else if (svc == rpc_gss_svc_privacy) {
  286                 /* Decode databody_priv. */
  287                 len = get_uint32(&results);
  288                 if (!results)
  289                         return (FALSE);
  290 
  291                 /* Decrypt databody. */
  292                 message = results;
  293                 if (len != RNDUP(len))
  294                         m_trim(message, len);
  295                 maj_stat = gss_unwrap_mbuf(&min_stat, ctx, &message,
  296                     &conf_state, &qop_state);
  297                 
  298                 /* Verify encryption and QOP. */
  299                 if (maj_stat != GSS_S_COMPLETE) {
  300                         rpc_gss_log_status("gss_unwrap", NULL,
  301                             maj_stat, min_stat);
  302                         return (FALSE);
  303                 }
  304                 if (qop_state != qop || conf_state != TRUE) {
  305                         m_freem(results);
  306                         return (FALSE);
  307                 }
  308         }
  309 
  310         /* Decode rpc_gss_data_t (sequence number + arguments). */
  311         seq_num = get_uint32(&message);
  312         if (!message)
  313                 return (FALSE);
  314         
  315         /* Verify sequence number. */
  316         if (seq_num != seq) {
  317                 rpc_gss_log_debug("wrong sequence number in databody");
  318                 m_freem(message);
  319                 return (FALSE);
  320         }
  321 
  322         *resultsp = message;
  323         return (TRUE);
  324 }
  325 
  326 #ifdef DEBUG
  327 #include <machine/stdarg.h>
  328 
  329 void
  330 rpc_gss_log_debug(const char *fmt, ...)
  331 {
  332         va_list ap;
  333 
  334         va_start(ap, fmt);
  335         printf("rpcsec_gss: ");
  336         vprintf(fmt, ap);
  337         printf("\n");
  338         va_end(ap);
  339 }
  340 
  341 void
  342 rpc_gss_log_status(const char *m, gss_OID mech, OM_uint32 maj_stat, OM_uint32 min_stat)
  343 {
  344         OM_uint32 min;
  345         gss_buffer_desc msg;
  346         int msg_ctx = 0;
  347 
  348         printf("rpcsec_gss: %s: ", m);
  349         
  350         gss_display_status(&min, maj_stat, GSS_C_GSS_CODE, GSS_C_NULL_OID,
  351                            &msg_ctx, &msg);
  352         printf("%s - ", (char *)msg.value);
  353         gss_release_buffer(&min, &msg);
  354 
  355         gss_display_status(&min, min_stat, GSS_C_MECH_CODE, mech,
  356                            &msg_ctx, &msg);
  357         printf("%s\n", (char *)msg.value);
  358         gss_release_buffer(&min, &msg);
  359 }
  360 
  361 #else
  362 
  363 void
  364 rpc_gss_log_debug(__unused const char *fmt, ...)
  365 {
  366 }
  367 
  368 void
  369 rpc_gss_log_status(__unused const char *m, __unused gss_OID mech,
  370     __unused OM_uint32 maj_stat, __unused OM_uint32 min_stat)
  371 {
  372 }
  373 
  374 #endif
  375 
  376 

Cache object: 432ce82eb6e4131f385c553907137546


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.