Print this page
NEX-15558 SMB logon fails during 1st second after service start
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15558 SMB logon fails during 1st second after service start
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-2626 SMB should not offer Kerberos in workgroup mode
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-4083 Upstream changes from illumos 5917 and 5995
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-2485 SMB authentication flood handled poorly
NEX-1810 extended security Kerberos (inbound)
NEX-1995 SMB fails to authenticate domain user with 40 or more domain group memberships
SUP-866 smbd lwps stuck in libsocket recv() for no apparent reason (more lint)
SUP-866 smbd lwps stuck in libsocket recv() for no apparent reason (lint)
SUP-866 smbd lwps stuck in libsocket recv() for no apparent reason
SMB-149 mount.cifs RedHat\Centos 6 doesn't work with default security options
SMB-77 Support raw NTLMSSP
SMB-50 User-mode SMB server (fix elfchk noise)
SMB-56 extended security NTLMSSP, inbound (fix a leak)
SMB-56 extended security NTLMSSP, inbound
   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  14  */
  15 
  16 /*
  17  * SMB authentication service
  18  *
  19  * This service listens on a local AF_UNIX socket, spawning a
  20  * thread to service each connection.  The client-side of such
  21  * connections is the in-kernel SMB service, with an open and
  22  * connect done in the SMB session setup handler.
  23  */
  24 
  25 #include <sys/types.h>
  26 #include <stdlib.h>
  27 #include <errno.h>
  28 #include <string.h>
  29 #include <strings.h>
  30 #include <unistd.h>
  31 #include <signal.h>
  32 #include <stdio.h>
  33 #include <note.h>


  86 /*
  87  * The maximum number of authentication thread is limited by the
  88  * smbsrv smb_threshold_...(->sv_ssetup_ct) mechanism.  However,
  89  * due to occasional delays closing these auth. sockets, we need
  90  * a little "slack" on the number of threads we'll allow, as
  91  * compared with the in-kernel limit.  We could perhaps just
  92  * remove this limit now, but want it for extra safety.
  93  */
  94 int smbd_authsvc_maxthread = SMB_AUTHSVC_MAXTHREAD + 32;
  95 int smbd_authsvc_thrcnt = 0;    /* current thrcnt */
  96 int smbd_authsvc_hiwat = 0;     /* largest thrcnt seen */
  97 #ifdef DEBUG
  98 int smbd_authsvc_slowdown = 0;
  99 #endif
 100 
 101 /*
 102  * These are the mechanisms we support, in order of preference.
 103  * But note: it's really the _client's_ preference that matters.
 104  * See &pref in the spnegoIsMechTypeAvailable() calls below.
 105  * Careful with this table; the code below knows its format and
 106  * may skip the fist two entries to ommit Kerberos.
 107  */
 108 static const spnego_mech_handler_t
 109 mech_table[] = {
 110         {
 111                 spnego_mech_oid_Kerberos_V5,
 112                 smbd_krb5ssp_init,
 113                 smbd_krb5ssp_work,
 114                 smbd_krb5ssp_fini
 115         },
 116         {
 117                 spnego_mech_oid_Kerberos_V5_Legacy,
 118                 smbd_krb5ssp_init,
 119                 smbd_krb5ssp_work,
 120                 smbd_krb5ssp_fini
 121         },
 122 #define MECH_TBL_IDX_NTLMSSP    2
 123         {
 124                 spnego_mech_oid_NTLMSSP,
 125                 smbd_ntlmssp_init,
 126                 smbd_ntlmssp_work,


 532 
 533 static int
 534 smbd_authsvc_oldreq(authsvc_context_t *ctx)
 535 {
 536         smb_logon_t     user_info;
 537         XDR             xdrs;
 538         smb_token_t     *token = NULL;
 539         int             rc = 0;
 540 
 541         bzero(&user_info, sizeof (user_info));
 542         xdrmem_create(&xdrs, ctx->ctx_irawbuf, ctx->ctx_irawlen,
 543             XDR_DECODE);
 544         if (!smb_logon_xdr(&xdrs, &user_info)) {
 545                 xdr_destroy(&xdrs);
 546                 return (NT_STATUS_INVALID_PARAMETER);
 547         }
 548         xdr_destroy(&xdrs);
 549 
 550         token = smbd_user_auth_logon(&user_info);
 551         xdr_free(smb_logon_xdr, (char *)&user_info);
 552         if (token == NULL)
 553                 return (NT_STATUS_ACCESS_DENIED);




 554 
 555         ctx->ctx_token = token;
 556 
 557         return (rc);
 558 }
 559 
 560 static int
 561 smbd_authsvc_clinfo(authsvc_context_t *ctx)
 562 {
 563 
 564         if (ctx->ctx_irawlen != sizeof (smb_lsa_clinfo_t))
 565                 return (NT_STATUS_INTERNAL_ERROR);
 566         (void) memcpy(&ctx->ctx_clinfo, ctx->ctx_irawbuf,
 567             sizeof (smb_lsa_clinfo_t));
 568 
 569         ctx->ctx_orawtype = LSA_MTYPE_OK;
 570         ctx->ctx_orawlen = 0;
 571         return (0);
 572 }
 573 


 614         rc = spnegoGetTokenType(ctx->ctx_itoken, &ctx->ctx_itoktype);
 615         if (rc != 0) {
 616                 smbd_report("authsvc: spnego get token type failed");
 617                 return (NT_STATUS_INVALID_PARAMETER);
 618         }
 619 
 620         if (ctx->ctx_itoktype != SPNEGO_TOKEN_INIT) {
 621                 smbd_report("authsvc: spnego wrong token type %d",
 622                     ctx->ctx_itoktype);
 623                 return (NT_STATUS_INVALID_PARAMETER);
 624         }
 625 
 626         /*
 627          * Figure out which mech type to use.  We want to use the
 628          * first of the client's supported mechanisms that we also
 629          * support.  Unfortunately, the spnego code does not have an
 630          * interface to walk the token's mech list, so we have to
 631          * ask about each mech type we know and keep track of which
 632          * was earliest in the token's mech list.
 633          *
 634          * Also, skip the Kerberos mechanisms in workgroup mode.
 635          */
 636         idx = 0;
 637         mh = mech_table;
 638         if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) {
 639                 idx = MECH_TBL_IDX_NTLMSSP;
 640                 mh = &mech_table[idx];
 641         }
 642         for (; mh->mh_init != NULL; idx++, mh++) {
 643 
 644                 if (spnegoIsMechTypeAvailable(ctx->ctx_itoken,
 645                     mh->mh_oid, &pref) != 0)
 646                         continue;
 647 
 648                 if (pref < best_pref) {
 649                         best_pref = pref;
 650                         best_mhidx = idx;
 651                 }
 652         }
 653         if (best_mhidx == -1) {
 654                 smbd_report("authsvc: no supported spnego mechanism");


 764          *
 765          * The worker must fill in:  ctx->ctx_negresult,
 766          * and: ctx->ctx_obodylen, but ctx->ctx_obodybuf
 767          * is optional, and is typically NULL after the
 768          * final message of an auth sequence, where
 769          * negresult == spnego_negresult_complete.
 770          */
 771         rc = ctx->ctx_mh_work(ctx);
 772         if (rc != 0)
 773                 return (rc);
 774 
 775         /*
 776          * Wrap the outgoing body in a negTokenTarg SPNEGO token.
 777          * The selected mech. OID is returned only when the
 778          * incoming token was of type SPNEGO_TOKEN_INIT.
 779          */
 780         if (ctx->ctx_itoktype == SPNEGO_TOKEN_INIT) {
 781                 /* tell the client the selected mech. */
 782                 oid = ctx->ctx_mech_oid;
 783         } else {
 784                 /* Ommit the "supported mech." field. */
 785                 oid = spnego_mech_oid_NotUsed;
 786         }
 787 
 788         /*
 789          * Determine the spnego "negresult" from the
 790          * reply message type (from the work func).
 791          */
 792         switch (ctx->ctx_orawtype) {
 793         case LSA_MTYPE_ERROR:
 794                 ctx->ctx_negresult = spnego_negresult_rejected;
 795                 break;
 796         case LSA_MTYPE_ES_DONE:
 797                 ctx->ctx_negresult = spnego_negresult_success;
 798                 break;
 799         case LSA_MTYPE_ES_CONT:
 800                 ctx->ctx_negresult = spnego_negresult_incomplete;
 801                 break;
 802         default:
 803                 return (-1);
 804         }


 898         if (len > ctx->ctx_orawlen) {
 899                 if ((ctx->ctx_orawbuf = realloc(ctx->ctx_orawbuf, len)) ==
 900                     NULL) {
 901                         return (NT_STATUS_INTERNAL_ERROR);
 902                 }
 903         }
 904 
 905         ctx->ctx_orawtype = LSA_MTYPE_TOKEN;
 906         ctx->ctx_orawlen = len;
 907         xdrmem_create(&xdrs, ctx->ctx_orawbuf, len, XDR_ENCODE);
 908         if (!smb_token_xdr(&xdrs, token))
 909                 rc = NT_STATUS_INTERNAL_ERROR;
 910         xdr_destroy(&xdrs);
 911 
 912         return (rc);
 913 }
 914 
 915 /*
 916  * Initialization time code to figure out what mechanisms we support.
 917  * Careful with this table; the code below knows its format and may
 918  * skip the fist two entries to ommit Kerberos.
 919  */
 920 static SPNEGO_MECH_OID MechTypeList[] = {
 921         spnego_mech_oid_Kerberos_V5,
 922         spnego_mech_oid_Kerberos_V5_Legacy,
 923 #define MECH_OID_IDX_NTLMSSP    2
 924         spnego_mech_oid_NTLMSSP,
 925 };
 926 static int MechTypeCnt = sizeof (MechTypeList) /
 927         sizeof (MechTypeList[0]);
 928 
 929 /* This string is just like Windows. */
 930 static char IgnoreSPN[] = "not_defined_in_RFC4178@please_ignore";
 931 
 932 /*
 933  * Build the SPNEGO "hint" token based on the
 934  * configured authentication mechanisms.
 935  * (NTLMSSP, and maybe Kerberos)
 936  */
 937 void
 938 smbd_get_authconf(smb_kmod_cfg_t *kcfg)
 939 {
 940         SPNEGO_MECH_OID *mechList = MechTypeList;
 941         int mechCnt = MechTypeCnt;
 942         SPNEGO_TOKEN_HANDLE hSpnegoToken = NULL;
 943         uchar_t *pBuf = kcfg->skc_negtok;
 944         uint32_t *pBufLen = &kcfg->skc_negtok_len;
 945         ulong_t tLen = sizeof (kcfg->skc_negtok);
 946         int rc;
 947 
 948         /*
 949          * In workgroup mode, skip Kerberos.
 950          */
 951         if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) {
 952                 mechList += MECH_OID_IDX_NTLMSSP;
 953                 mechCnt  -= MECH_OID_IDX_NTLMSSP;
 954         }
 955 
 956         rc = spnegoCreateNegTokenHint(mechList, mechCnt,
 957             (uchar_t *)IgnoreSPN, &hSpnegoToken);
 958         if (rc != SPNEGO_E_SUCCESS) {
 959                 syslog(LOG_DEBUG, "smb_config_get_negtok: "
 960                     "spnegoCreateNegTokenHint, rc=%d", rc);
 961                 *pBufLen = 0;
 962                 return;
 963         }
 964         rc = spnegoTokenGetBinary(hSpnegoToken, pBuf, &tLen);
 965         if (rc != SPNEGO_E_SUCCESS) {
 966                 syslog(LOG_DEBUG, "smb_config_get_negtok: "
 967                     "spnegoTokenGetBinary, rc=%d", rc);
 968                 *pBufLen = 0;
 969         } else {
   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  14  */
  15 
  16 /*
  17  * SMB authentication service
  18  *
  19  * This service listens on a local AF_UNIX socket, spawning a
  20  * thread to service each connection.  The client-side of such
  21  * connections is the in-kernel SMB service, with an open and
  22  * connect done in the SMB session setup handler.
  23  */
  24 
  25 #include <sys/types.h>
  26 #include <stdlib.h>
  27 #include <errno.h>
  28 #include <string.h>
  29 #include <strings.h>
  30 #include <unistd.h>
  31 #include <signal.h>
  32 #include <stdio.h>
  33 #include <note.h>


  86 /*
  87  * The maximum number of authentication thread is limited by the
  88  * smbsrv smb_threshold_...(->sv_ssetup_ct) mechanism.  However,
  89  * due to occasional delays closing these auth. sockets, we need
  90  * a little "slack" on the number of threads we'll allow, as
  91  * compared with the in-kernel limit.  We could perhaps just
  92  * remove this limit now, but want it for extra safety.
  93  */
  94 int smbd_authsvc_maxthread = SMB_AUTHSVC_MAXTHREAD + 32;
  95 int smbd_authsvc_thrcnt = 0;    /* current thrcnt */
  96 int smbd_authsvc_hiwat = 0;     /* largest thrcnt seen */
  97 #ifdef DEBUG
  98 int smbd_authsvc_slowdown = 0;
  99 #endif
 100 
 101 /*
 102  * These are the mechanisms we support, in order of preference.
 103  * But note: it's really the _client's_ preference that matters.
 104  * See &pref in the spnegoIsMechTypeAvailable() calls below.
 105  * Careful with this table; the code below knows its format and
 106  * may skip the fist two entries to omit Kerberos.
 107  */
 108 static const spnego_mech_handler_t
 109 mech_table[] = {
 110         {
 111                 spnego_mech_oid_Kerberos_V5,
 112                 smbd_krb5ssp_init,
 113                 smbd_krb5ssp_work,
 114                 smbd_krb5ssp_fini
 115         },
 116         {
 117                 spnego_mech_oid_Kerberos_V5_Legacy,
 118                 smbd_krb5ssp_init,
 119                 smbd_krb5ssp_work,
 120                 smbd_krb5ssp_fini
 121         },
 122 #define MECH_TBL_IDX_NTLMSSP    2
 123         {
 124                 spnego_mech_oid_NTLMSSP,
 125                 smbd_ntlmssp_init,
 126                 smbd_ntlmssp_work,


 532 
 533 static int
 534 smbd_authsvc_oldreq(authsvc_context_t *ctx)
 535 {
 536         smb_logon_t     user_info;
 537         XDR             xdrs;
 538         smb_token_t     *token = NULL;
 539         int             rc = 0;
 540 
 541         bzero(&user_info, sizeof (user_info));
 542         xdrmem_create(&xdrs, ctx->ctx_irawbuf, ctx->ctx_irawlen,
 543             XDR_DECODE);
 544         if (!smb_logon_xdr(&xdrs, &user_info)) {
 545                 xdr_destroy(&xdrs);
 546                 return (NT_STATUS_INVALID_PARAMETER);
 547         }
 548         xdr_destroy(&xdrs);
 549 
 550         token = smbd_user_auth_logon(&user_info);
 551         xdr_free(smb_logon_xdr, (char *)&user_info);
 552         if (token == NULL) {
 553                 rc = user_info.lg_status;
 554                 if (rc == 0) /* should not happen */
 555                         rc = NT_STATUS_INTERNAL_ERROR;
 556                 return (rc);
 557         }
 558 
 559         ctx->ctx_token = token;
 560 
 561         return (rc);
 562 }
 563 
 564 static int
 565 smbd_authsvc_clinfo(authsvc_context_t *ctx)
 566 {
 567 
 568         if (ctx->ctx_irawlen != sizeof (smb_lsa_clinfo_t))
 569                 return (NT_STATUS_INTERNAL_ERROR);
 570         (void) memcpy(&ctx->ctx_clinfo, ctx->ctx_irawbuf,
 571             sizeof (smb_lsa_clinfo_t));
 572 
 573         ctx->ctx_orawtype = LSA_MTYPE_OK;
 574         ctx->ctx_orawlen = 0;
 575         return (0);
 576 }
 577 


 618         rc = spnegoGetTokenType(ctx->ctx_itoken, &ctx->ctx_itoktype);
 619         if (rc != 0) {
 620                 smbd_report("authsvc: spnego get token type failed");
 621                 return (NT_STATUS_INVALID_PARAMETER);
 622         }
 623 
 624         if (ctx->ctx_itoktype != SPNEGO_TOKEN_INIT) {
 625                 smbd_report("authsvc: spnego wrong token type %d",
 626                     ctx->ctx_itoktype);
 627                 return (NT_STATUS_INVALID_PARAMETER);
 628         }
 629 
 630         /*
 631          * Figure out which mech type to use.  We want to use the
 632          * first of the client's supported mechanisms that we also
 633          * support.  Unfortunately, the spnego code does not have an
 634          * interface to walk the token's mech list, so we have to
 635          * ask about each mech type we know and keep track of which
 636          * was earliest in the token's mech list.
 637          *
 638          * Also, if not in domain mode, skip the Kerberos.
 639          */
 640         idx = 0;
 641         mh = mech_table;
 642         if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) {
 643                 idx = MECH_TBL_IDX_NTLMSSP;
 644                 mh = &mech_table[idx];
 645         }
 646         for (; mh->mh_init != NULL; idx++, mh++) {
 647 
 648                 if (spnegoIsMechTypeAvailable(ctx->ctx_itoken,
 649                     mh->mh_oid, &pref) != 0)
 650                         continue;
 651 
 652                 if (pref < best_pref) {
 653                         best_pref = pref;
 654                         best_mhidx = idx;
 655                 }
 656         }
 657         if (best_mhidx == -1) {
 658                 smbd_report("authsvc: no supported spnego mechanism");


 768          *
 769          * The worker must fill in:  ctx->ctx_negresult,
 770          * and: ctx->ctx_obodylen, but ctx->ctx_obodybuf
 771          * is optional, and is typically NULL after the
 772          * final message of an auth sequence, where
 773          * negresult == spnego_negresult_complete.
 774          */
 775         rc = ctx->ctx_mh_work(ctx);
 776         if (rc != 0)
 777                 return (rc);
 778 
 779         /*
 780          * Wrap the outgoing body in a negTokenTarg SPNEGO token.
 781          * The selected mech. OID is returned only when the
 782          * incoming token was of type SPNEGO_TOKEN_INIT.
 783          */
 784         if (ctx->ctx_itoktype == SPNEGO_TOKEN_INIT) {
 785                 /* tell the client the selected mech. */
 786                 oid = ctx->ctx_mech_oid;
 787         } else {
 788                 /* Omit the "supported mech." field. */
 789                 oid = spnego_mech_oid_NotUsed;
 790         }
 791 
 792         /*
 793          * Determine the spnego "negresult" from the
 794          * reply message type (from the work func).
 795          */
 796         switch (ctx->ctx_orawtype) {
 797         case LSA_MTYPE_ERROR:
 798                 ctx->ctx_negresult = spnego_negresult_rejected;
 799                 break;
 800         case LSA_MTYPE_ES_DONE:
 801                 ctx->ctx_negresult = spnego_negresult_success;
 802                 break;
 803         case LSA_MTYPE_ES_CONT:
 804                 ctx->ctx_negresult = spnego_negresult_incomplete;
 805                 break;
 806         default:
 807                 return (-1);
 808         }


 902         if (len > ctx->ctx_orawlen) {
 903                 if ((ctx->ctx_orawbuf = realloc(ctx->ctx_orawbuf, len)) ==
 904                     NULL) {
 905                         return (NT_STATUS_INTERNAL_ERROR);
 906                 }
 907         }
 908 
 909         ctx->ctx_orawtype = LSA_MTYPE_TOKEN;
 910         ctx->ctx_orawlen = len;
 911         xdrmem_create(&xdrs, ctx->ctx_orawbuf, len, XDR_ENCODE);
 912         if (!smb_token_xdr(&xdrs, token))
 913                 rc = NT_STATUS_INTERNAL_ERROR;
 914         xdr_destroy(&xdrs);
 915 
 916         return (rc);
 917 }
 918 
 919 /*
 920  * Initialization time code to figure out what mechanisms we support.
 921  * Careful with this table; the code below knows its format and may
 922  * skip the fist two entries to omit Kerberos.
 923  */
 924 static SPNEGO_MECH_OID MechTypeList[] = {
 925         spnego_mech_oid_Kerberos_V5,
 926         spnego_mech_oid_Kerberos_V5_Legacy,
 927 #define MECH_OID_IDX_NTLMSSP    2
 928         spnego_mech_oid_NTLMSSP,
 929 };
 930 static int MechTypeCnt = sizeof (MechTypeList) /
 931         sizeof (MechTypeList[0]);
 932 
 933 /* This string is just like Windows. */
 934 static char IgnoreSPN[] = "not_defined_in_RFC4178@please_ignore";
 935 
 936 /*
 937  * Build the SPNEGO "hint" token based on the
 938  * configured authentication mechanisms.
 939  * (NTLMSSP, and maybe Kerberos)
 940  */
 941 void
 942 smbd_get_authconf(smb_kmod_cfg_t *kcfg)
 943 {
 944         SPNEGO_MECH_OID *mechList = MechTypeList;
 945         int mechCnt = MechTypeCnt;
 946         SPNEGO_TOKEN_HANDLE hSpnegoToken = NULL;
 947         uchar_t *pBuf = kcfg->skc_negtok;
 948         uint32_t *pBufLen = &kcfg->skc_negtok_len;
 949         ulong_t tLen = sizeof (kcfg->skc_negtok);
 950         int rc;
 951 
 952         /*
 953          * If not in domain mode, skip Kerberos.
 954          */
 955         if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) {
 956                 mechList += MECH_OID_IDX_NTLMSSP;
 957                 mechCnt  -= MECH_OID_IDX_NTLMSSP;
 958         }
 959 
 960         rc = spnegoCreateNegTokenHint(mechList, mechCnt,
 961             (uchar_t *)IgnoreSPN, &hSpnegoToken);
 962         if (rc != SPNEGO_E_SUCCESS) {
 963                 syslog(LOG_DEBUG, "smb_config_get_negtok: "
 964                     "spnegoCreateNegTokenHint, rc=%d", rc);
 965                 *pBufLen = 0;
 966                 return;
 967         }
 968         rc = spnegoTokenGetBinary(hSpnegoToken, pBuf, &tLen);
 969         if (rc != SPNEGO_E_SUCCESS) {
 970                 syslog(LOG_DEBUG, "smb_config_get_negtok: "
 971                     "spnegoTokenGetBinary, rc=%d", rc);
 972                 *pBufLen = 0;
 973         } else {