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

Cache object: 8170074d5434e162eaeb2a5df8baad15


[ 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.