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 {
|