Print this page
NEX-18907 File Access Auditing does not work with SMB Kerberos authentication
Review by: Gordon Ross <gordon.ross@nexenta.com>
Review by: Evan Layton <evan.layton@nexenta.com>
NEX-3080 SMB1 signing problem with Kerberos auth.
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-1810 extended security Kerberos (inbound)
SMB-56 extended security NTLMSSP, inbound

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/smbsrv/smbd/smbd_krb5ssp.c
          +++ new/usr/src/cmd/smbsrv/smbd/smbd_krb5ssp.c
↓ open down ↓ 2 lines elided ↑ open up ↑
   3    3   * Common Development and Distribution License ("CDDL"), version 1.0.
   4    4   * You may only use this file in accordance with the terms of version
   5    5   * 1.0 of the CDDL.
   6    6   *
   7    7   * A full copy of the text of the CDDL should have accompanied this
   8    8   * source.  A copy of the CDDL is also available via the Internet at
   9    9   * http://www.illumos.org/license/CDDL.
  10   10   */
  11   11  
  12   12  /*
  13      - * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
       13 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  14   14   */
  15   15  
  16   16  /*
  17   17   * SPNEGO back-end for Kerberos.  See [MS-KILE]
  18   18   */
  19   19  
  20   20  #include <sys/types.h>
  21   21  #include <gssapi/gssapi_ext.h>
  22   22  #include <gssapi/gssapi_krb5.h>
  23   23  #include <krb5.h>
