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/kgssapi/krb5/krb5_mech.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
    5  * Authors: Doug Rabson <dfr@rabson.org>
    6  * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include "opt_inet6.h"
   34 
   35 #include <sys/param.h>
   36 #include <sys/kernel.h>
   37 #include <sys/kobj.h>
   38 #include <sys/lock.h>
   39 #include <sys/malloc.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/module.h>
   42 #include <sys/mutex.h>
   43 #include <kgssapi/gssapi.h>
   44 #include <kgssapi/gssapi_impl.h>
   45 
   46 #include "kgss_if.h"
   47 #include "kcrypto.h"
   48 
   49 #define GSS_TOKEN_SENT_BY_ACCEPTOR      1
   50 #define GSS_TOKEN_SEALED                2
   51 #define GSS_TOKEN_ACCEPTOR_SUBKEY       4
   52 
   53 static gss_OID_desc krb5_mech_oid =
   54 {9, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" };
   55 
   56 struct krb5_data {
   57         size_t          kd_length;
   58         void            *kd_data;
   59 };
   60 
   61 struct krb5_keyblock {
   62         uint16_t        kk_type; /* encryption type */
   63         struct krb5_data kk_key; /* key data */
   64 };
   65 
   66 struct krb5_address {
   67         uint16_t        ka_type;
   68         struct krb5_data ka_addr;
   69 };
   70 
   71 /*
   72  * The km_elem array is ordered so that the highest received sequence
   73  * number is listed first.
   74  */
   75 struct krb5_msg_order {
   76         uint32_t                km_flags;
   77         uint32_t                km_start;
   78         uint32_t                km_length;
   79         uint32_t                km_jitter_window;
   80         uint32_t                km_first_seq;
   81         uint32_t                *km_elem;
   82 };
   83 
   84 struct krb5_context {
   85         struct _gss_ctx_id_t    kc_common;
   86         struct mtx              kc_lock;
   87         uint32_t                kc_ac_flags;
   88         uint32_t                kc_ctx_flags;
   89         uint32_t                kc_more_flags;
   90 #define LOCAL                   1
   91 #define OPEN                    2
   92 #define COMPAT_OLD_DES3         4
   93 #define COMPAT_OLD_DES3_SELECTED 8
   94 #define ACCEPTOR_SUBKEY         16
   95         struct krb5_address     kc_local_address;
   96         struct krb5_address     kc_remote_address;
   97         uint16_t                kc_local_port;
   98         uint16_t                kc_remote_port;
   99         struct krb5_keyblock    kc_keyblock;
  100         struct krb5_keyblock    kc_local_subkey;
  101         struct krb5_keyblock    kc_remote_subkey;
  102         volatile uint32_t       kc_local_seqnumber;
  103         uint32_t                kc_remote_seqnumber;
  104         uint32_t                kc_keytype;
  105         uint32_t                kc_cksumtype;
  106         struct krb5_data        kc_source_name;
  107         struct krb5_data        kc_target_name;
  108         uint32_t                kc_lifetime;
  109         struct krb5_msg_order   kc_msg_order;
  110         struct krb5_key_state   *kc_tokenkey;
  111         struct krb5_key_state   *kc_encryptkey;
  112         struct krb5_key_state   *kc_checksumkey;
  113 
  114         struct krb5_key_state   *kc_send_seal_Ke;
  115         struct krb5_key_state   *kc_send_seal_Ki;
  116         struct krb5_key_state   *kc_send_seal_Kc;
  117         struct krb5_key_state   *kc_send_sign_Kc;
  118 
  119         struct krb5_key_state   *kc_recv_seal_Ke;
  120         struct krb5_key_state   *kc_recv_seal_Ki;
  121         struct krb5_key_state   *kc_recv_seal_Kc;
  122         struct krb5_key_state   *kc_recv_sign_Kc;
  123 };
  124 
  125 static uint16_t
  126 get_uint16(const uint8_t **pp, size_t *lenp)
  127 {
  128         const uint8_t *p = *pp;
  129         uint16_t v;
  130 
  131         if (*lenp < 2)
  132                 return (0);
  133 
  134         v = (p[0] << 8) | p[1];
  135         *pp = p + 2;
  136         *lenp = *lenp - 2;
  137 
  138         return (v);
  139 }
  140 
  141 static uint32_t
  142 get_uint32(const uint8_t **pp, size_t *lenp)
  143 {
  144         const uint8_t *p = *pp;
  145         uint32_t v;
  146 
  147         if (*lenp < 4)
  148                 return (0);
  149 
  150         v = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
  151         *pp = p + 4;
  152         *lenp = *lenp - 4;
  153 
  154         return (v);
  155 }
  156 
  157 static void
  158 get_data(const uint8_t **pp, size_t *lenp, struct krb5_data *dp)
  159 {
  160         size_t sz = get_uint32(pp, lenp);
  161 
  162         dp->kd_length = sz;
  163         dp->kd_data = malloc(sz, M_GSSAPI, M_WAITOK);
  164 
  165         if (*lenp < sz)
  166                 sz = *lenp;
  167         bcopy(*pp, dp->kd_data, sz);
  168         (*pp) += sz;
  169         (*lenp) -= sz;
  170 }
  171 
  172 static void
  173 delete_data(struct krb5_data *dp)
  174 {
  175         if (dp->kd_data) {
  176                 free(dp->kd_data, M_GSSAPI);
  177                 dp->kd_length = 0;
  178                 dp->kd_data = NULL;
  179         }
  180 }
  181 
  182 static void
  183 get_address(const uint8_t **pp, size_t *lenp, struct krb5_address *ka)
  184 {
  185 
  186         ka->ka_type = get_uint16(pp, lenp);
  187         get_data(pp, lenp, &ka->ka_addr);
  188 }
  189 
  190 static void
  191 delete_address(struct krb5_address *ka)
  192 {
  193         delete_data(&ka->ka_addr);
  194 }
  195 
  196 static void
  197 get_keyblock(const uint8_t **pp, size_t *lenp, struct krb5_keyblock *kk)
  198 {
  199 
  200         kk->kk_type = get_uint16(pp, lenp);
  201         get_data(pp, lenp, &kk->kk_key);
  202 }
  203 
  204 static void
  205 delete_keyblock(struct krb5_keyblock *kk)
  206 {
  207         if (kk->kk_key.kd_data)
  208                 bzero(kk->kk_key.kd_data, kk->kk_key.kd_length);
  209         delete_data(&kk->kk_key);
  210 }
  211 
  212 static void
  213 copy_key(struct krb5_keyblock *from, struct krb5_keyblock **to)
  214 {
  215 
  216         if (from->kk_key.kd_length)
  217                 *to = from;
  218         else
  219                 *to = NULL;
  220 }
  221 
  222 /*
  223  * Return non-zero if we are initiator.
  224  */
  225 static __inline int
  226 is_initiator(struct krb5_context *kc)
  227 {
  228         return (kc->kc_more_flags & LOCAL);
  229 }
  230 
  231 /*
  232  * Return non-zero if we are acceptor.
  233  */
  234 static __inline int
  235 is_acceptor(struct krb5_context *kc)
  236 {
  237         return !(kc->kc_more_flags & LOCAL);
  238 }
  239 
  240 static void
  241 get_initiator_subkey(struct krb5_context *kc, struct krb5_keyblock **kdp)
  242 {
  243 
  244         if (is_initiator(kc))
  245                 copy_key(&kc->kc_local_subkey, kdp);
  246         else
  247                 copy_key(&kc->kc_remote_subkey, kdp);
  248         if (!*kdp)
  249                 copy_key(&kc->kc_keyblock, kdp);
  250 }
  251 
  252 static void
  253 get_acceptor_subkey(struct krb5_context *kc, struct krb5_keyblock **kdp)
  254 {
  255 
  256         if (is_initiator(kc))
  257                 copy_key(&kc->kc_remote_subkey, kdp);
  258         else
  259                 copy_key(&kc->kc_local_subkey, kdp);
  260 }
  261 
  262 static OM_uint32
  263 get_keys(struct krb5_context *kc)
  264 {
  265         struct krb5_keyblock *keydata;
  266         struct krb5_encryption_class *ec;
  267         struct krb5_key_state *key;
  268         int etype;
  269 
  270         keydata = NULL;
  271         get_acceptor_subkey(kc, &keydata);
  272         if (!keydata)
  273                 if ((kc->kc_more_flags & ACCEPTOR_SUBKEY) == 0)
  274                         get_initiator_subkey(kc, &keydata);
  275         if (!keydata)
  276                 return (GSS_S_FAILURE);
  277 
  278         /*
  279          * GSS-API treats all DES etypes the same and all DES3 etypes
  280          * the same.
  281          */
  282         switch (keydata->kk_type) {
  283         case ETYPE_DES_CBC_CRC:
  284         case ETYPE_DES_CBC_MD4:
  285         case ETYPE_DES_CBC_MD5:
  286                 etype = ETYPE_DES_CBC_CRC;
  287                 break;
  288 
  289         case ETYPE_DES3_CBC_MD5:
  290         case ETYPE_DES3_CBC_SHA1:
  291         case ETYPE_OLD_DES3_CBC_SHA1:
  292                 etype = ETYPE_DES3_CBC_SHA1;
  293                 break;
  294 
  295         default:
  296                 etype = keydata->kk_type;
  297         }
  298 
  299         ec = krb5_find_encryption_class(etype);
  300         if (!ec)
  301                 return (GSS_S_FAILURE);
  302 
  303         key = krb5_create_key(ec);
  304         krb5_set_key(key, keydata->kk_key.kd_data);
  305         kc->kc_tokenkey = key;
  306 
  307         switch (etype) {
  308         case ETYPE_DES_CBC_CRC:
  309         case ETYPE_ARCFOUR_HMAC_MD5: 
  310         case ETYPE_ARCFOUR_HMAC_MD5_56: {
  311                 /*
  312                  * Single DES and ARCFOUR uses a 'derived' key (XOR
  313                  * with 0xf0) for encrypting wrap tokens. The original
  314                  * key is used for checksums and sequence numbers.
  315                  */
  316                 struct krb5_key_state *ekey;
  317                 uint8_t *ekp, *kp;
  318                 int i;
  319 
  320                 ekey = krb5_create_key(ec);
  321                 ekp = ekey->ks_key;
  322                 kp = key->ks_key;
  323                 for (i = 0; i < ec->ec_keylen; i++)
  324                         ekp[i] = kp[i] ^ 0xf0;
  325                 krb5_set_key(ekey, ekp);
  326                 kc->kc_encryptkey = ekey;
  327                 refcount_acquire(&key->ks_refs);
  328                 kc->kc_checksumkey = key;
  329                 break;
  330         }
  331 
  332         case ETYPE_DES3_CBC_SHA1:
  333                 /*
  334                  * Triple DES uses a RFC 3961 style derived key with
  335                  * usage number KG_USAGE_SIGN for checksums. The
  336                  * original key is used for encryption and sequence
  337                  * numbers.
  338                  */
  339                 kc->kc_checksumkey = krb5_get_checksum_key(key, KG_USAGE_SIGN);
  340                 refcount_acquire(&key->ks_refs);
  341                 kc->kc_encryptkey = key;
  342                 break;
  343 
  344         default:
  345                 /*
  346                  * We need eight derived keys four for sending and
  347                  * four for receiving.
  348                  */
  349                 if (is_initiator(kc)) {
  350                         /*
  351                          * We are initiator.
  352                          */
  353                         kc->kc_send_seal_Ke = krb5_get_encryption_key(key,
  354                             KG_USAGE_INITIATOR_SEAL);
  355                         kc->kc_send_seal_Ki = krb5_get_integrity_key(key,
  356                             KG_USAGE_INITIATOR_SEAL);
  357                         kc->kc_send_seal_Kc = krb5_get_checksum_key(key,
  358                             KG_USAGE_INITIATOR_SEAL);
  359                         kc->kc_send_sign_Kc = krb5_get_checksum_key(key,
  360                             KG_USAGE_INITIATOR_SIGN);
  361 
  362                         kc->kc_recv_seal_Ke = krb5_get_encryption_key(key,
  363                             KG_USAGE_ACCEPTOR_SEAL);
  364                         kc->kc_recv_seal_Ki = krb5_get_integrity_key(key,
  365                             KG_USAGE_ACCEPTOR_SEAL);
  366                         kc->kc_recv_seal_Kc = krb5_get_checksum_key(key,
  367                             KG_USAGE_ACCEPTOR_SEAL);
  368                         kc->kc_recv_sign_Kc = krb5_get_checksum_key(key,
  369                             KG_USAGE_ACCEPTOR_SIGN);
  370                 } else {
  371                         /*
  372                          * We are acceptor.
  373                          */
  374                         kc->kc_send_seal_Ke = krb5_get_encryption_key(key,
  375                             KG_USAGE_ACCEPTOR_SEAL);
  376                         kc->kc_send_seal_Ki = krb5_get_integrity_key(key,
  377                             KG_USAGE_ACCEPTOR_SEAL);
  378                         kc->kc_send_seal_Kc = krb5_get_checksum_key(key,
  379                             KG_USAGE_ACCEPTOR_SEAL);
  380                         kc->kc_send_sign_Kc = krb5_get_checksum_key(key,
  381                             KG_USAGE_ACCEPTOR_SIGN);
  382 
  383                         kc->kc_recv_seal_Ke = krb5_get_encryption_key(key,
  384                             KG_USAGE_INITIATOR_SEAL);
  385                         kc->kc_recv_seal_Ki = krb5_get_integrity_key(key,
  386                             KG_USAGE_INITIATOR_SEAL);
  387                         kc->kc_recv_seal_Kc = krb5_get_checksum_key(key,
  388                             KG_USAGE_INITIATOR_SEAL);
  389                         kc->kc_recv_sign_Kc = krb5_get_checksum_key(key,
  390                             KG_USAGE_INITIATOR_SIGN);
  391                 }
  392                 break;
  393         }
  394 
  395         return (GSS_S_COMPLETE);
  396 }
  397 
  398 static void
  399 krb5_init(gss_ctx_id_t ctx)
  400 {
  401         struct krb5_context *kc = (struct krb5_context *)ctx;
  402 
  403         mtx_init(&kc->kc_lock, "krb5 gss lock", NULL, MTX_DEF);
  404 }
  405 
  406 static OM_uint32
  407 krb5_import(gss_ctx_id_t ctx,
  408     enum sec_context_format format,
  409     const gss_buffer_t context_token)
  410 {
  411         struct krb5_context *kc = (struct krb5_context *)ctx;
  412         OM_uint32 res;
  413         const uint8_t *p = (const uint8_t *) context_token->value;
  414         size_t len = context_token->length;
  415         uint32_t flags;
  416         int i;
  417 
  418         /*
  419          * We support heimdal 0.6 and heimdal 1.1
  420          */
  421         if (format != KGSS_HEIMDAL_0_6 && format != KGSS_HEIMDAL_1_1)
  422                 return (GSS_S_DEFECTIVE_TOKEN);
  423 
  424 #define SC_LOCAL_ADDRESS        1
  425 #define SC_REMOTE_ADDRESS       2
  426 #define SC_KEYBLOCK             4
  427 #define SC_LOCAL_SUBKEY         8
  428 #define SC_REMOTE_SUBKEY        16
  429 
  430         /*
  431          * Ensure that the token starts with krb5 oid.
  432          */
  433         if (p[0] != 0x00 || p[1] != krb5_mech_oid.length
  434             || len < krb5_mech_oid.length + 2
  435             || bcmp(krb5_mech_oid.elements, p + 2,
  436                 krb5_mech_oid.length))
  437                 return (GSS_S_DEFECTIVE_TOKEN);
  438         p += krb5_mech_oid.length + 2;
  439         len -= krb5_mech_oid.length + 2;
  440 
  441         flags = get_uint32(&p, &len);
  442         kc->kc_ac_flags = get_uint32(&p, &len);
  443         if (flags & SC_LOCAL_ADDRESS)
  444                 get_address(&p, &len, &kc->kc_local_address);
  445         if (flags & SC_REMOTE_ADDRESS)
  446                 get_address(&p, &len, &kc->kc_remote_address);
  447         kc->kc_local_port = get_uint16(&p, &len);
  448         kc->kc_remote_port = get_uint16(&p, &len);
  449         if (flags & SC_KEYBLOCK)
  450                 get_keyblock(&p, &len, &kc->kc_keyblock);
  451         if (flags & SC_LOCAL_SUBKEY)
  452                 get_keyblock(&p, &len, &kc->kc_local_subkey);
  453         if (flags & SC_REMOTE_SUBKEY)
  454                 get_keyblock(&p, &len, &kc->kc_remote_subkey);
  455         kc->kc_local_seqnumber = get_uint32(&p, &len);
  456         kc->kc_remote_seqnumber = get_uint32(&p, &len);
  457         kc->kc_keytype = get_uint32(&p, &len);
  458         kc->kc_cksumtype = get_uint32(&p, &len);
  459         get_data(&p, &len, &kc->kc_source_name);
  460         get_data(&p, &len, &kc->kc_target_name);
  461         kc->kc_ctx_flags = get_uint32(&p, &len);
  462         kc->kc_more_flags = get_uint32(&p, &len);
  463         kc->kc_lifetime = get_uint32(&p, &len);
  464         /*
  465          * Heimdal 1.1 adds the message order stuff.
  466          */
  467         if (format == KGSS_HEIMDAL_1_1) {
  468                 kc->kc_msg_order.km_flags = get_uint32(&p, &len);
  469                 kc->kc_msg_order.km_start = get_uint32(&p, &len);
  470                 kc->kc_msg_order.km_length = get_uint32(&p, &len);
  471                 kc->kc_msg_order.km_jitter_window = get_uint32(&p, &len);
  472                 kc->kc_msg_order.km_first_seq = get_uint32(&p, &len);
  473                 kc->kc_msg_order.km_elem =
  474                         malloc(kc->kc_msg_order.km_jitter_window * sizeof(uint32_t),
  475                             M_GSSAPI, M_WAITOK);
  476                 for (i = 0; i < kc->kc_msg_order.km_jitter_window; i++)
  477                         kc->kc_msg_order.km_elem[i] = get_uint32(&p, &len);
  478         } else {
  479                 kc->kc_msg_order.km_flags = 0;
  480         }
  481 
  482         res = get_keys(kc);
  483         if (GSS_ERROR(res))
  484                 return (res);
  485 
  486         /*
  487          * We don't need these anymore.
  488          */
  489         delete_keyblock(&kc->kc_keyblock);
  490         delete_keyblock(&kc->kc_local_subkey);
  491         delete_keyblock(&kc->kc_remote_subkey);
  492 
  493         return (GSS_S_COMPLETE);
  494 }
  495 
  496 static void
  497 krb5_delete(gss_ctx_id_t ctx, gss_buffer_t output_token)
  498 {
  499         struct krb5_context *kc = (struct krb5_context *)ctx;
  500 
  501         delete_address(&kc->kc_local_address);
  502         delete_address(&kc->kc_remote_address);
  503         delete_keyblock(&kc->kc_keyblock);
  504         delete_keyblock(&kc->kc_local_subkey);
  505         delete_keyblock(&kc->kc_remote_subkey);
  506         delete_data(&kc->kc_source_name);
  507         delete_data(&kc->kc_target_name);
  508         if (kc->kc_msg_order.km_elem)
  509                 free(kc->kc_msg_order.km_elem, M_GSSAPI);
  510         if (output_token) {
  511                 output_token->length = 0;
  512                 output_token->value = NULL;
  513         }
  514         if (kc->kc_tokenkey) {
  515                 krb5_free_key(kc->kc_tokenkey);
  516                 if (kc->kc_encryptkey) {
  517                         krb5_free_key(kc->kc_encryptkey);
  518                         krb5_free_key(kc->kc_checksumkey);
  519                 } else {
  520                         krb5_free_key(kc->kc_send_seal_Ke);
  521                         krb5_free_key(kc->kc_send_seal_Ki);
  522                         krb5_free_key(kc->kc_send_seal_Kc);
  523                         krb5_free_key(kc->kc_send_sign_Kc);
  524                         krb5_free_key(kc->kc_recv_seal_Ke);
  525                         krb5_free_key(kc->kc_recv_seal_Ki);
  526                         krb5_free_key(kc->kc_recv_seal_Kc);
  527                         krb5_free_key(kc->kc_recv_sign_Kc);
  528                 }
  529         }
  530         mtx_destroy(&kc->kc_lock);
  531 }
  532 
  533 static gss_OID
  534 krb5_mech_type(gss_ctx_id_t ctx)
  535 {
  536 
  537         return (&krb5_mech_oid);
  538 }
  539 
  540 /*
  541  * Make a token with the given type and length (the length includes
  542  * the TOK_ID), initialising the token header appropriately. Return a
  543  * pointer to the TOK_ID of the token.  A new mbuf is allocated with
  544  * the framing header plus hlen bytes of space.
  545  *
  546  * Format is as follows:
  547  *
  548  *      0x60                    [APPLICATION 0] SEQUENCE
  549  *      DER encoded length      length of oid + type + inner token length
  550  *      0x06 NN <oid data>      OID of mechanism type
  551  *      TT TT                   TOK_ID
  552  *      <inner token>           data for inner token
  553  *      
  554  * 1:           der encoded length
  555  */
  556 static void *
  557 krb5_make_token(char tok_id[2], size_t hlen, size_t len, struct mbuf **mp)
  558 {
  559         size_t inside_len, len_len, tlen;
  560         gss_OID oid = &krb5_mech_oid;
  561         struct mbuf *m;
  562         uint8_t *p;
  563 
  564         inside_len = 2 + oid->length + len;
  565         if (inside_len < 128)
  566                 len_len = 1;
  567         else if (inside_len < 0x100)
  568                 len_len = 2;
  569         else if (inside_len < 0x10000)
  570                 len_len = 3;
  571         else if (inside_len < 0x1000000)
  572                 len_len = 4;
  573         else
  574                 len_len = 5;
  575 
  576         tlen = 1 + len_len + 2 + oid->length + hlen;
  577         KASSERT(tlen <= MLEN, ("token head too large"));
  578         MGET(m, M_WAITOK, MT_DATA);
  579         M_ALIGN(m, tlen);
  580         m->m_len = tlen;
  581 
  582         p = (uint8_t *) m->m_data;
  583         *p++ = 0x60;
  584         switch (len_len) {
  585         case 1:
  586                 *p++ = inside_len;
  587                 break;
  588         case 2:
  589                 *p++ = 0x81;
  590                 *p++ = inside_len;
  591                 break;
  592         case 3:
  593                 *p++ = 0x82;
  594                 *p++ = inside_len >> 8;
  595                 *p++ = inside_len;
  596                 break;
  597         case 4:
  598                 *p++ = 0x83;
  599                 *p++ = inside_len >> 16;
  600                 *p++ = inside_len >> 8;
  601                 *p++ = inside_len;
  602                 break;
  603         case 5:
  604                 *p++ = 0x84;
  605                 *p++ = inside_len >> 24;
  606                 *p++ = inside_len >> 16;
  607                 *p++ = inside_len >> 8;
  608                 *p++ = inside_len;
  609                 break;
  610         }
  611 
  612         *p++ = 0x06;
  613         *p++ = oid->length;
  614         bcopy(oid->elements, p, oid->length);
  615         p += oid->length;
  616 
  617         p[0] = tok_id[0];
  618         p[1] = tok_id[1];
  619 
  620         *mp = m;
  621 
  622         return (p);
  623 }
  624 
  625 /*
  626  * Verify a token, checking the inner token length and mechanism oid.
  627  * pointer to the first byte of the TOK_ID. The length of the
  628  * encapsulated data is checked to be at least len bytes; the actual
  629  * length of the encapsulated data (including TOK_ID) is returned in
  630  * *encap_len.
  631  *
  632  * If can_pullup is TRUE and the token header is fragmented, we will
  633  * rearrange it.
  634  *
  635  * Format is as follows:
  636  *
  637  *      0x60                    [APPLICATION 0] SEQUENCE
  638  *      DER encoded length      length of oid + type + inner token length
  639  *      0x06 NN <oid data>      OID of mechanism type
  640  *      TT TT                   TOK_ID
  641  *      <inner token>           data for inner token
  642  *      
  643  * 1:           der encoded length
  644  */
  645 static void *
  646 krb5_verify_token(char tok_id[2], size_t len, struct mbuf **mp,
  647     size_t *encap_len, bool_t can_pullup)
  648 {
  649         struct mbuf *m;
  650         size_t tlen, hlen, len_len, inside_len;
  651         gss_OID oid = &krb5_mech_oid;
  652         uint8_t *p;
  653 
  654         m = *mp;
  655         tlen = m_length(m, NULL);
  656         if (tlen < 2)
  657                 return (NULL);
  658 
  659         /*
  660          * Ensure that at least the framing part of the token is
  661          * contigous.
  662          */
  663         if (m->m_len < 2) {
  664                 if (can_pullup)
  665                         *mp = m = m_pullup(m, 2);
  666                 else
  667                         return (NULL);
  668         }
  669 
  670         p = m->m_data;
  671 
  672         if (*p++ != 0x60)
  673                 return (NULL);
  674 
  675         if (*p < 0x80) {
  676                 inside_len = *p++;
  677                 len_len = 1;
  678         } else {
  679                 /*
  680                  * Ensure there is enough space for the DER encoded length.
  681                  */
  682                 len_len = (*p & 0x7f) + 1;
  683                 if (tlen < len_len + 1)
  684                         return (NULL);
  685                 if (m->m_len < len_len + 1) {
  686                         if (can_pullup)
  687                                 *mp = m = m_pullup(m, len_len + 1);
  688                         else
  689                                 return (NULL);
  690                         p = m->m_data + 1;
  691                 }
  692 
  693                 switch (*p++) {
  694                 case 0x81:
  695                         inside_len = *p++;
  696                         break;
  697 
  698                 case 0x82:
  699                         inside_len = (p[0] << 8) | p[1];
  700                         p += 2;
  701                         break;
  702 
  703                 case 0x83:
  704                         inside_len = (p[0] << 16) | (p[1] << 8) | p[2];
  705                         p += 3;
  706                         break;
  707 
  708                 case 0x84:
  709                         inside_len = (p[0] << 24) | (p[1] << 16)
  710                                 | (p[2] << 8) | p[3];
  711                         p += 4;
  712                         break;
  713 
  714                 default:
  715                         return (NULL);
  716                 }
  717         }
  718 
  719         if (tlen != inside_len + len_len + 1)
  720                 return (NULL);
  721         if (inside_len < 2 + oid->length + len)
  722                 return (NULL);
  723 
  724         /*
  725          * Now that we know the value of len_len, we can pullup the
  726          * whole header. The header is 1 + len_len + 2 + oid->length +
  727          * len bytes.
  728          */
  729         hlen = 1 + len_len + 2 + oid->length + len;
  730         if (m->m_len < hlen) {
  731                 if (can_pullup)
  732                         *mp = m = m_pullup(m, hlen);
  733                 else
  734                         return (NULL);
  735                 p = m->m_data + 1 + len_len;
  736         }
  737 
  738         if (*p++ != 0x06)
  739                 return (NULL);
  740         if (*p++ != oid->length)
  741                 return (NULL);
  742         if (bcmp(oid->elements, p, oid->length))
  743                 return (NULL);
  744         p += oid->length;
  745 
  746         if (p[0] != tok_id[0])
  747                 return (NULL);
  748 
  749         if (p[1] != tok_id[1])
  750                 return (NULL);
  751 
  752         *encap_len = inside_len - 2 - oid->length;
  753 
  754         return (p);
  755 }
  756 
  757 static void
  758 krb5_insert_seq(struct krb5_msg_order *mo, uint32_t seq, int index)
  759 {
  760         int i;
  761 
  762         if (mo->km_length < mo->km_jitter_window)
  763                 mo->km_length++;
  764 
  765         for (i = mo->km_length - 1; i > index; i--)
  766                 mo->km_elem[i] = mo->km_elem[i - 1];
  767         mo->km_elem[index] = seq;
  768 }
  769 
  770 /*
  771  * Check sequence numbers according to RFC 2743 section 1.2.3.
  772  */
  773 static OM_uint32
  774 krb5_sequence_check(struct krb5_context *kc, uint32_t seq)
  775 {
  776         OM_uint32 res = GSS_S_FAILURE;
  777         struct krb5_msg_order *mo = &kc->kc_msg_order;
  778         int check_sequence = mo->km_flags & GSS_C_SEQUENCE_FLAG;
  779         int check_replay = mo->km_flags & GSS_C_REPLAY_FLAG;
  780         int i;
  781 
  782         mtx_lock(&kc->kc_lock);
  783 
  784         /*
  785          * Message is in-sequence with no gap.
  786          */
  787         if (mo->km_length == 0 || seq == mo->km_elem[0] + 1) {
  788                 /*
  789                  * This message is received in-sequence with no gaps.
  790                  */
  791                 krb5_insert_seq(mo, seq, 0);
  792                 res = GSS_S_COMPLETE;
  793                 goto out;
  794         }
  795 
  796         if (seq > mo->km_elem[0]) {
  797                 /*
  798                  * This message is received in-sequence with a gap.
  799                  */
  800                 krb5_insert_seq(mo, seq, 0);
  801                 if (check_sequence)
  802                         res = GSS_S_GAP_TOKEN;
  803                 else
  804                         res = GSS_S_COMPLETE;
  805                 goto out;
  806         }
  807 
  808         if (seq < mo->km_elem[mo->km_length - 1]) {
  809                 if (check_replay && !check_sequence)
  810                         res = GSS_S_OLD_TOKEN;
  811                 else
  812                         res = GSS_S_UNSEQ_TOKEN;
  813                 goto out;
  814         }
  815 
  816         for (i = 0; i < mo->km_length; i++) {
  817                 if (mo->km_elem[i] == seq) {
  818                         res = GSS_S_DUPLICATE_TOKEN;
  819                         goto out;
  820                 }
  821                 if (mo->km_elem[i] < seq) {
  822                         /*
  823                          * We need to insert this seq here,
  824                          */
  825                         krb5_insert_seq(mo, seq, i);
  826                         if (check_replay && !check_sequence)
  827                                 res = GSS_S_COMPLETE;
  828                         else
  829                                 res = GSS_S_UNSEQ_TOKEN;
  830                         goto out;
  831                 }
  832         }
  833 
  834 out:
  835         mtx_unlock(&kc->kc_lock);
  836 
  837         return (res);
  838 }
  839 
  840 static uint8_t sgn_alg_des_md5[] = { 0x00, 0x00 };
  841 static uint8_t seal_alg_des[] = { 0x00, 0x00 };
  842 static uint8_t sgn_alg_des3_sha1[] = { 0x04, 0x00 };
  843 static uint8_t seal_alg_des3[] = { 0x02, 0x00 };
  844 static uint8_t seal_alg_rc4[] = { 0x10, 0x00 };
  845 static uint8_t sgn_alg_hmac_md5[] = { 0x11, 0x00 };
  846 
  847 /*
  848  * Return the size of the inner token given the use of the key's
  849  * encryption class. For wrap tokens, the length of the padded
  850  * plaintext will be added to this.
  851  */
  852 static size_t
  853 token_length(struct krb5_key_state *key)
  854 {
  855 
  856         return (16 + key->ks_class->ec_checksumlen);
  857 }
  858 
  859 static OM_uint32
  860 krb5_get_mic_old(struct krb5_context *kc, struct mbuf *m,
  861     struct mbuf **micp, uint8_t sgn_alg[2])
  862 {
  863         struct mbuf *mlast, *mic, *tm;
  864         uint8_t *p, dir;
  865         size_t tlen, mlen, cklen;
  866         uint32_t seq;
  867         char buf[8];
  868 
  869         mlen = m_length(m, &mlast);
  870 
  871         tlen = token_length(kc->kc_tokenkey);
  872         p = krb5_make_token("\x01\x01", tlen, tlen, &mic);
  873         p += 2;                 /* TOK_ID */
  874         *p++ = sgn_alg[0];      /* SGN_ALG */
  875         *p++ = sgn_alg[1];
  876 
  877         *p++ = 0xff;            /* filler */
  878         *p++ = 0xff;
  879         *p++ = 0xff;
  880         *p++ = 0xff;
  881 
  882         /*
  883          * SGN_CKSUM:
  884          *
  885          * Calculate the keyed checksum of the token header plus the
  886          * message.
  887          */
  888         cklen = kc->kc_checksumkey->ks_class->ec_checksumlen;
  889 
  890         mic->m_len = p - (uint8_t *) mic->m_data;
  891         mic->m_next = m;
  892         MGET(tm, M_WAITOK, MT_DATA);
  893         tm->m_len = cklen;
  894         mlast->m_next = tm;
  895 
  896         krb5_checksum(kc->kc_checksumkey, 15, mic, mic->m_len - 8,
  897             8 + mlen, cklen);
  898         bcopy(tm->m_data, p + 8, cklen);
  899         mic->m_next = NULL;
  900         mlast->m_next = NULL;
  901         m_free(tm);
  902 
  903         /*
  904          * SND_SEQ:
  905          *
  906          * Take the four bytes of the sequence number least
  907          * significant first followed by four bytes of direction
  908          * marker (zero for initiator and 0xff for acceptor). Encrypt
  909          * that data using the SGN_CKSUM as IV. Note: ARC4 wants the
  910          * sequence number big-endian.
  911          */
  912         seq = atomic_fetchadd_32(&kc->kc_local_seqnumber, 1);
  913         if (sgn_alg[0] == 0x11) {
  914                 p[0] = (seq >> 24);
  915                 p[1] = (seq >> 16);
  916                 p[2] = (seq >> 8);
  917                 p[3] = (seq >> 0);
  918         } else {
  919                 p[0] = (seq >> 0);
  920                 p[1] = (seq >> 8);
  921                 p[2] = (seq >> 16);
  922                 p[3] = (seq >> 24);
  923         }
  924         if (is_initiator(kc)) {
  925                 dir = 0;
  926         } else {
  927                 dir = 0xff;
  928         }
  929         p[4] = dir;
  930         p[5] = dir;
  931         p[6] = dir;
  932         p[7] = dir;
  933         bcopy(p + 8, buf, 8);
  934 
  935         /*
  936          * Set the mic buffer to its final size so that the encrypt
  937          * can see the SND_SEQ part.
  938          */
  939         mic->m_len += 8 + cklen;
  940         krb5_encrypt(kc->kc_tokenkey, mic, mic->m_len - cklen - 8, 8, buf, 8);
  941 
  942         *micp = mic;
  943         return (GSS_S_COMPLETE);
  944 }
  945 
  946 static OM_uint32
  947 krb5_get_mic_new(struct krb5_context *kc,  struct mbuf *m,
  948     struct mbuf **micp)
  949 {
  950         struct krb5_key_state *key = kc->kc_send_sign_Kc;
  951         struct mbuf *mlast, *mic;
  952         uint8_t *p;
  953         int flags;
  954         size_t mlen, cklen;
  955         uint32_t seq;
  956 
  957         mlen = m_length(m, &mlast);
  958         cklen = key->ks_class->ec_checksumlen;
  959 
  960         KASSERT(16 + cklen <= MLEN, ("checksum too large for an mbuf"));
  961         MGET(mic, M_WAITOK, MT_DATA);
  962         M_ALIGN(mic, 16 + cklen);
  963         mic->m_len = 16 + cklen;
  964         p = mic->m_data;
  965 
  966         /* TOK_ID */
  967         p[0] = 0x04;
  968         p[1] = 0x04;
  969 
  970         /* Flags */
  971         flags = 0;
  972         if (is_acceptor(kc))
  973                 flags |= GSS_TOKEN_SENT_BY_ACCEPTOR;
  974         if (kc->kc_more_flags & ACCEPTOR_SUBKEY)
  975                 flags |= GSS_TOKEN_ACCEPTOR_SUBKEY;
  976         p[2] = flags;
  977 
  978         /* Filler */
  979         p[3] = 0xff;
  980         p[4] = 0xff;
  981         p[5] = 0xff;
  982         p[6] = 0xff;
  983         p[7] = 0xff;
  984 
  985         /* SND_SEQ */
  986         p[8] = 0;
  987         p[9] = 0;
  988         p[10] = 0;
  989         p[11] = 0;
  990         seq = atomic_fetchadd_32(&kc->kc_local_seqnumber, 1);
  991         p[12] = (seq >> 24);
  992         p[13] = (seq >> 16);
  993         p[14] = (seq >> 8);
  994         p[15] = (seq >> 0);
  995 
  996         /*
  997          * SGN_CKSUM:
  998          *
  999          * Calculate the keyed checksum of the message plus the first
 1000          * 16 bytes of the token header.
 1001          */
 1002         mlast->m_next = mic;
 1003         krb5_checksum(key, 0, m, 0, mlen + 16, cklen);
 1004         mlast->m_next = NULL;
 1005 
 1006         *micp = mic;
 1007         return (GSS_S_COMPLETE);
 1008 }
 1009 
 1010 static OM_uint32
 1011 krb5_get_mic(gss_ctx_id_t ctx, OM_uint32 *minor_status,
 1012     gss_qop_t qop_req, struct mbuf *m, struct mbuf **micp)
 1013 {
 1014         struct krb5_context *kc = (struct krb5_context *)ctx;
 1015 
 1016         *minor_status = 0;
 1017 
 1018         if (qop_req != GSS_C_QOP_DEFAULT)
 1019                 return (GSS_S_BAD_QOP);
 1020 
 1021         if (time_uptime > kc->kc_lifetime)
 1022                 return (GSS_S_CONTEXT_EXPIRED);
 1023 
 1024         switch (kc->kc_tokenkey->ks_class->ec_type) {
 1025         case ETYPE_DES_CBC_CRC:
 1026                 return (krb5_get_mic_old(kc, m, micp, sgn_alg_des_md5));
 1027 
 1028         case ETYPE_DES3_CBC_SHA1:
 1029                 return (krb5_get_mic_old(kc, m, micp, sgn_alg_des3_sha1));
 1030 
 1031         case ETYPE_ARCFOUR_HMAC_MD5:
 1032         case ETYPE_ARCFOUR_HMAC_MD5_56:
 1033                 return (krb5_get_mic_old(kc, m, micp, sgn_alg_hmac_md5));
 1034 
 1035         default:
 1036                 return (krb5_get_mic_new(kc, m, micp));
 1037         }
 1038 
 1039         return (GSS_S_FAILURE);
 1040 }
 1041 
 1042 static OM_uint32
 1043 krb5_verify_mic_old(struct krb5_context *kc, struct mbuf *m, struct mbuf *mic,
 1044     uint8_t sgn_alg[2])
 1045 {
 1046         struct mbuf *mlast, *tm;
 1047         uint8_t *p, *tp, dir;
 1048         size_t mlen, tlen, elen;
 1049         size_t cklen;
 1050         uint32_t seq;
 1051 
 1052         mlen = m_length(m, &mlast);
 1053 
 1054         tlen = token_length(kc->kc_tokenkey);
 1055         p = krb5_verify_token("\x01\x01", tlen, &mic, &elen, FALSE);
 1056         if (!p)
 1057                 return (GSS_S_DEFECTIVE_TOKEN);
 1058 #if 0
 1059         /*
 1060          * Disable this check - heimdal-1.1 generates DES3 MIC tokens
 1061          * that are 2 bytes too big.
 1062          */
 1063         if (elen != tlen)
 1064                 return (GSS_S_DEFECTIVE_TOKEN);
 1065 #endif
 1066         /* TOK_ID */
 1067         p += 2;
 1068 
 1069         /* SGN_ALG */
 1070         if (p[0] != sgn_alg[0] || p[1] != sgn_alg[1])
 1071                 return (GSS_S_DEFECTIVE_TOKEN);
 1072         p += 2;
 1073 
 1074         if (p[0] != 0xff || p[1] != 0xff || p[2] != 0xff || p[3] != 0xff)
 1075                 return (GSS_S_DEFECTIVE_TOKEN);
 1076         p += 4;
 1077 
 1078         /*
 1079          * SGN_CKSUM:
 1080          *
 1081          * Calculate the keyed checksum of the token header plus the
 1082          * message.
 1083          */
 1084         cklen = kc->kc_checksumkey->ks_class->ec_checksumlen;
 1085         mic->m_len = p - (uint8_t *) mic->m_data;
 1086         mic->m_next = m;
 1087         MGET(tm, M_WAITOK, MT_DATA);
 1088         tm->m_len = cklen;
 1089         mlast->m_next = tm;
 1090 
 1091         krb5_checksum(kc->kc_checksumkey, 15, mic, mic->m_len - 8,
 1092             8 + mlen, cklen);
 1093         mic->m_next = NULL;
 1094         mlast->m_next = NULL;
 1095         if (bcmp(tm->m_data, p + 8, cklen)) {
 1096                 m_free(tm);
 1097                 return (GSS_S_BAD_SIG);
 1098         }
 1099 
 1100         /*
 1101          * SND_SEQ:
 1102          *
 1103          * Take the four bytes of the sequence number least
 1104          * significant first followed by four bytes of direction
 1105          * marker (zero for initiator and 0xff for acceptor). Encrypt
 1106          * that data using the SGN_CKSUM as IV.  Note: ARC4 wants the
 1107          * sequence number big-endian.
 1108          */
 1109         bcopy(p, tm->m_data, 8);
 1110         tm->m_len = 8;
 1111         krb5_decrypt(kc->kc_tokenkey, tm, 0, 8, p + 8, 8);
 1112 
 1113         tp = tm->m_data;
 1114         if (sgn_alg[0] == 0x11) {
 1115                 seq = tp[3] | (tp[2] << 8) | (tp[1] << 16) | (tp[0] << 24);
 1116         } else {
 1117                 seq = tp[0] | (tp[1] << 8) | (tp[2] << 16) | (tp[3] << 24);
 1118         }
 1119 
 1120         if (is_initiator(kc)) {
 1121                 dir = 0xff;
 1122         } else {
 1123                 dir = 0;
 1124         }
 1125         if (tp[4] != dir || tp[5] != dir || tp[6] != dir || tp[7] != dir) {
 1126                 m_free(tm);
 1127                 return (GSS_S_DEFECTIVE_TOKEN);
 1128         }
 1129         m_free(tm);
 1130 
 1131         if (kc->kc_msg_order.km_flags &
 1132                 (GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG)) {
 1133                 return (krb5_sequence_check(kc, seq));
 1134         }
 1135 
 1136         return (GSS_S_COMPLETE);
 1137 }
 1138 
 1139 static OM_uint32
 1140 krb5_verify_mic_new(struct krb5_context *kc, struct mbuf *m, struct mbuf *mic)
 1141 {
 1142         OM_uint32 res;
 1143         struct krb5_key_state *key = kc->kc_recv_sign_Kc;
 1144         struct mbuf *mlast;
 1145         uint8_t *p;
 1146         int flags;
 1147         size_t mlen, cklen;
 1148         char buf[32];
 1149 
 1150         mlen = m_length(m, &mlast);
 1151         cklen = key->ks_class->ec_checksumlen;
 1152 
 1153         KASSERT(mic->m_next == NULL, ("MIC should be contiguous"));
 1154         if (mic->m_len != 16 + cklen)
 1155                 return (GSS_S_DEFECTIVE_TOKEN);
 1156         p = mic->m_data;
 1157 
 1158         /* TOK_ID */
 1159         if (p[0] != 0x04)
 1160                 return (GSS_S_DEFECTIVE_TOKEN);
 1161         if (p[1] != 0x04)
 1162                 return (GSS_S_DEFECTIVE_TOKEN);
 1163 
 1164         /* Flags */
 1165         flags = 0;
 1166         if (is_initiator(kc))
 1167                 flags |= GSS_TOKEN_SENT_BY_ACCEPTOR;
 1168         if (kc->kc_more_flags & ACCEPTOR_SUBKEY)
 1169                 flags |= GSS_TOKEN_ACCEPTOR_SUBKEY;
 1170         if (p[2] != flags)
 1171                 return (GSS_S_DEFECTIVE_TOKEN);
 1172 
 1173         /* Filler */
 1174         if (p[3] != 0xff)
 1175                 return (GSS_S_DEFECTIVE_TOKEN);
 1176         if (p[4] != 0xff)
 1177                 return (GSS_S_DEFECTIVE_TOKEN);
 1178         if (p[5] != 0xff)
 1179                 return (GSS_S_DEFECTIVE_TOKEN);
 1180         if (p[6] != 0xff)
 1181                 return (GSS_S_DEFECTIVE_TOKEN);
 1182         if (p[7] != 0xff)
 1183                 return (GSS_S_DEFECTIVE_TOKEN);
 1184 
 1185         /* SND_SEQ */
 1186         if (kc->kc_msg_order.km_flags &
 1187                 (GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG)) {
 1188                 uint32_t seq;
 1189                 if (p[8] || p[9] || p[10] || p[11]) {
 1190                         res = GSS_S_UNSEQ_TOKEN;
 1191                 } else {
 1192                         seq = (p[12] << 24) | (p[13] << 16)
 1193                                 | (p[14] << 8) | p[15];
 1194                         res = krb5_sequence_check(kc, seq);
 1195                 }
 1196                 if (GSS_ERROR(res))
 1197                         return (res);
 1198         } else {
 1199                 res = GSS_S_COMPLETE;
 1200         }
 1201 
 1202         /*
 1203          * SGN_CKSUM:
 1204          *
 1205          * Calculate the keyed checksum of the message plus the first
 1206          * 16 bytes of the token header.
 1207          */
 1208         m_copydata(mic, 16, cklen, buf);
 1209         mlast->m_next = mic;
 1210         krb5_checksum(key, 0, m, 0, mlen + 16, cklen);
 1211         mlast->m_next = NULL;
 1212         if (bcmp(buf, p + 16, cklen)) {
 1213                 return (GSS_S_BAD_SIG);
 1214         }
 1215 
 1216         return (GSS_S_COMPLETE);
 1217 }
 1218 
 1219 static OM_uint32
 1220 krb5_verify_mic(gss_ctx_id_t ctx, OM_uint32 *minor_status,
 1221     struct mbuf *m, struct mbuf *mic, gss_qop_t *qop_state)
 1222 {
 1223         struct krb5_context *kc = (struct krb5_context *)ctx;
 1224 
 1225         *minor_status = 0;
 1226         if (qop_state)
 1227                 *qop_state = GSS_C_QOP_DEFAULT;
 1228 
 1229         if (time_uptime > kc->kc_lifetime)
 1230                 return (GSS_S_CONTEXT_EXPIRED);
 1231 
 1232         switch (kc->kc_tokenkey->ks_class->ec_type) {
 1233         case ETYPE_DES_CBC_CRC:
 1234                 return (krb5_verify_mic_old(kc, m, mic, sgn_alg_des_md5));
 1235 
 1236         case ETYPE_ARCFOUR_HMAC_MD5:
 1237         case ETYPE_ARCFOUR_HMAC_MD5_56:
 1238                 return (krb5_verify_mic_old(kc, m, mic, sgn_alg_hmac_md5));
 1239 
 1240         case ETYPE_DES3_CBC_SHA1:
 1241                 return (krb5_verify_mic_old(kc, m, mic, sgn_alg_des3_sha1));
 1242 
 1243         default:
 1244                 return (krb5_verify_mic_new(kc, m, mic));
 1245         }
 1246 
 1247         return (GSS_S_FAILURE);
 1248 }
 1249 
 1250 static OM_uint32
 1251 krb5_wrap_old(struct krb5_context *kc, int conf_req_flag,
 1252     struct mbuf **mp, int *conf_state,
 1253     uint8_t sgn_alg[2], uint8_t seal_alg[2])
 1254 {
 1255         struct mbuf *m, *mlast, *tm, *cm, *pm;
 1256         size_t mlen, tlen, padlen, datalen;
 1257         uint8_t *p, dir;
 1258         size_t cklen;
 1259         uint8_t buf[8];
 1260         uint32_t seq;
 1261 
 1262         /*
 1263          * How many trailing pad bytes do we need?
 1264          */
 1265         m = *mp;
 1266         mlen = m_length(m, &mlast);
 1267         tlen = kc->kc_tokenkey->ks_class->ec_msgblocklen;
 1268         padlen = tlen - (mlen % tlen);
 1269 
 1270         /*
 1271          * The data part of the token has eight bytes of random
 1272          * confounder prepended and followed by up to eight bytes of
 1273          * padding bytes each of which is set to the number of padding
 1274          * bytes.
 1275          */
 1276         datalen = mlen + 8 + padlen;
 1277         tlen = token_length(kc->kc_tokenkey);
 1278 
 1279         p = krb5_make_token("\x02\x01", tlen, datalen + tlen, &tm);
 1280         p += 2;                 /* TOK_ID */
 1281         *p++ = sgn_alg[0];      /* SGN_ALG */
 1282         *p++ = sgn_alg[1];
 1283         if (conf_req_flag) {
 1284                 *p++ = seal_alg[0]; /* SEAL_ALG */
 1285                 *p++ = seal_alg[1];
 1286         } else {
 1287                 *p++ = 0xff;    /* SEAL_ALG = none */
 1288                 *p++ = 0xff;
 1289         }
 1290 
 1291         *p++ = 0xff;            /* filler */
 1292         *p++ = 0xff;
 1293 
 1294         /*
 1295          * Copy the padded message data.
 1296          */
 1297         if (M_LEADINGSPACE(m) >= 8) {
 1298                 m->m_data -= 8;
 1299                 m->m_len += 8;
 1300         } else {
 1301                 MGET(cm, M_WAITOK, MT_DATA);
 1302                 cm->m_len = 8;
 1303                 cm->m_next = m;
 1304                 m = cm;
 1305         }
 1306         arc4rand(m->m_data, 8, 0);
 1307         if (M_TRAILINGSPACE(mlast) >= padlen) {
 1308                 memset(mlast->m_data + mlast->m_len, padlen, padlen);
 1309                 mlast->m_len += padlen;
 1310         } else {
 1311                 MGET(pm, M_WAITOK, MT_DATA);
 1312                 memset(pm->m_data, padlen, padlen);
 1313                 pm->m_len = padlen;
 1314                 mlast->m_next = pm;
 1315                 mlast = pm;
 1316         }
 1317         tm->m_next = m;
 1318 
 1319         /*
 1320          * SGN_CKSUM:
 1321          *
 1322          * Calculate the keyed checksum of the token header plus the
 1323          * padded message. Fiddle with tm->m_len so that we only
 1324          * checksum the 8 bytes of head that we care about.
 1325          */
 1326         cklen = kc->kc_checksumkey->ks_class->ec_checksumlen;
 1327         tlen = tm->m_len;
 1328         tm->m_len = p - (uint8_t *) tm->m_data;
 1329         MGET(cm, M_WAITOK, MT_DATA);
 1330         cm->m_len = cklen;
 1331         mlast->m_next = cm;
 1332         krb5_checksum(kc->kc_checksumkey, 13, tm, tm->m_len - 8,
 1333             datalen + 8, cklen);
 1334         tm->m_len = tlen;
 1335         mlast->m_next = NULL;
 1336         bcopy(cm->m_data, p + 8, cklen);
 1337         m_free(cm);
 1338 
 1339         /*
 1340          * SND_SEQ:
 1341          *
 1342          * Take the four bytes of the sequence number least
 1343          * significant first (most significant first for ARCFOUR)
 1344          * followed by four bytes of direction marker (zero for
 1345          * initiator and 0xff for acceptor). Encrypt that data using
 1346          * the SGN_CKSUM as IV.
 1347          */
 1348         seq = atomic_fetchadd_32(&kc->kc_local_seqnumber, 1);
 1349         if (sgn_alg[0] == 0x11) {
 1350                 p[0] = (seq >> 24);
 1351                 p[1] = (seq >> 16);
 1352                 p[2] = (seq >> 8);
 1353                 p[3] = (seq >> 0);
 1354         } else {
 1355                 p[0] = (seq >> 0);
 1356                 p[1] = (seq >> 8);
 1357                 p[2] = (seq >> 16);
 1358                 p[3] = (seq >> 24);
 1359         }
 1360         if (is_initiator(kc)) {
 1361                 dir = 0;
 1362         } else {
 1363                 dir = 0xff;
 1364         }
 1365         p[4] = dir;
 1366         p[5] = dir;
 1367         p[6] = dir;
 1368         p[7] = dir;
 1369         krb5_encrypt(kc->kc_tokenkey, tm, p - (uint8_t *) tm->m_data,
 1370             8, p + 8, 8);
 1371 
 1372         if (conf_req_flag) {
 1373                 /*
 1374                  * Encrypt the padded message with an IV of zero for
 1375                  * DES and DES3, or an IV of the sequence number in
 1376                  * big-endian format for ARCFOUR.
 1377                  */
 1378                 if (seal_alg[0] == 0x10) {
 1379                         buf[0] = (seq >> 24);
 1380                         buf[1] = (seq >> 16);
 1381                         buf[2] = (seq >> 8);
 1382                         buf[3] = (seq >> 0);
 1383                         krb5_encrypt(kc->kc_encryptkey, m, 0, datalen,
 1384                             buf, 4);
 1385                 } else {
 1386                         krb5_encrypt(kc->kc_encryptkey, m, 0, datalen,
 1387                             NULL, 0);
 1388                 }
 1389         }
 1390 
 1391         if (conf_state)
 1392                 *conf_state = conf_req_flag;
 1393 
 1394         *mp = tm;
 1395         return (GSS_S_COMPLETE);
 1396 }
 1397 
 1398 static OM_uint32
 1399 krb5_wrap_new(struct krb5_context *kc, int conf_req_flag,
 1400     struct mbuf **mp, int *conf_state)
 1401 {
 1402         struct krb5_key_state *Ke = kc->kc_send_seal_Ke;
 1403         struct krb5_key_state *Ki = kc->kc_send_seal_Ki;
 1404         struct krb5_key_state *Kc = kc->kc_send_seal_Kc;
 1405         const struct krb5_encryption_class *ec = Ke->ks_class;
 1406         struct mbuf *m, *mlast, *tm;
 1407         uint8_t *p;
 1408         int flags, EC;
 1409         size_t mlen, blen, mblen, cklen, ctlen;
 1410         uint32_t seq;
 1411         static char zpad[32];
 1412 
 1413         m = *mp;
 1414         mlen = m_length(m, &mlast);
 1415 
 1416         blen = ec->ec_blocklen;
 1417         mblen = ec->ec_msgblocklen;
 1418         cklen = ec->ec_checksumlen;
 1419 
 1420         if (conf_req_flag) {
 1421                 /*
 1422                  * For sealed messages, we need space for 16 bytes of
 1423                  * header, blen confounder, plaintext, padding, copy
 1424                  * of header and checksum.
 1425                  *
 1426                  * We pad to mblen (which may be different from
 1427                  * blen). If the encryption class is using CTS, mblen
 1428                  * will be one (i.e. no padding required).
 1429                  */
 1430                 if (mblen > 1)
 1431                         EC = mlen % mblen;
 1432                 else
 1433                         EC = 0;
 1434                 ctlen = blen + mlen + EC + 16;
 1435 
 1436                 /*
 1437                  * Put initial header and confounder before the
 1438                  * message.
 1439                  */
 1440                 M_PREPEND(m, 16 + blen, M_WAITOK);
 1441 
 1442                 /*
 1443                  * Append padding + copy of header and checksum. Try
 1444                  * to fit this into the end of the original message,
 1445                  * otherwise allocate a trailer.
 1446                  */
 1447                 if (M_TRAILINGSPACE(mlast) >= EC + 16 + cklen) {
 1448                         tm = NULL;
 1449                         mlast->m_len += EC + 16 + cklen;
 1450                 } else {
 1451                         MGET(tm, M_WAITOK, MT_DATA);
 1452                         tm->m_len = EC + 16 + cklen;
 1453                         mlast->m_next = tm;
 1454                 }
 1455         } else {
 1456                 /*
 1457                  * For unsealed messages, we need 16 bytes of header
 1458                  * plus space for the plaintext and a checksum. EC is
 1459                  * set to the checksum size. We leave space in tm for
 1460                  * a copy of the header - this will be trimmed later.
 1461                  */
 1462                 M_PREPEND(m, 16, M_WAITOK);
 1463 
 1464                 MGET(tm, M_WAITOK, MT_DATA);
 1465                 tm->m_len = cklen + 16;
 1466                 mlast->m_next = tm;
 1467                 ctlen = 0;
 1468                 EC = cklen;
 1469         }
 1470 
 1471         p = m->m_data;
 1472 
 1473         /* TOK_ID */
 1474         p[0] = 0x05;
 1475         p[1] = 0x04;
 1476 
 1477         /* Flags */
 1478         flags = 0;
 1479         if (conf_req_flag)
 1480                 flags = GSS_TOKEN_SEALED;
 1481         if (is_acceptor(kc))
 1482                 flags |= GSS_TOKEN_SENT_BY_ACCEPTOR;
 1483         if (kc->kc_more_flags & ACCEPTOR_SUBKEY)
 1484                 flags |= GSS_TOKEN_ACCEPTOR_SUBKEY;
 1485         p[2] = flags;
 1486 
 1487         /* Filler */
 1488         p[3] = 0xff;
 1489 
 1490         /* EC + RRC - set to zero initially */
 1491         p[4] = 0;
 1492         p[5] = 0;
 1493         p[6] = 0;
 1494         p[7] = 0;
 1495 
 1496         /* SND_SEQ */
 1497         p[8] = 0;
 1498         p[9] = 0;
 1499         p[10] = 0;
 1500         p[11] = 0;
 1501         seq = atomic_fetchadd_32(&kc->kc_local_seqnumber, 1);
 1502         p[12] = (seq >> 24);
 1503         p[13] = (seq >> 16);
 1504         p[14] = (seq >> 8);
 1505         p[15] = (seq >> 0);
 1506 
 1507         if (conf_req_flag) {
 1508                 /*
 1509                  * Encrypt according to RFC 4121 section 4.2 and RFC
 1510                  * 3961 section 5.3. Note: we don't generate tokens
 1511                  * with RRC values other than zero. If we did, we
 1512                  * should zero RRC in the copied header.
 1513                  */
 1514                 arc4rand(p + 16, blen, 0);
 1515                 if (EC) {
 1516                         m_copyback(m, 16 + blen + mlen, EC, zpad);
 1517                 }
 1518                 m_copyback(m, 16 + blen + mlen + EC, 16, p);
 1519 
 1520                 krb5_checksum(Ki, 0, m, 16, ctlen, cklen);
 1521                 krb5_encrypt(Ke, m, 16, ctlen, NULL, 0);
 1522         } else {
 1523                 /*
 1524                  * The plaintext message is followed by a checksum of
 1525                  * the plaintext plus a version of the header where EC
 1526                  * and RRC are set to zero. Also, the original EC must
 1527                  * be our checksum size.
 1528                  */
 1529                 bcopy(p, tm->m_data, 16);
 1530                 krb5_checksum(Kc, 0, m, 16, mlen + 16, cklen);
 1531                 tm->m_data += 16;
 1532                 tm->m_len -= 16;
 1533         }
 1534 
 1535         /*
 1536          * Finally set EC to its actual value
 1537          */
 1538         p[4] = EC >> 8;
 1539         p[5] = EC;
 1540 
 1541         *mp = m;
 1542         return (GSS_S_COMPLETE);
 1543 }
 1544 
 1545 static OM_uint32
 1546 krb5_wrap(gss_ctx_id_t ctx, OM_uint32 *minor_status,
 1547     int conf_req_flag, gss_qop_t qop_req,
 1548     struct mbuf **mp, int *conf_state)
 1549 {
 1550         struct krb5_context *kc = (struct krb5_context *)ctx;
 1551 
 1552         *minor_status = 0;
 1553         if (conf_state)
 1554                 *conf_state = 0;
 1555 
 1556         if (qop_req != GSS_C_QOP_DEFAULT)
 1557                 return (GSS_S_BAD_QOP);
 1558 
 1559         if (time_uptime > kc->kc_lifetime)
 1560                 return (GSS_S_CONTEXT_EXPIRED);
 1561 
 1562         switch (kc->kc_tokenkey->ks_class->ec_type) {
 1563         case ETYPE_DES_CBC_CRC:
 1564                 return (krb5_wrap_old(kc, conf_req_flag,
 1565                         mp, conf_state, sgn_alg_des_md5, seal_alg_des));
 1566 
 1567         case ETYPE_ARCFOUR_HMAC_MD5:
 1568         case ETYPE_ARCFOUR_HMAC_MD5_56:
 1569                 return (krb5_wrap_old(kc, conf_req_flag,
 1570                         mp, conf_state, sgn_alg_hmac_md5, seal_alg_rc4));
 1571 
 1572         case ETYPE_DES3_CBC_SHA1:
 1573                 return (krb5_wrap_old(kc, conf_req_flag,
 1574                         mp, conf_state, sgn_alg_des3_sha1, seal_alg_des3));
 1575 
 1576         default:
 1577                 return (krb5_wrap_new(kc, conf_req_flag, mp, conf_state));
 1578         }
 1579 
 1580         return (GSS_S_FAILURE);
 1581 }
 1582 
 1583 static void
 1584 m_trim(struct mbuf *m, int len)
 1585 {
 1586         struct mbuf *n;
 1587         int off;
 1588 
 1589         if (m == NULL)
 1590                 return;
 1591         n = m_getptr(m, len, &off);
 1592         if (n) {
 1593                 n->m_len = off;
 1594                 if (n->m_next) {
 1595                         m_freem(n->m_next);
 1596                         n->m_next = NULL;
 1597                 }
 1598         }
 1599 }
 1600 
 1601 static OM_uint32
 1602 krb5_unwrap_old(struct krb5_context *kc, struct mbuf **mp, int *conf_state,
 1603     uint8_t sgn_alg[2], uint8_t seal_alg[2])
 1604 {
 1605         OM_uint32 res;
 1606         struct mbuf *m, *mlast, *hm, *cm, *n;
 1607         uint8_t *p, dir;
 1608         size_t tlen, elen, datalen, padlen;
 1609         size_t cklen;
 1610         uint8_t buf[32];
 1611         uint32_t seq;
 1612         int i, conf;
 1613 
 1614         m = *mp;
 1615         m_length(m, &mlast);
 1616 
 1617         tlen = token_length(kc->kc_tokenkey);
 1618         cklen = kc->kc_tokenkey->ks_class->ec_checksumlen;
 1619 
 1620         p = krb5_verify_token("\x02\x01", tlen, &m, &elen, TRUE);
 1621         *mp = m;
 1622         if (!p)
 1623                 return (GSS_S_DEFECTIVE_TOKEN);
 1624         datalen = elen - tlen;
 1625 
 1626         /*
 1627          * Trim the framing header first to make life a little easier
 1628          * later.
 1629          */
 1630         m_adj(m, p - (uint8_t *) m->m_data);
 1631 
 1632         /* TOK_ID */
 1633         p += 2;
 1634 
 1635         /* SGN_ALG */
 1636         if (p[0] != sgn_alg[0] || p[1] != sgn_alg[1])
 1637                 return (GSS_S_DEFECTIVE_TOKEN);
 1638         p += 2;
 1639 
 1640         /* SEAL_ALG */
 1641         if (p[0] == seal_alg[0] && p[1] == seal_alg[1])
 1642                 conf = 1;
 1643         else if (p[0] == 0xff && p[1] == 0xff)
 1644                 conf = 0;
 1645         else
 1646                 return (GSS_S_DEFECTIVE_TOKEN);
 1647         p += 2;
 1648 
 1649         if (p[0] != 0xff || p[1] != 0xff)
 1650                 return (GSS_S_DEFECTIVE_TOKEN);
 1651         p += 2;
 1652 
 1653         /*
 1654          * SND_SEQ:
 1655          *
 1656          * Take the four bytes of the sequence number least
 1657          * significant first (most significant for ARCFOUR) followed
 1658          * by four bytes of direction marker (zero for initiator and
 1659          * 0xff for acceptor). Encrypt that data using the SGN_CKSUM
 1660          * as IV.
 1661          */
 1662         krb5_decrypt(kc->kc_tokenkey, m, 8, 8, p + 8, 8);
 1663         if (sgn_alg[0] == 0x11) {
 1664                 seq = p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24);
 1665         } else {
 1666                 seq = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
 1667         }
 1668 
 1669         if (is_initiator(kc)) {
 1670                 dir = 0xff;
 1671         } else {
 1672                 dir = 0;
 1673         }
 1674         if (p[4] != dir || p[5] != dir || p[6] != dir || p[7] != dir)
 1675                 return (GSS_S_DEFECTIVE_TOKEN);
 1676 
 1677         if (kc->kc_msg_order.km_flags &
 1678             (GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG)) {
 1679                 res = krb5_sequence_check(kc, seq);
 1680                 if (GSS_ERROR(res))
 1681                         return (res);
 1682         } else {
 1683                 res = GSS_S_COMPLETE;
 1684         }
 1685 
 1686         /*
 1687          * If the token was encrypted, decode it in-place.
 1688          */
 1689         if (conf) {
 1690                 /*
 1691                  * Decrypt the padded message with an IV of zero for
 1692                  * DES and DES3 or an IV of the big-endian encoded
 1693                  * sequence number for ARCFOUR.
 1694                  */
 1695                 if (seal_alg[0] == 0x10) {
 1696                         krb5_decrypt(kc->kc_encryptkey, m, 16 + cklen,
 1697                             datalen, p, 4);
 1698                 } else {
 1699                         krb5_decrypt(kc->kc_encryptkey, m, 16 + cklen,
 1700                             datalen, NULL, 0);
 1701                 }
 1702         }
 1703         if (conf_state)
 1704                 *conf_state = conf;
 1705 
 1706         /*
 1707          * Check the trailing pad bytes.
 1708          * RFC1964 specifies between 1<->8 bytes, each with a binary value
 1709          * equal to the number of bytes.
 1710          */
 1711         if (mlast->m_len > 0)
 1712                 padlen = mlast->m_data[mlast->m_len - 1];
 1713         else {
 1714                 n = m_getptr(m, tlen + datalen - 1, &i);
 1715                 /*
 1716                  * When the position is exactly equal to the # of data bytes
 1717                  * in the mbuf list, m_getptr() will return the last mbuf in
 1718                  * the list and an off == m_len for that mbuf, so that case
 1719                  * needs to be checked as well as a NULL return.
 1720                  */
 1721                 if (n == NULL || n->m_len == i)
 1722                         return (GSS_S_DEFECTIVE_TOKEN);
 1723                 padlen = n->m_data[i];
 1724         }
 1725         if (padlen < 1 || padlen > 8 || padlen > tlen + datalen)
 1726                 return (GSS_S_DEFECTIVE_TOKEN);
 1727         m_copydata(m, tlen + datalen - padlen, padlen, buf);
 1728         for (i = 0; i < padlen; i++) {
 1729                 if (buf[i] != padlen) {
 1730                         return (GSS_S_DEFECTIVE_TOKEN);
 1731                 }
 1732         }
 1733 
 1734         /*
 1735          * SGN_CKSUM:
 1736          *
 1737          * Calculate the keyed checksum of the token header plus the
 1738          * padded message. We do a little mbuf surgery to trim out the
 1739          * parts we don't want to checksum.
 1740          */
 1741         hm = m;
 1742         *mp = m = m_split(m, 16 + cklen, M_WAITOK);
 1743         mlast = m_last(m);
 1744         hm->m_len = 8;
 1745         hm->m_next = m;
 1746         MGET(cm, M_WAITOK, MT_DATA);
 1747         cm->m_len = cklen;
 1748         mlast->m_next = cm;
 1749 
 1750         krb5_checksum(kc->kc_checksumkey, 13, hm, 0, datalen + 8, cklen);
 1751         hm->m_next = NULL;
 1752         mlast->m_next = NULL;
 1753 
 1754         if (bcmp(cm->m_data, hm->m_data + 16, cklen)) {
 1755                 m_freem(hm);
 1756                 m_free(cm);
 1757                 return (GSS_S_BAD_SIG);
 1758         }
 1759         m_freem(hm);
 1760         m_free(cm);
 1761 
 1762         /*
 1763          * Trim off the confounder and padding.
 1764          */
 1765         m_adj(m, 8);
 1766         if (mlast->m_len >= padlen) {
 1767                 mlast->m_len -= padlen;
 1768         } else {
 1769                 m_trim(m, datalen - 8 - padlen);
 1770         }
 1771 
 1772         *mp = m;
 1773         return (res);
 1774 }
 1775 
 1776 static OM_uint32
 1777 krb5_unwrap_new(struct krb5_context *kc, struct mbuf **mp, int *conf_state)
 1778 {
 1779         OM_uint32 res;
 1780         struct krb5_key_state *Ke = kc->kc_recv_seal_Ke;
 1781         struct krb5_key_state *Ki = kc->kc_recv_seal_Ki;
 1782         struct krb5_key_state *Kc = kc->kc_recv_seal_Kc;
 1783         const struct krb5_encryption_class *ec = Ke->ks_class;
 1784         struct mbuf *m, *mlast, *hm, *cm;
 1785         uint8_t *p;
 1786         int sealed, flags, EC, RRC;
 1787         size_t blen, cklen, ctlen, mlen, plen, tlen;
 1788         char buf[32], buf2[32];
 1789 
 1790         m = *mp;
 1791         mlen = m_length(m, &mlast);
 1792 
 1793         if (mlen <= 16)
 1794                 return (GSS_S_DEFECTIVE_TOKEN);
 1795         if (m->m_len < 16) {
 1796                 m = m_pullup(m, 16);
 1797                 *mp = m;
 1798         }
 1799         p = m->m_data;
 1800 
 1801         /* TOK_ID */
 1802         if (p[0] != 0x05)
 1803                 return (GSS_S_DEFECTIVE_TOKEN);
 1804         if (p[1] != 0x04)
 1805                 return (GSS_S_DEFECTIVE_TOKEN);
 1806 
 1807         /* Flags */
 1808         sealed = p[2] & GSS_TOKEN_SEALED;
 1809         flags = sealed;
 1810         if (is_initiator(kc))
 1811                 flags |= GSS_TOKEN_SENT_BY_ACCEPTOR;
 1812         if (kc->kc_more_flags & ACCEPTOR_SUBKEY)
 1813                 flags |= GSS_TOKEN_ACCEPTOR_SUBKEY;
 1814         if (p[2] != flags)
 1815                 return (GSS_S_DEFECTIVE_TOKEN);
 1816 
 1817         /* Filler */
 1818         if (p[3] != 0xff)
 1819                 return (GSS_S_DEFECTIVE_TOKEN);
 1820 
 1821         /* EC + RRC */
 1822         EC = (p[4] << 8) + p[5];
 1823         RRC = (p[6] << 8) + p[7];
 1824 
 1825         /* SND_SEQ */
 1826         if (kc->kc_msg_order.km_flags &
 1827                 (GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG)) {
 1828                 uint32_t seq;
 1829                 if (p[8] || p[9] || p[10] || p[11]) {
 1830                         res = GSS_S_UNSEQ_TOKEN;
 1831                 } else {
 1832                         seq = (p[12] << 24) | (p[13] << 16)
 1833                                 | (p[14] << 8) | p[15];
 1834                         res = krb5_sequence_check(kc, seq);
 1835                 }
 1836                 if (GSS_ERROR(res))
 1837                         return (res);
 1838         } else {
 1839                 res = GSS_S_COMPLETE;
 1840         }
 1841 
 1842         /*
 1843          * Separate the header before dealing with RRC. We only need
 1844          * to keep the header if the message isn't encrypted.
 1845          */
 1846         if (sealed) {
 1847                 hm = NULL;
 1848                 m_adj(m, 16);
 1849         } else {
 1850                 hm = m;
 1851                 *mp = m = m_split(m, 16, M_WAITOK);
 1852                 mlast = m_last(m);
 1853         }
 1854 
 1855         /*
 1856          * Undo the effects of RRC by rotating left.
 1857          */
 1858         if (RRC > 0) {
 1859                 struct mbuf *rm;
 1860                 size_t rlen;
 1861 
 1862                 rlen = mlen - 16;
 1863                 if (RRC <= sizeof(buf) && m->m_len >= rlen) {
 1864                         /*
 1865                          * Simple case, just rearrange the bytes in m.
 1866                          */
 1867                         bcopy(m->m_data, buf, RRC);
 1868                         bcopy(m->m_data + RRC, m->m_data, rlen - RRC);
 1869                         bcopy(buf, m->m_data + rlen - RRC, RRC);
 1870                 } else {
 1871                         /*
 1872                          * More complicated - rearrange the mbuf
 1873                          * chain.
 1874                          */
 1875                         rm = m;
 1876                         *mp = m = m_split(m, RRC, M_WAITOK);
 1877                         m_cat(m, rm);
 1878                         mlast = rm;
 1879                 }
 1880         }
 1881 
 1882         blen = ec->ec_blocklen;
 1883         cklen = ec->ec_checksumlen;
 1884         if (sealed) {
 1885                 /*
 1886                  * Decrypt according to RFC 4121 section 4.2 and RFC
 1887                  * 3961 section 5.3. The message must be large enough
 1888                  * for a blocksize confounder, at least one block of
 1889                  * cyphertext and a checksum.
 1890                  */
 1891                 if (mlen < 16 + 2*blen + cklen)
 1892                         return (GSS_S_DEFECTIVE_TOKEN);
 1893 
 1894                 ctlen = mlen - 16 - cklen;
 1895                 krb5_decrypt(Ke, m, 0, ctlen, NULL, 0);
 1896 
 1897                 /*
 1898                  * The size of the plaintext is ctlen minus blocklen
 1899                  * (for the confounder), 16 (for the copy of the token
 1900                  * header) and EC (for the filler). The actual
 1901                  * plaintext starts after the confounder.
 1902                  */
 1903                 plen = ctlen - blen - 16 - EC;
 1904 
 1905                 /*
 1906                  * Checksum the padded plaintext.
 1907                  */
 1908                 m_copydata(m, ctlen, cklen, buf);
 1909                 krb5_checksum(Ki, 0, m, 0, ctlen, cklen);
 1910                 m_copydata(m, ctlen, cklen, buf2);
 1911 
 1912                 if (bcmp(buf, buf2, cklen))
 1913                         return (GSS_S_BAD_SIG);
 1914 
 1915                 /*
 1916                  * Trim the message back to just plaintext.
 1917                  */
 1918                 m_adj(m, blen);
 1919                 tlen = 16 + EC + cklen;
 1920                 if (mlast->m_len >= tlen) {
 1921                         mlast->m_len -= tlen;
 1922                 } else {
 1923                         m_trim(m, plen);
 1924                 }
 1925         } else {
 1926                 /*
 1927                  * The plaintext message is followed by a checksum of
 1928                  * the plaintext plus a version of the header where EC
 1929                  * and RRC are set to zero. Also, the original EC must
 1930                  * be our checksum size.
 1931                  */
 1932                 if (mlen < 16 + cklen || EC != cklen)
 1933                         return (GSS_S_DEFECTIVE_TOKEN);
 1934 
 1935                 /*
 1936                  * The size of the plaintext is simply the message
 1937                  * size less header and checksum. The plaintext starts
 1938                  * right after the header (which we have saved in hm).
 1939                  */
 1940                 plen = mlen - 16 - cklen;
 1941 
 1942                 /*
 1943                  * Insert a copy of the header (with EC and RRC set to
 1944                  * zero) between the plaintext message and the
 1945                  * checksum.
 1946                  */
 1947                 p = hm->m_data;
 1948                 p[4] = p[5] = p[6] = p[7] = 0;
 1949 
 1950                 cm = m_split(m, plen, M_WAITOK);
 1951                 mlast = m_last(m);
 1952                 m->m_next = hm;
 1953                 hm->m_next = cm;
 1954 
 1955                 bcopy(cm->m_data, buf, cklen);
 1956                 krb5_checksum(Kc, 0, m, 0, plen + 16, cklen);
 1957                 if (bcmp(cm->m_data, buf, cklen))
 1958                         return (GSS_S_BAD_SIG);
 1959 
 1960                 /*
 1961                  * The checksum matches, discard all buf the plaintext.
 1962                  */
 1963                 mlast->m_next = NULL;
 1964                 m_freem(hm);
 1965         }
 1966 
 1967         if (conf_state)
 1968                 *conf_state = (sealed != 0);
 1969 
 1970         return (res);
 1971 }
 1972 
 1973 static OM_uint32
 1974 krb5_unwrap(gss_ctx_id_t ctx, OM_uint32 *minor_status,
 1975     struct mbuf **mp, int *conf_state, gss_qop_t *qop_state)
 1976 {
 1977         struct krb5_context *kc = (struct krb5_context *)ctx;
 1978         OM_uint32 maj_stat;
 1979 
 1980         *minor_status = 0;
 1981         if (qop_state)
 1982                 *qop_state = GSS_C_QOP_DEFAULT;
 1983         if (conf_state)
 1984                 *conf_state = 0;
 1985 
 1986         if (time_uptime > kc->kc_lifetime)
 1987                 return (GSS_S_CONTEXT_EXPIRED);
 1988 
 1989         switch (kc->kc_tokenkey->ks_class->ec_type) {
 1990         case ETYPE_DES_CBC_CRC:
 1991                 maj_stat = krb5_unwrap_old(kc, mp, conf_state,
 1992                         sgn_alg_des_md5, seal_alg_des);
 1993                 break;
 1994 
 1995         case ETYPE_ARCFOUR_HMAC_MD5:
 1996         case ETYPE_ARCFOUR_HMAC_MD5_56:
 1997                 maj_stat = krb5_unwrap_old(kc, mp, conf_state,
 1998                         sgn_alg_hmac_md5, seal_alg_rc4);
 1999                 break;
 2000 
 2001         case ETYPE_DES3_CBC_SHA1:
 2002                 maj_stat = krb5_unwrap_old(kc, mp, conf_state,
 2003                         sgn_alg_des3_sha1, seal_alg_des3);
 2004                 break;
 2005 
 2006         default:
 2007                 maj_stat = krb5_unwrap_new(kc, mp, conf_state);
 2008                 break;
 2009         }
 2010 
 2011         if (GSS_ERROR(maj_stat)) {
 2012                 m_freem(*mp);
 2013                 *mp = NULL;
 2014         }
 2015 
 2016         return (maj_stat);
 2017 }
 2018 
 2019 static OM_uint32
 2020 krb5_wrap_size_limit(gss_ctx_id_t ctx, OM_uint32 *minor_status,
 2021     int conf_req_flag, gss_qop_t qop_req, OM_uint32 req_output_size,
 2022     OM_uint32 *max_input_size)
 2023 {
 2024         struct krb5_context *kc = (struct krb5_context *)ctx;
 2025         const struct krb5_encryption_class *ec;
 2026         OM_uint32 overhead;
 2027 
 2028         *minor_status = 0;
 2029         *max_input_size = 0;
 2030 
 2031         if (qop_req != GSS_C_QOP_DEFAULT)
 2032                 return (GSS_S_BAD_QOP);
 2033 
 2034         ec = kc->kc_tokenkey->ks_class;
 2035         switch (ec->ec_type) {
 2036         case ETYPE_DES_CBC_CRC:
 2037         case ETYPE_DES3_CBC_SHA1:
 2038         case ETYPE_ARCFOUR_HMAC_MD5: 
 2039         case ETYPE_ARCFOUR_HMAC_MD5_56:
 2040                 /*
 2041                  * up to 5 bytes for [APPLICATION 0] SEQUENCE
 2042                  * 2 + krb5 oid length
 2043                  * 8 bytes of header
 2044                  * 8 bytes of confounder
 2045                  * maximum of 8 bytes of padding
 2046                  * checksum
 2047                  */
 2048                 overhead = 5 + 2 + krb5_mech_oid.length;
 2049                 overhead += 8 + 8 + ec->ec_msgblocklen;
 2050                 overhead += ec->ec_checksumlen;
 2051                 break;
 2052 
 2053         default:
 2054                 if (conf_req_flag) {
 2055                         /*
 2056                          * 16 byts of header
 2057                          * blocklen bytes of confounder
 2058                          * up to msgblocklen - 1 bytes of padding
 2059                          * 16 bytes for copy of header
 2060                          * checksum
 2061                          */
 2062                         overhead = 16 + ec->ec_blocklen;
 2063                         overhead += ec->ec_msgblocklen - 1;
 2064                         overhead += 16;
 2065                         overhead += ec->ec_checksumlen;
 2066                 } else {
 2067                         /*
 2068                          * 16 bytes of header plus checksum.
 2069                          */
 2070                         overhead = 16 + ec->ec_checksumlen;
 2071                 }
 2072         }
 2073 
 2074         *max_input_size = req_output_size - overhead;
 2075 
 2076         return (GSS_S_COMPLETE);
 2077 }
 2078 
 2079 static kobj_method_t krb5_methods[] = {
 2080         KOBJMETHOD(kgss_init,           krb5_init),
 2081         KOBJMETHOD(kgss_import,         krb5_import),
 2082         KOBJMETHOD(kgss_delete,         krb5_delete),
 2083         KOBJMETHOD(kgss_mech_type,      krb5_mech_type),
 2084         KOBJMETHOD(kgss_get_mic,        krb5_get_mic),
 2085         KOBJMETHOD(kgss_verify_mic,     krb5_verify_mic),
 2086         KOBJMETHOD(kgss_wrap,           krb5_wrap),
 2087         KOBJMETHOD(kgss_unwrap,         krb5_unwrap),
 2088         KOBJMETHOD(kgss_wrap_size_limit, krb5_wrap_size_limit),
 2089         { 0, 0 }
 2090 };
 2091 
 2092 static struct kobj_class krb5_class = {
 2093         "kerberosv5",
 2094         krb5_methods,
 2095         sizeof(struct krb5_context)
 2096 };
 2097 
 2098 /*
 2099  * Kernel module glue
 2100  */
 2101 static int
 2102 kgssapi_krb5_modevent(module_t mod, int type, void *data)
 2103 {
 2104 
 2105         switch (type) {
 2106         case MOD_LOAD:
 2107                 kgss_install_mech(&krb5_mech_oid, "kerberosv5", &krb5_class);
 2108                 break;
 2109 
 2110         case MOD_UNLOAD:
 2111                 kgss_uninstall_mech(&krb5_mech_oid);
 2112                 break;
 2113         }
 2114 
 2115         return (0);
 2116 }
 2117 static moduledata_t kgssapi_krb5_mod = {
 2118         "kgssapi_krb5",
 2119         kgssapi_krb5_modevent,
 2120         NULL,
 2121 };
 2122 DECLARE_MODULE(kgssapi_krb5, kgssapi_krb5_mod, SI_SUB_VFS, SI_ORDER_ANY);
 2123 MODULE_DEPEND(kgssapi_krb5, kgssapi, 1, 1, 1);
 2124 MODULE_DEPEND(kgssapi_krb5, crypto, 1, 1, 1);
 2125 MODULE_DEPEND(kgssapi_krb5, rc4, 1, 1, 1);
 2126 MODULE_VERSION(kgssapi_krb5, 1);

Cache object: bbcd8bb0352d26cc181203fbc16ea345


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