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: releng/10.2/sys/rpc/rpcsec_gss/rpcsec_gss_prot.c 249096 2013-04-04 15:16:53Z gnn $");
   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_WAITOK);
  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         if (m == NULL)
  212                 return;
  213         n = m_getptr(m, len, &off);
  214         if (n) {
  215                 n->m_len = off;
  216                 if (n->m_next) {
  217                         m_freem(n->m_next);
  218                         n->m_next = NULL;
  219                 }
  220         }
  221 }
  222 
  223 bool_t
  224 xdr_rpc_gss_unwrap_data(struct mbuf **resultsp,
  225                         gss_ctx_id_t ctx, gss_qop_t qop,
  226                         rpc_gss_service_t svc, u_int seq)
  227 {
  228         struct mbuf     *results, *message, *mic;
  229         uint32_t        len, cklen;
  230         OM_uint32       maj_stat, min_stat;
  231         u_int           seq_num, conf_state, qop_state;
  232 
  233         results = *resultsp;
  234         *resultsp = NULL;
  235         
  236         message = NULL;
  237         if (svc == rpc_gss_svc_integrity) {
  238                 /*
  239                  * Extract the seq+message part. Remember that there
  240                  * may be extra RPC padding in the checksum. The
  241                  * message part is RPC encoded already so no
  242                  * padding.
  243                  */
  244                 len = get_uint32(&results);
  245                 message = results;
  246                 results = m_split(results, len, M_WAITOK);
  247                 if (!results) {
  248                         m_freem(message);
  249                         return (FALSE);
  250                 }
  251 
  252                 /*
  253                  * Extract the MIC and make it contiguous.
  254                  */
  255                 cklen = get_uint32(&results);
  256                 if (!results) {
  257                         m_freem(message);
  258                         return (FALSE);
  259                 }
  260                 KASSERT(cklen <= MHLEN, ("unexpected large GSS-API checksum"));
  261                 mic = results;
  262                 if (cklen > mic->m_len) {
  263                         mic = m_pullup(mic, cklen);
  264                         if (!mic) {
  265                                 m_freem(message);
  266                                 return (FALSE);
  267                         }
  268                 }
  269                 if (cklen != RNDUP(cklen))
  270                         m_trim(mic, cklen);
  271 
  272                 /* Verify checksum and QOP. */
  273                 maj_stat = gss_verify_mic_mbuf(&min_stat, ctx,
  274                     message, mic, &qop_state);
  275                 m_freem(mic);
  276                 
  277                 if (maj_stat != GSS_S_COMPLETE || qop_state != qop) {
  278                         m_freem(message);
  279                         rpc_gss_log_status("gss_verify_mic", NULL,
  280                             maj_stat, min_stat);
  281                         return (FALSE);
  282                 }
  283         } else if (svc == rpc_gss_svc_privacy) {
  284                 /* Decode databody_priv. */
  285                 len = get_uint32(&results);
  286                 if (!results)
  287                         return (FALSE);
  288 
  289                 /* Decrypt databody. */
  290                 message = results;
  291                 if (len != RNDUP(len))
  292                         m_trim(message, len);
  293                 maj_stat = gss_unwrap_mbuf(&min_stat, ctx, &message,
  294                     &conf_state, &qop_state);
  295                 
  296                 /* Verify encryption and QOP. */
  297                 if (maj_stat != GSS_S_COMPLETE) {
  298                         rpc_gss_log_status("gss_unwrap", NULL,
  299                             maj_stat, min_stat);
  300                         return (FALSE);
  301                 }
  302                 if (qop_state != qop || conf_state != TRUE) {
  303                         m_freem(results);
  304                         return (FALSE);
  305                 }
  306         }
  307 
  308         /* Decode rpc_gss_data_t (sequence number + arguments). */
  309         seq_num = get_uint32(&message);
  310         if (!message)
  311                 return (FALSE);
  312         
  313         /* Verify sequence number. */
  314         if (seq_num != seq) {
  315                 rpc_gss_log_debug("wrong sequence number in databody");
  316                 m_freem(message);
  317                 return (FALSE);
  318         }
  319 
  320         *resultsp = message;
  321         return (TRUE);
  322 }
  323 
  324 #ifdef DEBUG
  325 #include <machine/stdarg.h>
  326 
  327 void
  328 rpc_gss_log_debug(const char *fmt, ...)
  329 {
  330         va_list ap;
  331 
  332         va_start(ap, fmt);
  333         printf("rpcsec_gss: ");
  334         vprintf(fmt, ap);
  335         printf("\n");
  336         va_end(ap);
  337 }
  338 
  339 void
  340 rpc_gss_log_status(const char *m, gss_OID mech, OM_uint32 maj_stat, OM_uint32 min_stat)
  341 {
  342         OM_uint32 min;
  343         gss_buffer_desc msg;
  344         int msg_ctx = 0;
  345 
  346         printf("rpcsec_gss: %s: ", m);
  347         
  348         gss_display_status(&min, maj_stat, GSS_C_GSS_CODE, GSS_C_NULL_OID,
  349                            &msg_ctx, &msg);
  350         printf("%s - ", (char *)msg.value);
  351         gss_release_buffer(&min, &msg);
  352 
  353         gss_display_status(&min, min_stat, GSS_C_MECH_CODE, mech,
  354                            &msg_ctx, &msg);
  355         printf("%s\n", (char *)msg.value);
  356         gss_release_buffer(&min, &msg);
  357 }
  358 
  359 #else
  360 
  361 void
  362 rpc_gss_log_debug(__unused const char *fmt, ...)
  363 {
  364 }
  365 
  366 void
  367 rpc_gss_log_status(__unused const char *m, __unused gss_OID mech,
  368     __unused OM_uint32 maj_stat, __unused OM_uint32 min_stat)
  369 {
  370 }
  371 
  372 #endif
  373 
  374 

Cache object: edc8171d0844c8fedc7debe093561f65


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