↓ open down ↓ 88 lines elided ↑ open up ↑
 112  112  {
 113  113          gss_buffer_desc intok, outtok;
 114  114          gss_buffer_desc namebuf;
 115  115          krb5ssp_backend_t *be = ctx->ctx_backend;
 116  116          gss_name_t gname = NULL;
 117  117          OM_uint32 major, minor, ret_flags;
 118  118          gss_OID name_type = GSS_C_NULL_OID;
 119  119          gss_OID mech_type = GSS_C_NULL_OID;
 120  120          krb5_error_code kerr;
 121  121          uint32_t status;
      122 +        smb_token_t *token = NULL;
 122  123  
 123  124          intok.length = ctx->ctx_ibodylen;
 124  125          intok.value  = ctx->ctx_ibodybuf;
 125  126          bzero(&outtok, sizeof (gss_buffer_desc));
 126  127          bzero(&namebuf, sizeof (gss_buffer_desc));
 127  128  
 128  129          /* Do this early, for error message support. */
 129  130          kerr = krb5_init_context(&be->be_kctx);
 130  131          if (kerr != 0) {
 131  132                  smbd_report("krb5ssp, krb5_init_ctx: %s",
 132  133                      krb5_get_error_message(be->be_kctx, kerr));
 133  134                  return (NT_STATUS_INTERNAL_ERROR);
 134  135          }
 135  136  
      137 +        free(be->be_username);
      138 +        be->be_username = NULL;
      139 +
 136  140          major = gss_accept_sec_context(&minor, &be->be_gssctx,
 137  141              GSS_C_NO_CREDENTIAL, &intok,
 138  142              GSS_C_NO_CHANNEL_BINDINGS, &gname, &mech_type, &outtok,
 139  143              &ret_flags, NULL, NULL);
 140  144  
 141  145          if (outtok.length == 0)
 142  146                  ctx->ctx_obodylen = 0;
 143  147          else if (outtok.length <= ctx->ctx_obodylen) {
 144  148                  ctx->ctx_obodylen = outtok.length;
 145  149                  (void) memcpy(ctx->ctx_obodybuf, outtok.value, outtok.length);
↓ open down ↓ 5 lines elided ↑ open up ↑
 151  155                  ctx->ctx_obodylen = outtok.length;
 152  156                  outtok.value = NULL;
 153  157          }
 154  158  
 155  159          if (GSS_ERROR(major)) {
 156  160                  smbd_report("krb5ssp: gss_accept_sec_context, "
 157  161                      "mech=0x%x, major=0x%x, minor=0x%x",
 158  162                      (int)mech_type, major, minor);
 159  163                  smbd_report(" krb5: %s",
 160  164                      krb5_get_error_message(be->be_kctx, minor));
 161      -                return (NT_STATUS_WRONG_PASSWORD);
      165 +                status = NT_STATUS_WRONG_PASSWORD;
      166 +                goto out;
 162  167          }
 163  168  
 164  169          switch (major) {
 165  170          case GSS_S_COMPLETE:
 166  171                  break;
 167  172          case GSS_S_CONTINUE_NEEDED:
 168  173                  if (outtok.length > 0) {
 169  174                          ctx->ctx_orawtype = LSA_MTYPE_ES_CONT;
 170  175                          /* becomes NT_STATUS_MORE_PROCESSING_REQUIRED */
 171  176                          return (0);
 172  177                  }
 173      -                return (NT_STATUS_WRONG_PASSWORD);
      178 +                status = NT_STATUS_WRONG_PASSWORD;
      179 +                goto out;
 174  180          default:
 175      -                return (NT_STATUS_WRONG_PASSWORD);
      181 +                status = NT_STATUS_WRONG_PASSWORD;
      182 +                goto out;
 176  183          }
 177  184  
 178  185          /*
 179  186           * OK, we got GSS_S_COMPLETE.  Get the name so we can use it
 180  187           * in log messages if we get failures decoding the PAC etc.
 181  188           * Then get the PAC, decode it, build the logon token.
 182  189           */
 183  190  
 184  191          if (gname != NULL && GSS_S_COMPLETE ==
 185  192              gss_display_name(&minor, gname, &namebuf, &name_type)) {
↓ open down ↓ 5 lines elided ↑ open up ↑
 191  198                          return (NT_STATUS_NO_MEMORY);
 192  199                  }
 193  200          }
 194  201  
 195  202          /*
 196  203           * Extract the KRB5_AUTHDATA_WIN2K_PAC data.
 197  204           */
 198  205          status = get_authz_data_pac(be->be_gssctx,
 199  206              &be->be_authz_pac);
 200  207          if (status)
 201      -                return (status);
      208 +                goto out;
 202  209  
 203  210          kerr = krb5_pac_parse(be->be_kctx, be->be_authz_pac.value,
 204  211              be->be_authz_pac.length, &be->be_kpac);
 205  212          if (kerr) {
 206  213                  smbd_report("krb5ssp, krb5_pac_parse: %s",
 207  214                      krb5_get_error_message(be->be_kctx, kerr));
 208      -                return (NT_STATUS_UNSUCCESSFUL);
      215 +                status = NT_STATUS_UNSUCCESSFUL;
      216 +                goto out;
 209  217          }
 210  218  
 211  219          kerr = krb5_pac_get_buffer(be->be_kctx, be->be_kpac,
 212  220              PAC_LOGON_INFO, &be->be_pac);
 213  221          if (kerr) {
 214  222                  smbd_report("krb5ssp, krb5_pac_get_buffer: %s",
 215  223                      krb5_get_error_message(be->be_kctx, kerr));
 216      -                return (NT_STATUS_UNSUCCESSFUL);
      224 +                status = NT_STATUS_UNSUCCESSFUL;
      225 +                goto out;
 217  226          }
 218  227  
 219  228          ctx->ctx_token = calloc(1, sizeof (smb_token_t));
 220      -        if (ctx->ctx_token == NULL)
 221      -                return (NT_STATUS_NO_MEMORY);
 222      -
      229 +        if (ctx->ctx_token == NULL) {
      230 +                status = NT_STATUS_NO_MEMORY;
      231 +                goto out;
      232 +        }
 223  233          status = smb_decode_krb5_pac(ctx->ctx_token, be->be_pac.data,
 224  234              be->be_pac.length);
 225  235          if (status)
 226      -                return (status);
      236 +                goto out;
 227  237  
 228  238          status = get_ssnkey(ctx);
 229  239          if (status)
 230      -                return (status);
      240 +                goto out;
 231  241  
 232      -        if (!smb_token_setup_common(ctx->ctx_token))
 233      -                return (NT_STATUS_UNSUCCESSFUL);
      242 +        if (!smb_token_setup_common(ctx->ctx_token)) {
      243 +                status = NT_STATUS_UNSUCCESSFUL;
      244 +                goto out;
      245 +        }
 234  246  
 235  247          /* Success! */
 236  248          ctx->ctx_orawtype = LSA_MTYPE_ES_DONE;
 237  249  
 238      -        return (0);
      250 +        status = 0;
      251 +        token = ctx->ctx_token;
      252 +
      253 +        /*
      254 +         * Before we return, audit successful and failed logons.
      255 +         * We only audit logons where we should have a username.
      256 +         */
      257 +out:
      258 +        if (!smbd_logon_audit(token, &ctx->ctx_clinfo.lci_clnt_ipaddr,
      259 +            be->be_username, "") && status == 0)
      260 +                return (NT_STATUS_AUDIT_FAILED);
      261 +
      262 +        return (status);
 239  263  }
 240  264  
 241  265  /*
 242  266   * See: GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID
 243  267   * and: KRB5_AUTHDATA_WIN2K_PAC
 244  268   */
 245  269  static const gss_OID_desc
 246  270  oid_ex_authz_data_pac = {
 247  271          13, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0a\x81\x00" };
 248  272  
↓ open down ↓ 102 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX