summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/Makefile5
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_in_tkt.c10
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/send_tgs.c7
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mech/inq_context.c35
-rw-r--r--usr/src/lib/libshare/smb/Makefile.com5
-rw-r--r--usr/src/lib/libsmbfs/Makefile5
-rw-r--r--usr/src/lib/libsmbfs/Makefile.com4
-rw-r--r--usr/src/lib/libsmbfs/netsmb/ntlmssp.h (renamed from usr/src/lib/libsmbfs/smb/ntlmssp.h)29
-rw-r--r--usr/src/lib/libsmbfs/netsmb/spnego.h260
-rw-r--r--usr/src/lib/libsmbfs/smb/derparse.c92
-rw-r--r--usr/src/lib/libsmbfs/smb/derparse.h8
-rw-r--r--usr/src/lib/libsmbfs/smb/llib-lsmbfs3
-rw-r--r--usr/src/lib/libsmbfs/smb/mapfile-vers16
-rw-r--r--usr/src/lib/libsmbfs/smb/spnego.c119
-rw-r--r--usr/src/lib/libsmbfs/smb/spnego.h244
-rw-r--r--usr/src/lib/libsmbfs/smb/spnegoparse.c94
-rw-r--r--usr/src/lib/libsmbfs/smb/spnegoparse.h7
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/Makefile.com1
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h4
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers3
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c97
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c4
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c122
-rw-r--r--usr/src/lib/smbsrv/libsmb/Makefile.com7
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/libsmb.h61
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/mapfile-vers11
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_auth.c241
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_cfg.c44
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_info.c24
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_kmod.c11
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_mac.c207
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c23
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h8
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_ksetpwd.c29
34 files changed, 1031 insertions, 809 deletions
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile
index 704d7ba772..544a04dd33 100644
--- a/usr/src/lib/Makefile
+++ b/usr/src/lib/Makefile
@@ -19,11 +19,11 @@
# CDDL HEADER END
#
-# Copyright 2011 Nexenta Systems, Inc. All rights reserved.
# Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2012 by Delphix. All rights reserved.
# Copyright (c) 2012, Joyent, Inc. All rights reserved.
# Copyright (c) 2013 Gary Mills
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
# Copyright 2014 Garrett D'Amore <garrett@damore.org>
# Copyright (c) 2015 Gary Mills
@@ -660,7 +660,8 @@ libexacct/demo: libexacct libproject libsocket libnsl
libtsalarm: libpcp
smbsrv: libsocket libnsl libmd libxnet libpthread librt \
libshare libidmap pkcs11 libsqlite libcryptoutil \
- libreparse libcmdutils libfakekernel
+ libreparse libcmdutils libresolv libsmbfs libuuid \
+ libfakekernel
libv12n: libds libuuid
libvrrpadm: libsocket libdladm libscf
libvscan: libscf
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_in_tkt.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_in_tkt.c
index 3138920e9b..967c8f7fe4 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_in_tkt.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_in_tkt.c
@@ -1,5 +1,7 @@
/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
/*
* lib/krb5/krb/get_in_tkt.c
*
@@ -130,6 +132,12 @@ send_as_request2(krb5_context context,
reply.data = 0;
+ /* Solaris Kerberos (illumos) */
+ if (krb5_getenv("MS_INTEROP")) {
+ /* Don't bother with UDP. */
+ tcp_only = 1;
+ }
+
/* set the nonce if the caller expects us to do it */
if (request->nonce == 0) {
if ((retval = krb5_timeofday(context, &time_now)))
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/send_tgs.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/send_tgs.c
index f3e159e6f9..10cdcdd502 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/send_tgs.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/send_tgs.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -176,6 +177,12 @@ krb5_send_tgs2(krb5_context context, krb5_flags kdcoptions,
if (!in_cred->ticket.length)
return(KRB5_NO_TKT_SUPPLIED);
+ /* Solaris Kerberos (illumos) */
+ if (krb5_getenv("MS_INTEROP")) {
+ /* Don't bother with UDP. */
+ tcp_only = 1;
+ }
+
memset((char *)&tgsreq, 0, sizeof(tgsreq));
tgsreq.kdc_options = kdcoptions;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/inq_context.c b/usr/src/lib/gss_mechs/mech_krb5/mech/inq_context.c
index b15cbbf14b..b5ec62c921 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mech/inq_context.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/mech/inq_context.c
@@ -1,4 +1,5 @@
/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -258,10 +259,12 @@ gss_krb5int_extract_authz_data_from_sec_context(
const gss_OID desired_object,
gss_buffer_set_t *data_set)
{
+ gss_buffer_desc ad_data;
OM_uint32 major_status;
+ krb5_error_code code;
krb5_gss_ctx_id_rec *ctx;
int ad_type = 0;
- size_t i;
+ int i, j;
*data_set = GSS_C_NO_BUFFER_SET;
@@ -280,7 +283,6 @@ gss_krb5int_extract_authz_data_from_sec_context(
if (ctx->authdata != NULL) {
for (i = 0; ctx->authdata[i] != NULL; i++) {
if (ctx->authdata[i]->ad_type == ad_type) {
- gss_buffer_desc ad_data;
ad_data.length = ctx->authdata[i]->length;
ad_data.value = ctx->authdata[i]->contents;
@@ -289,10 +291,39 @@ gss_krb5int_extract_authz_data_from_sec_context(
&ad_data, data_set);
if (GSS_ERROR(major_status))
break;
+ } else if (ctx->authdata[i]->ad_type == KRB5_AUTHDATA_IF_RELEVANT) {
+ /*
+ * Solaris Kerberos (illumos)
+ * Unwrap the AD-IF-RELEVANT object and look inside.
+ */
+ krb5_authdata **ad_if_relevant = NULL;
+ code = krb5_decode_authdata_container(ctx->k5_context,
+ KRB5_AUTHDATA_IF_RELEVANT,
+ ctx->authdata[i],
+ &ad_if_relevant);
+ if (code != 0)
+ continue;
+
+ for (j = 0; ad_if_relevant[j] != NULL; j++) {
+ if (ad_if_relevant[j]->ad_type == ad_type) {
+ ad_data.length = ad_if_relevant[j]->length;
+ ad_data.value = ad_if_relevant[j]->contents;
+
+ major_status = generic_gss_add_buffer_set_member(minor_status,
+ &ad_data, data_set);
+ if (GSS_ERROR(major_status)) {
+ krb5_free_authdata(ctx->k5_context, ad_if_relevant);
+ goto break2;
+ }
+ }
+ }
+ krb5_free_authdata(ctx->k5_context, ad_if_relevant);
+ /* Solaris Kerberos (illumos) */
}
}
}
+break2:
if (GSS_ERROR(major_status)) {
OM_uint32 tmp;
diff --git a/usr/src/lib/libshare/smb/Makefile.com b/usr/src/lib/libshare/smb/Makefile.com
index 0fc5f66142..ea69f59b22 100644
--- a/usr/src/lib/libshare/smb/Makefile.com
+++ b/usr/src/lib/libshare/smb/Makefile.com
@@ -22,7 +22,7 @@
# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
#
LIBRARY = libshare_smb.a
@@ -45,8 +45,7 @@ LIBSRCS = $(LIBOBJS:%.o=$(SRCDIR)/%.c)
lintcheck := SRCS = $(LIBSRCS)
LIBS = $(DYNLIB)
-LDLIBS += -lshare -ldlpi -lnsl -lnvpair -lscf -lumem -lc
-all install := LDLIBS += -lxml2
+LDLIBS += -lshare -lscf -luuid -ldlpi -lnsl -lnvpair -lxml2 -lumem -lc
CFLAGS += $(CCVERBOSE)
CERRWARN += -_gcc=-Wno-char-subscripts
diff --git a/usr/src/lib/libsmbfs/Makefile b/usr/src/lib/libsmbfs/Makefile
index 47c14c6bfa..b708bd0571 100644
--- a/usr/src/lib/libsmbfs/Makefile
+++ b/usr/src/lib/libsmbfs/Makefile
@@ -19,10 +19,11 @@
# CDDL HEADER END
#
#
-# Copyright 2011 Nexenta Systems, Inc. All rights reserved.
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
#
# lib/libsmbfs/Makefile
@@ -30,7 +31,7 @@
include $(SRC)/lib/Makefile.lib
-HDRS= smbfs_acl.h smbfs_api.h smb_keychain.h
+HDRS= ntlmssp.h smbfs_acl.h smbfs_api.h smb_keychain.h spnego.h
HDRDIR= netsmb
ROOTHDRDIR= $(ROOT)/usr/include/netsmb
diff --git a/usr/src/lib/libsmbfs/Makefile.com b/usr/src/lib/libsmbfs/Makefile.com
index a3ec0fb397..f5801a18db 100644
--- a/usr/src/lib/libsmbfs/Makefile.com
+++ b/usr/src/lib/libsmbfs/Makefile.com
@@ -23,6 +23,8 @@
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
#
# lib/libsmbfs/Makefile.com
@@ -101,7 +103,7 @@ CERRWARN += -_gcc=-Wno-uninitialized
CERRWARN += -_gcc=-Wno-unused-variable
CPPFLAGS += -D__EXTENSIONS__ -D_REENTRANT -DMIA \
- -I$(SRCDIR) -I.. \
+ -I$(SRCDIR) -I.. -I../netsmb \
-I$(SRC)/uts/common \
-I$(SRC)/common/smbclnt
diff --git a/usr/src/lib/libsmbfs/smb/ntlmssp.h b/usr/src/lib/libsmbfs/netsmb/ntlmssp.h
index 5f3e09ac0d..f4cfc34783 100644
--- a/usr/src/lib/libsmbfs/smb/ntlmssp.h
+++ b/usr/src/lib/libsmbfs/netsmb/ntlmssp.h
@@ -22,6 +22,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
@@ -37,6 +38,10 @@
* http://msdn.microsoft.com/en-us/library/cc236621(PROT.10).aspx
*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* NTLMSSP Message Types
* [MS-NLMP] sec. 2.2.1
@@ -82,4 +87,28 @@
#define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000
#define NTLMSSP_NEGOTIATE_56 0x80000000
+/*
+ * NTLMSSP AV_PAIR types
+ * [MS-NLMP] sec. 2.2.2.1
+ *
+ * The names are all LE-Unicode.
+ */
+typedef enum ntlmssp_AvId {
+ MsvAvEOL = 0, /* End Of List */
+ MsvAvNbComputerName, /* server's NetBIOS name */
+ MsvAvNbDomainName, /* server's NetBIOS domain */
+ MsvAvDnsComputerName, /* server's DNS name */
+ MsvAvDnsDomainName, /* server's DNS domain */
+ MsvAvDnsTreeName, /* server's Forest name */
+ MsvAvFlags, /* 32-bit (LE) flags */
+ MsvAvTimestamp, /* 64-bit time, [MS-DTYP] sec. 2.3.1 */
+ MsvAvRestrictions, /* struct, [MS-NLMP] sec. 2.2.2.2 */
+ MsvAvTargetName, /* SPN of the server */
+ MsvChannelBindings, /* MD5 hash of GSS challen bindings */
+} ntlmssp_AvId_t;
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _NTLMSSP_H */
diff --git a/usr/src/lib/libsmbfs/netsmb/spnego.h b/usr/src/lib/libsmbfs/netsmb/spnego.h
new file mode 100644
index 0000000000..1a60436740
--- /dev/null
+++ b/usr/src/lib/libsmbfs/netsmb/spnego.h
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2002 Microsoft Corporation
+ * All rights reserved.
+ *
+ * THIS CODE AND INFORMATION IS PROVIDED "AS IS"
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY
+ * AND/OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Date - 10/08/2002
+ * Author - Sanj Surati
+ */
+
+/*
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * spnego.h
+ *
+ * SPNEGO Token Handler Header File
+ *
+ * Contains the definitions required to interpret and create
+ * SPNEGO tokens so that Kerberos GSS tokens can be
+ * Unpackaged/packaged.
+ */
+
+#ifndef _SPNEGO_H
+#define _SPNEGO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Type Definitions
+ */
+
+/*
+ * Users of SPNEGO Token Handler API will request
+ * these as well as free them,
+ */
+typedef void* SPNEGO_TOKEN_HANDLE;
+
+/*
+ * Defines the element types that are found
+ * in each of the tokens.
+ */
+
+typedef enum spnego_element_type
+{
+ spnego_element_min, /* Lower bound */
+
+ /* Init token elements */
+ spnego_init_mechtypes,
+ spnego_init_reqFlags,
+ spnego_init_mechToken,
+ spnego_init_mechListMIC,
+
+ /* Targ token elements */
+ spnego_targ_negResult,
+ spnego_targ_supportedMech,
+ spnego_targ_responseToken,
+ spnego_targ_mechListMIC,
+
+ spnego_element_max /* Upper bound */
+
+} SPNEGO_ELEMENT_TYPE;
+
+/*
+ * Token Element Availability. Elements in both
+ * token types are optional. Since there are only
+ * 4 elements in each Token, we will allocate space
+ * to hold the information, but we need a way to
+ * indicate whether or not an element is available
+ */
+
+#define SPNEGO_TOKEN_ELEMENT_UNAVAILABLE 0
+#define SPNEGO_TOKEN_ELEMENT_AVAILABLE 1
+
+/*
+ * Token type values. SPNEGO has 2 token types:
+ * NegTokenInit and NegTokenTarg
+ */
+
+#define SPNEGO_TOKEN_INIT 0
+#define SPNEGO_TOKEN_TARG 1
+
+/*
+ * GSS Mechanism OID enumeration. We only really handle
+ * 3 different OIDs. These are stored in an array structure
+ * defined in the parsing code.
+ */
+
+typedef enum spnego_mech_oid
+{
+ /* Init token elements */
+ spnego_mech_oid_Kerberos_V5_Legacy, /* Really V5, but OID off by 1 */
+ spnego_mech_oid_Kerberos_V5,
+ spnego_mech_oid_Spnego,
+ spnego_mech_oid_NTLMSSP,
+ spnego_mech_oid_NotUsed = -1
+
+} SPNEGO_MECH_OID;
+
+/*
+ * Defines the negResult values.
+ */
+
+typedef enum spnego_negResult
+{
+ spnego_negresult_success,
+ spnego_negresult_incomplete,
+ spnego_negresult_rejected,
+ spnego_negresult_NotUsed = -1
+} SPNEGO_NEGRESULT;
+
+/*
+ * Context Flags in NegTokenInit
+ */
+
+/*
+ * ContextFlags values MUST be zero or a combination
+ * of the below
+ */
+
+#define SPNEGO_NEGINIT_CONTEXT_DELEG_FLAG 0x80
+#define SPNEGO_NEGINIT_CONTEXT_MUTUAL_FLAG 0x40
+#define SPNEGO_NEGINIT_CONTEXT_REPLAY_FLAG 0x20
+#define SPNEGO_NEGINIT_CONTEXT_SEQUENCE_FLAG 0x10
+#define SPNEGO_NEGINIT_CONTEXT_ANON_FLAG 0x8
+#define SPNEGO_NEGINIT_CONTEXT_CONF_FLAG 0x4
+#define SPNEGO_NEGINIT_CONTEXT_INTEG_FLAG 0x2
+
+/*
+ * Mask to retrieve valid values.
+ */
+
+#define SPNEGO_NEGINIT_CONTEXT_MASK 0xFE
+
+/*
+ * SPNEGO API return codes.
+ */
+
+/* API function was successful */
+#define SPNEGO_E_SUCCESS 0
+
+/* The supplied Token was invalid */
+#define SPNEGO_E_INVALID_TOKEN -1
+
+/* An invalid length was encountered */
+#define SPNEGO_E_INVALID_LENGTH -2
+
+/* The Token Parse failed */
+#define SPNEGO_E_PARSE_FAILED -3
+
+/* The requested value was not found */
+#define SPNEGO_E_NOT_FOUND -4
+
+/* The requested element is not available */
+#define SPNEGO_E_ELEMENT_UNAVAILABLE -5
+
+/* Out of Memory */
+#define SPNEGO_E_OUT_OF_MEMORY -6
+
+/* Not Implemented */
+#define SPNEGO_E_NOT_IMPLEMENTED -7
+
+/* Invalid Parameter */
+#define SPNEGO_E_INVALID_PARAMETER -8
+
+/* Token Handler encountered an unexpected OID */
+#define SPNEGO_E_UNEXPECTED_OID -9
+
+/* The requested token was not found */
+#define SPNEGO_E_TOKEN_NOT_FOUND -10
+
+/* An unexpected type was encountered in the encoding */
+#define SPNEGO_E_UNEXPECTED_TYPE -11
+
+/* The buffer was too small */
+#define SPNEGO_E_BUFFER_TOO_SMALL -12
+
+/* A Token Element was invalid (e.g. improper length or value) */
+#define SPNEGO_E_INVALID_ELEMENT -13
+
+/* Miscelaneous API Functions */
+
+/* Frees opaque data */
+void spnegoFreeData(SPNEGO_TOKEN_HANDLE hSpnegoToken);
+
+/* Initializes SPNEGO_TOKEN structure from DER encoded binary data */
+int spnegoInitFromBinary(unsigned char *pbTokenData, unsigned long ulLength,
+ SPNEGO_TOKEN_HANDLE* phSpnegoToken);
+
+/* Initializes SPNEGO_TOKEN structure for a NegTokenInit type */
+int spnegoCreateNegTokenHint(SPNEGO_MECH_OID *pMechTypeList, int MechTypeCnt,
+ unsigned char *pbPrincipal, SPNEGO_TOKEN_HANDLE* phSpnegoToken);
+
+/* Initializes SPNEGO_TOKEN structure for a NegTokenInit type */
+int spnegoCreateNegTokenInit(SPNEGO_MECH_OID MechType,
+ unsigned char ucContextFlags, unsigned char *pbMechToken,
+ unsigned long ulMechTokenLen, unsigned char *pbMechTokenMIC,
+ unsigned long ulMechTokenMIC, SPNEGO_TOKEN_HANDLE *phSpnegoToken);
+
+/* Initializes SPNEGO_TOKEN structure for a NegTokenTarg type */
+int spnegoCreateNegTokenTarg(SPNEGO_MECH_OID MechType,
+ SPNEGO_NEGRESULT spnegoNegResult, unsigned char *pbMechToken,
+ unsigned long ulMechTokenLen, unsigned char *pbMechListMIC,
+ unsigned long ulMechListMICLen, SPNEGO_TOKEN_HANDLE* phSpnegoToken);
+
+/* Copies binary representation of SPNEGO Data into user supplied buffer */
+int spnegoTokenGetBinary(SPNEGO_TOKEN_HANDLE hSpnegoToken,
+ unsigned char *pbTokenData, unsigned long *pulDataLen);
+
+/* Returns SPNEGO Token Type */
+int spnegoGetTokenType(SPNEGO_TOKEN_HANDLE hSpnegoToken, int *piTokenType);
+
+/* Reading an Init Token */
+
+/* Returns the Initial Mech Type in the MechList element in the NegInitToken. */
+int spnegoIsMechTypeAvailable(SPNEGO_TOKEN_HANDLE hSpnegoToken,
+ SPNEGO_MECH_OID MechOID, int *piMechTypeIndex);
+
+/* Returns the value from the context flags element in the NegInitToken */
+int spnegoGetContextFlags(SPNEGO_TOKEN_HANDLE hSpnegoToken,
+ unsigned char *pucContextFlags);
+
+/* Reading a Response Token */
+
+/*
+ * Returns the value from the negResult element
+ * (Status code of GSS call - 0,1,2)
+ */
+int spnegoGetNegotiationResult(SPNEGO_TOKEN_HANDLE hSpnegoToken,
+ SPNEGO_NEGRESULT* pnegResult);
+
+/* Returns the Supported Mech Type from the NegTokenTarg. */
+int spnegoGetSupportedMechType(SPNEGO_TOKEN_HANDLE hSpnegoToken,
+ SPNEGO_MECH_OID* pMechOID);
+
+/* Reading either Token Type */
+
+/*
+ * Returns the actual Mechanism data from the token
+ * (this is what is passed into GSS-API functions
+ */
+int spnegoGetMechToken(SPNEGO_TOKEN_HANDLE hSpnegoToken,
+ unsigned char *pbTokenData, unsigned long *pulDataLen);
+
+/* Returns the Message Integrity BLOB in the token */
+int spnegoGetMechListMIC(SPNEGO_TOKEN_HANDLE hSpnegoToken,
+ unsigned char *pbMICData, unsigned long *pulDataLen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SPNEGO_H */
diff --git a/usr/src/lib/libsmbfs/smb/derparse.c b/usr/src/lib/libsmbfs/smb/derparse.c
index f92da913c2..f21a277d5a 100644
--- a/usr/src/lib/libsmbfs/smb/derparse.c
+++ b/usr/src/lib/libsmbfs/smb/derparse.c
@@ -1,3 +1,4 @@
+// Copyright 2012 Nexenta Systems, Inc. All rights reserved.
// Copyright (C) 2002 Microsoft Corporation
// All rights reserved.
//
@@ -451,29 +452,37 @@ long ASNDerCalcElementLength( long nDataLength, long* pnInternalLength )
// Comments :
// Helper function to calculate a MechList length. A mechlist consists
// of a NegTokenInit sequence token, a sequence token for the MechList
-// and finally a list of OIDs. In our case, we only really have one
-// OID.
+// and finally a list of OIDs.
//
////////////////////////////////////////////////////////////////////////////
-long ASNDerCalcMechListLength( SPNEGO_MECH_OID mechoid, long* pnInternalLength )
+long ASNDerCalcMechListLength( SPNEGO_MECH_OID *mechOidLst, int mechOidCnt,
+ long* pnInternalLength )
{
- // First the OID
- long nTotalLength = g_stcMechOIDList[mechoid].iLen;
-
- // Next add in a sequence token
- nTotalLength += ASNDerCalcTokenLength( nTotalLength, 0L );
-
- // Internal length is the length without the element sequence token
- if ( NULL != pnInternalLength )
- {
- *pnInternalLength = nTotalLength;
- }
-
- // Finally add in the element's sequence token
- nTotalLength += ASNDerCalcTokenLength( nTotalLength, 0L );
-
- return nTotalLength;
+ // First the OID
+ SPNEGO_MECH_OID oid_idx;
+ long nTotalLength;
+ int i;
+
+ nTotalLength = 0;
+ for (i = 0; i < mechOidCnt; i++) {
+ oid_idx = mechOidLst[i];
+ nTotalLength += g_stcMechOIDList[oid_idx].iLen;
+ }
+
+ // Next add in a sequence token
+ nTotalLength += ASNDerCalcTokenLength( nTotalLength, 0L );
+
+ // Internal length is the length without the element sequence token
+ if ( NULL != pnInternalLength )
+ {
+ *pnInternalLength = nTotalLength;
+ }
+
+ // Finally add in the element's sequence token
+ nTotalLength += ASNDerCalcTokenLength( nTotalLength, 0L );
+
+ return nTotalLength;
}
@@ -646,9 +655,12 @@ int ASNDerWriteToken( unsigned char* pbData, unsigned char ucType,
int ASNDerWriteOID( unsigned char* pbData, SPNEGO_MECH_OID eMechOID )
{
- memcpy( pbData, g_stcMechOIDList[eMechOID].ucOid, g_stcMechOIDList[eMechOID].iLen );
+ if (pbData != NULL) {
+ memcpy( pbData, g_stcMechOIDList[eMechOID].ucOid,
+ g_stcMechOIDList[eMechOID].iLen );
+ }
- return g_stcMechOIDList[eMechOID].iLen;
+ return g_stcMechOIDList[eMechOID].iLen;
}
@@ -671,27 +683,35 @@ int ASNDerWriteOID( unsigned char* pbData, SPNEGO_MECH_OID eMechOID )
//
////////////////////////////////////////////////////////////////////////////
-long ASNDerWriteMechList( unsigned char* pbData, SPNEGO_MECH_OID mechoid )
+long ASNDerWriteMechList( unsigned char* pbData, SPNEGO_MECH_OID *mechOidLst, int mechOidCnt )
{
- // First get the length
- long nInternalLength = 0L;
- long nMechListLength = ASNDerCalcMechListLength( mechoid, &nInternalLength );
- long nTempLength = 0L;
-
- nTempLength = ASNDerWriteToken( pbData, SPNEGO_NEGINIT_ELEMENT_MECHTYPES,
+ // First get the length
+ long nInternalLength = 0L;
+ long nMechListLength;
+ long nTempLength = 0L;
+ int i;
+
+ nMechListLength = ASNDerCalcMechListLength(mechOidLst, mechOidCnt, &nInternalLength);
+ nTempLength = ASNDerWriteToken( pbData, SPNEGO_NEGINIT_ELEMENT_MECHTYPES,
NULL, nInternalLength );
- // Adjust the data pointer
- pbData += nTempLength;
+ // Adjust the data pointer
+ pbData += nTempLength;
+ nInternalLength -= nTempLength;
+
+ // Now write the Sequence token and the OID (the OID is a BLOB in the global
+ // structure.
- // Now write the Sequence token and the OID (the OID is a BLOB in the global
- // structure.
+ nTempLength = ASNDerWriteToken( pbData, SPNEGO_CONSTRUCTED_SEQUENCE,
+ NULL, nInternalLength);
+ pbData += nTempLength;
- nTempLength = ASNDerWriteToken( pbData, SPNEGO_CONSTRUCTED_SEQUENCE,
- g_stcMechOIDList[mechoid].ucOid,
- g_stcMechOIDList[mechoid].iLen );
+ for (i = 0; i < mechOidCnt; i++) {
+ nTempLength = ASNDerWriteOID( pbData, mechOidLst[i] );
+ pbData += nTempLength;
+ }
- return nMechListLength;
+ return nMechListLength;
}
diff --git a/usr/src/lib/libsmbfs/smb/derparse.h b/usr/src/lib/libsmbfs/smb/derparse.h
index dcdf5828dc..b1801c8e1c 100644
--- a/usr/src/lib/libsmbfs/smb/derparse.h
+++ b/usr/src/lib/libsmbfs/smb/derparse.h
@@ -1,3 +1,4 @@
+// Copyright 2012 Nexenta Systems, Inc. All rights reserved.
// Copyright (C) 2002 Microsoft Corporation
// All rights reserved.
//
@@ -21,8 +22,6 @@
//
/////////////////////////////////////////////////////////////
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifndef __DERPARSE_H__
#define __DERPARSE_H__
@@ -178,12 +177,13 @@ int ASNDerCheckOID( unsigned char* pbTokenData, SPNEGO_MECH_OID nMechOID, long n
int ASNDerCalcNumLengthBytes( long nLength );
long ASNDerCalcTokenLength( long nLength, long nDataLength );
long ASNDerCalcElementLength( long nDataLength, long* pnInternalLength );
-long ASNDerCalcMechListLength( SPNEGO_MECH_OID mechoid, long* pnInternalLength );
+long ASNDerCalcMechListLength( SPNEGO_MECH_OID *mechOidLst, int mechOidCnt,
+ long* pnInternalLength );
int ASNDerWriteLength( unsigned char* pbData, long nLength );
int ASNDerWriteToken( unsigned char* pbData, unsigned char ucType,
unsigned char* pbTokenValue, long nLength );
int ASNDerWriteOID( unsigned char* pbData, SPNEGO_MECH_OID eMechOID );
-long ASNDerWriteMechList( unsigned char* pbData, SPNEGO_MECH_OID mechoid );
+long ASNDerWriteMechList( unsigned char* pbData, SPNEGO_MECH_OID *mechOidLst, int mechOidCnt );
int ASNDerWriteElement( unsigned char* pbData, unsigned char ucElementSequence,
unsigned char ucType, unsigned char* pbTokenValue, long nLength );
diff --git a/usr/src/lib/libsmbfs/smb/llib-lsmbfs b/usr/src/lib/libsmbfs/smb/llib-lsmbfs
index e8e05e4272..1096482541 100644
--- a/usr/src/lib/libsmbfs/smb/llib-lsmbfs
+++ b/usr/src/lib/libsmbfs/smb/llib-lsmbfs
@@ -22,6 +22,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*LINTLIBRARY*/
@@ -34,4 +36,5 @@
#include <netsmb/smb_keychain.h>
#include <netsmb/smb_netshareenum.h>
#include <netsmb/smb_rap.h>
+#include <netsmb/spnego.h>
diff --git a/usr/src/lib/libsmbfs/smb/mapfile-vers b/usr/src/lib/libsmbfs/smb/mapfile-vers
index 1c2a5d6fa9..24bffec63d 100644
--- a/usr/src/lib/libsmbfs/smb/mapfile-vers
+++ b/usr/src/lib/libsmbfs/smb/mapfile-vers
@@ -18,8 +18,8 @@
# CDDL HEADER END
#
#
-# Copyright 2011 Nexenta Systems, Inc. All rights reserved.
# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
#
#
@@ -151,6 +151,20 @@ SYMBOL_VERSION SUNWprivate {
smbfs_set_default_user;
smbutil_std_opts;
+
+ spnegoCreateNegTokenHint;
+ spnegoCreateNegTokenInit;
+ spnegoCreateNegTokenTarg;
+ spnegoFreeData;
+ spnegoGetContextFlags;
+ spnegoGetMechListMIC;
+ spnegoGetMechToken;
+ spnegoGetNegotiationResult;
+ spnegoGetSupportedMechType;
+ spnegoGetTokenType;
+ spnegoInitFromBinary;
+ spnegoIsMechTypeAvailable;
+ spnegoTokenGetBinary;
local:
*;
};
diff --git a/usr/src/lib/libsmbfs/smb/spnego.c b/usr/src/lib/libsmbfs/smb/spnego.c
index 3e300cd606..a15303da30 100644
--- a/usr/src/lib/libsmbfs/smb/spnego.c
+++ b/usr/src/lib/libsmbfs/smb/spnego.c
@@ -1,3 +1,4 @@
+// Copyright 2012 Nexenta Systems, Inc. All rights reserved.
// Copyright (C) 2002 Microsoft Corporation
// All rights reserved.
//
@@ -21,10 +22,9 @@
//
/////////////////////////////////////////////////////////////
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include <memory.h>
#include "spnego.h"
#include "derparse.h"
@@ -89,6 +89,111 @@ int spnegoInitFromBinary( unsigned char* pbTokenData, unsigned long ulLength, SP
/////////////////////////////////////////////////////////////////////////////
//
// Function:
+// spnegoCreateNegTokenHint
+//
+// Parameters:
+// [in] pMechTypeList - List of MechTypes (OIDs) to include
+// [in] MechTypeCnt - Length of MechTypes array
+// [in] pbPrincipal - Principal name for MechListMIC
+// [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer
+//
+// Returns:
+// int Success - SPNEGO_E_SUCCESS
+// Failure - SPNEGO API Error code
+//
+// Comments :
+// Initializes a SPNEGO_TOKEN_HANDLE for a NegTokenInit type token
+// from the supplied parameters. The token created is the "hint"
+// used (for example) in the response to an SMB negotiate protocol.
+// Returned data structure must be freed by calling spnegoFreeData().
+//
+// The "hint" tells the client what authentication methods this
+// server supports (the ones in the MechTypeList). The Principal
+// name historically was the server's own SPN, but recent versions
+// of windows only supply: "not_defined_in_RFC4178@please_ignore"
+// So if you want to be nice to your clients, provide the host SPN,
+// otherwise provide the bogus SPN string like recent windows.
+//
+////////////////////////////////////////////////////////////////////////////
+
+int spnegoCreateNegTokenHint( SPNEGO_MECH_OID *pMechTypeList, int MechTypeCnt,
+ unsigned char *pbPrincipal, SPNEGO_TOKEN_HANDLE* phSpnegoToken )
+{
+ int nReturn;
+ long nTokenLength = 0L;
+ long nInternalTokenLength = 0L;
+ unsigned long ulPrincipalLen;
+ unsigned char* pbMechListMIC;
+ unsigned long ulMechListMICLen;
+ unsigned char* pbTokenData = NULL;
+ SPNEGO_TOKEN** ppSpnegoToken = (SPNEGO_TOKEN**) phSpnegoToken;
+
+ if ( NULL == ppSpnegoToken || NULL == pbPrincipal )
+ return (SPNEGO_E_INVALID_PARAMETER);
+
+ /*
+ * Get the actual token size
+ */
+ ulPrincipalLen = strlen((char *)pbPrincipal);
+ ulMechListMICLen = ASNDerCalcElementLength( ulPrincipalLen, NULL );
+ nReturn = CalculateMinSpnegoInitTokenSize(
+ 0, /* ulMechTokenLen */
+ ulMechListMICLen,
+ pMechTypeList,
+ MechTypeCnt,
+ 0, /* nReqFlagsAvailable */
+ &nTokenLength,
+ &nInternalTokenLength );
+ if ( nReturn != SPNEGO_E_SUCCESS )
+ return (nReturn);
+
+ // Allocate a buffer to hold the data.
+ pbTokenData = calloc( 1, nTokenLength );
+
+ if ( NULL == pbTokenData )
+ return ( SPNEGO_E_OUT_OF_MEMORY );
+
+ /*
+ * Construct the MechListMIC
+ */
+ pbMechListMIC = pbTokenData + (nTokenLength - ulMechListMICLen);
+ (void) ASNDerWriteElement( pbMechListMIC, SPNEGO_NEGINIT_ELEMENT_MECHTYPES,
+ GENERALSTR, pbPrincipal, ulPrincipalLen );
+
+ // Now write the token
+ nReturn = CreateSpnegoInitToken(
+ pMechTypeList,
+ MechTypeCnt,
+ 0, /* ContextFlags */
+ NULL, 0, /* MechToken, len */
+ pbMechListMIC,
+ ulMechListMICLen,
+ pbTokenData,
+ nTokenLength,
+ nInternalTokenLength );
+ if ( nReturn != SPNEGO_E_SUCCESS ) {
+ free( pbTokenData );
+ return (nReturn);
+ }
+
+ // This will copy our allocated pointer, and ensure that the sructure cleans
+ // up the data later
+ nReturn = InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYPTR,
+ SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA,
+ pbTokenData, nTokenLength, ppSpnegoToken );
+
+ // Cleanup on failure
+ if ( nReturn != SPNEGO_E_SUCCESS ) {
+ free( pbTokenData );
+ return (nReturn);
+ }
+
+ return (SPNEGO_E_SUCCESS);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Function:
// spnegoCreateNegTokenInit
//
// Parameters:
@@ -131,7 +236,7 @@ int spnegoCreateNegTokenInit( SPNEGO_MECH_OID MechType,
// Get the actual token size
if ( ( nReturn = CalculateMinSpnegoInitTokenSize( ulMechTokenLen, ulMechListMICLen,
- MechType, ( ucContextFlags != 0L ),
+ &MechType, 1, ( ucContextFlags != 0L ),
&nTokenLength, &nInternalTokenLength ) )
== SPNEGO_E_SUCCESS )
{
@@ -142,7 +247,7 @@ int spnegoCreateNegTokenInit( SPNEGO_MECH_OID MechType,
{
// Now write the token
- if ( ( nReturn = CreateSpnegoInitToken( MechType,
+ if ( ( nReturn = CreateSpnegoInitToken( &MechType, 1,
ucContextFlags, pbMechToken,
ulMechTokenLen, pbMechListMIC,
ulMechListMICLen, pbTokenData,
@@ -227,11 +332,7 @@ int spnegoCreateNegTokenTarg( SPNEGO_MECH_OID MechType,
spnego_mech_oid_NotUsed == MechType ) &&
( IsValidNegResult( spnegoNegResult ) ||
- spnego_negresult_NotUsed == spnegoNegResult ) &&
-
- !( !IsValidMechOid( MechType ) &&
- ( spnego_negresult_success == spnegoNegResult ||
- spnego_negresult_incomplete == spnegoNegResult ) ) )
+ spnego_negresult_NotUsed == spnegoNegResult ) )
{
// Get the actual token size
diff --git a/usr/src/lib/libsmbfs/smb/spnego.h b/usr/src/lib/libsmbfs/smb/spnego.h
deleted file mode 100644
index 9865fbd85d..0000000000
--- a/usr/src/lib/libsmbfs/smb/spnego.h
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright (C) 2002 Microsoft Corporation
-// All rights reserved.
-//
-// THIS CODE AND INFORMATION IS PROVIDED "AS IS"
-// WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-// OR IMPLIED, INCLUDING BUT NOT LIMITED
-// TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY
-// AND/OR FITNESS FOR A PARTICULAR PURPOSE.
-//
-// Date - 10/08/2002
-// Author - Sanj Surati
-
-/////////////////////////////////////////////////////////////
-//
-// SPNEGO.H
-//
-// SPNEGO Token Handler Header File
-//
-// Contains the definitions required to interpret and create
-// SPNEGO tokens so that Kerberos GSS tokens can be
-// Unpackaged/packaged.
-//
-/////////////////////////////////////////////////////////////
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifndef __SPNEGO_H__
-#define __SPNEGO_H__
-
-// C++ Specific
-#if defined(__cplusplus)
-extern "C"
-{
-#endif
-
-// Type Definitions
-
-//
-// Users of SPNEGO Token Handler API will request
-// these as well as free them,
-//
-typedef void* SPNEGO_TOKEN_HANDLE;
-
-//
-// Defines the element types that are found
-// in each of the tokens.
-//
-
-typedef enum spnego_element_type
-{
- spnego_element_min, // Lower bound
-
- // Init token elements
- spnego_init_mechtypes,
- spnego_init_reqFlags,
- spnego_init_mechToken,
- spnego_init_mechListMIC,
-
- // Targ token elements
- spnego_targ_negResult,
- spnego_targ_supportedMech,
- spnego_targ_responseToken,
- spnego_targ_mechListMIC,
-
- spnego_element_max // Upper bound
-
-} SPNEGO_ELEMENT_TYPE;
-
-//
-// Token Element Availability. Elements in both
-// token types are optional. Since there are only
-// 4 elements in each Token, we will allocate space
-// to hold the information, but we need a way to
-// indicate whether or not an element is available
-//
-
-#define SPNEGO_TOKEN_ELEMENT_UNAVAILABLE 0
-#define SPNEGO_TOKEN_ELEMENT_AVAILABLE 1
-
-//
-// Token type values. SPNEGO has 2 token types:
-// NegTokenInit and NegTokenTarg
-//
-
-#define SPNEGO_TOKEN_INIT 0
-#define SPNEGO_TOKEN_TARG 1
-
-//
-// GSS Mechanism OID enumeration. We only really handle
-// 3 different OIDs. These are stored in an array structure
-// defined in the parsing code.
-//
-
-typedef enum spnego_mech_oid
-{
- // Init token elements
- spnego_mech_oid_Kerberos_V5_Legacy, // Really V5, but OID off by 1 bit
- spnego_mech_oid_Kerberos_V5,
- spnego_mech_oid_Spnego,
- spnego_mech_oid_NTLMSSP,
- spnego_mech_oid_NotUsed = -1
-
-} SPNEGO_MECH_OID;
-
-//
-// Defines the negResult values.
-//
-
-typedef enum spnego_negResult
-{
- spnego_negresult_success,
- spnego_negresult_incomplete,
- spnego_negresult_rejected,
- spnego_negresult_NotUsed = -1
-} SPNEGO_NEGRESULT;
-
-//
-// Context Flags in NegTokenInit
-//
-
-//
-// ContextFlags values MUST be zero or a combination
-// of the below
-//
-
-#define SPNEGO_NEGINIT_CONTEXT_DELEG_FLAG 0x80
-#define SPNEGO_NEGINIT_CONTEXT_MUTUAL_FLAG 0x40
-#define SPNEGO_NEGINIT_CONTEXT_REPLAY_FLAG 0x20
-#define SPNEGO_NEGINIT_CONTEXT_SEQUENCE_FLAG 0x10
-#define SPNEGO_NEGINIT_CONTEXT_ANON_FLAG 0x8
-#define SPNEGO_NEGINIT_CONTEXT_CONF_FLAG 0x4
-#define SPNEGO_NEGINIT_CONTEXT_INTEG_FLAG 0x2
-
-//
-// Mask to retrieve valid values.
-//
-
-#define SPNEGO_NEGINIT_CONTEXT_MASK 0xFE // Logical combination of above flags
-
-//
-// SPNEGO API return codes.
-//
-
-// API function was successful
-#define SPNEGO_E_SUCCESS 0
-
-// The supplied Token was invalid
-#define SPNEGO_E_INVALID_TOKEN -1
-
-// An invalid length was encountered
-#define SPNEGO_E_INVALID_LENGTH -2
-
-// The Token Parse failed
-#define SPNEGO_E_PARSE_FAILED -3
-
-// The requested value was not found
-#define SPNEGO_E_NOT_FOUND -4
-
-// The requested element is not available
-#define SPNEGO_E_ELEMENT_UNAVAILABLE -5
-
-// Out of Memory
-#define SPNEGO_E_OUT_OF_MEMORY -6
-
-// Not Implemented
-#define SPNEGO_E_NOT_IMPLEMENTED -7
-
-// Invalid Parameter
-#define SPNEGO_E_INVALID_PARAMETER -8
-
-// Token Handler encountered an unexpected OID
-#define SPNEGO_E_UNEXPECTED_OID -9
-
-// The requested token was not found
-#define SPNEGO_E_TOKEN_NOT_FOUND -10
-
-// An unexpected type was encountered in the encoding
-#define SPNEGO_E_UNEXPECTED_TYPE -11
-
-// The buffer was too small
-#define SPNEGO_E_BUFFER_TOO_SMALL -12
-
-// A Token Element was invalid (e.g. improper length or value)
-#define SPNEGO_E_INVALID_ELEMENT -13
-
-/* Miscelaneous API Functions */
-
-// Frees opaque data
-void spnegoFreeData( SPNEGO_TOKEN_HANDLE hSpnegoToken );
-
-// Initializes SPNEGO_TOKEN structure from DER encoded binary data
-int spnegoInitFromBinary( unsigned char* pbTokenData, unsigned long ulLength, SPNEGO_TOKEN_HANDLE* phSpnegoToken );
-
-// Initializes SPNEGO_TOKEN structure for a NegTokenInit type using the
-// supplied parameters
-int spnegoCreateNegTokenInit( SPNEGO_MECH_OID MechType,
- unsigned char ucContextFlags, unsigned char* pbMechToken,
- unsigned long ulMechTokenLen, unsigned char* pbMechTokenMIC,
- unsigned long ulMechTokenMIC, SPNEGO_TOKEN_HANDLE* phSpnegoToken );
-
-// Initializes SPNEGO_TOKEN structure for a NegTokenTarg type using the
-// supplied parameters
-int spnegoCreateNegTokenTarg( SPNEGO_MECH_OID MechType,
- SPNEGO_NEGRESULT spnegoNegResult, unsigned char* pbMechToken,
- unsigned long ulMechTokenLen, unsigned char* pbMechListMIC,
- unsigned long ulMechListMICLen, SPNEGO_TOKEN_HANDLE* phSpnegoToken );
-
-// Copies binary representation of SPNEGO Data into user supplied buffer
-int spnegoTokenGetBinary( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pbTokenData,
- unsigned long * pulDataLen );
-
-// Returns SPNEGO Token Type
-int spnegoGetTokenType( SPNEGO_TOKEN_HANDLE hSpnegoToken, int * piTokenType );
-
-/* Reading an Init Token */
-
-// Returns the Initial Mech Type in the MechList element in the NegInitToken.
-int spnegoIsMechTypeAvailable( SPNEGO_TOKEN_HANDLE hSpnegoToken, SPNEGO_MECH_OID MechOID, int * piMechTypeIndex );
-
-// Returns the value from the context flags element in the NegInitToken as an unsigned long
-int spnegoGetContextFlags( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pucContextFlags );
-
-/* Reading a Response Token */
-
-// Returns the value from the negResult element (Status code of GSS call - 0,1,2)
-int spnegoGetNegotiationResult( SPNEGO_TOKEN_HANDLE hSpnegoToken, SPNEGO_NEGRESULT* pnegResult );
-
-// Returns the Supported Mech Type from the NegTokenTarg.
-int spnegoGetSupportedMechType( SPNEGO_TOKEN_HANDLE hSpnegoToken, SPNEGO_MECH_OID* pMechOID );
-
-/* Reading either Token Type */
-
-// Returns the actual Mechanism data from the token (this is what is passed into GSS-API functions
-int spnegoGetMechToken( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pbTokenData, unsigned long* pulDataLen );
-
-// Returns the Message Integrity BLOB in the token
-int spnegoGetMechListMIC( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pbMICData, unsigned long* pulDataLen );
-
-// C++ Specific
-#if defined(__cplusplus)
-}
-#endif
-
-#endif
diff --git a/usr/src/lib/libsmbfs/smb/spnegoparse.c b/usr/src/lib/libsmbfs/smb/spnegoparse.c
index e9f1e2781b..ea5fb03a70 100644
--- a/usr/src/lib/libsmbfs/smb/spnegoparse.c
+++ b/usr/src/lib/libsmbfs/smb/spnegoparse.c
@@ -1,3 +1,4 @@
+// Copyright 2012 Nexenta Systems, Inc. All rights reserved.
// Copyright (C) 2002 Microsoft Corporation
// All rights reserved.
//
@@ -54,6 +55,7 @@ extern MECH_OID g_stcMechOIDList [];
// Parameters:
// [in] nMechTokenLength - Length of the MechToken Element
// [in] nMechListMICLength - Length of the MechListMIC Element
+// (or negHints, if no MechToken)
// [in] mechOID - OID for MechList
// [in] nReqFlagsAvailable - Is ContextFlags element available
// [out] pnTokenSize - Filled out with total size of token
@@ -75,7 +77,7 @@ extern MECH_OID g_stcMechOIDList [];
////////////////////////////////////////////////////////////////////////////
int CalculateMinSpnegoInitTokenSize( long nMechTokenLength,
- long nMechListMICLength, SPNEGO_MECH_OID mechOid,
+ long nMechListMICLength, SPNEGO_MECH_OID *mechOidLst, int mechOidCnt,
int nReqFlagsAvailable, long* pnTokenSize,
long* pnInternalTokenLength )
{
@@ -87,7 +89,7 @@ int CalculateMinSpnegoInitTokenSize( long nMechTokenLength,
// We will calculate this by walking the token backwards
- // Start with MIC Element
+ // Start with MIC Element (or negHints)
if ( nMechListMICLength > 0L )
{
nTempLength = ASNDerCalcElementLength( nMechListMICLength, NULL );
@@ -130,7 +132,7 @@ int CalculateMinSpnegoInitTokenSize( long nMechTokenLength,
}
// Next is the MechList - This is REQUIRED
- nTempLength += ASNDerCalcMechListLength( mechOid, NULL );
+ nTempLength += ASNDerCalcMechListLength( mechOidLst, mechOidCnt, NULL );
// Check for rollover error
if ( nTempLength < nTotalLength )
@@ -205,11 +207,12 @@ xEndTokenInitLength:
// CreateSpnegoInitToken
//
// Parameters:
-// [in] MechType - OID in MechList
+// [in] pMechTypeList - OID array
+// [in] MechTypeCnt - OID array length
// [in] ucContextFlags - ContextFlags value
// [in] pbMechToken - Mech Token Binary Data
// [in] ulMechTokenLen - Length of Mech Token
-// [in] pbMechListMIC - MechListMIC Binary Data
+// [in] pbMechListMIC - MechListMIC Binary Data (or negHints)
// [in] ulMechListMICn - Length of MechListMIC
// [out] pbTokenData - Buffer to write token into.
// [in] nTokenLength - Length of pbTokenData buffer
@@ -227,9 +230,18 @@ xEndTokenInitLength:
// backwards, so we always know how many bytes we will potentially be
// writing out.
//
+// This function is also used to create an SPNEGO "hint", as described in
+// [MS-SPNG] sec. 2.2.1 negTokenInit2. The "hint" looks almost identical
+// to a NegTokenInit, but has a "negHints" field inserted before the MIC.
+// A normal SPNEGO negTokenInit2 contains only the mech list and the
+// negHints. To avoid a giant copy/paste of this function, we pass the
+// negHints as the MIC arg, and pass NULL as the MechToken to indicate
+// that we're creating a Hint rather than an Init, and use the correct
+// type when writing out the MIC (or negHints) element.
+//
////////////////////////////////////////////////////////////////////////////
-int CreateSpnegoInitToken( SPNEGO_MECH_OID MechType,
+int CreateSpnegoInitToken( SPNEGO_MECH_OID *pMechTypeList, long MechTypeCnt,
unsigned char ucContextFlags, unsigned char* pbMechToken,
unsigned long ulMechTokenLen, unsigned char* pbMechListMIC,
unsigned long ulMechListMICLen, unsigned char* pbTokenData,
@@ -251,17 +263,22 @@ int CreateSpnegoInitToken( SPNEGO_MECH_OID MechType,
// We will write the token out backwards to properly handle the cases
// where the length bytes become adjustable
- // Start with MIC Element
+ // Start with MIC Element (or negHints)
if ( ulMechListMICLen > 0L )
{
+ unsigned char ucType;
nTempLength = ASNDerCalcElementLength( ulMechListMICLen, &nInternalLength );
- // Decrease the pbWriteTokenData, now we know the length and
- // write it out.
+ // Decrease the pbWriteTokenData, now we know the length and write it out.
+ // Note: When MechTokenLen == 0, we're writing a negTokenInit2 and the
+ // MIC arg is really negHints, written as a constructed sequence.
+ // Otherwise we're writing a negTokenInit, and the MIC is an OCTETSTRING.
+ ucType = (ulMechTokenLen == 0) ?
+ SPNEGO_CONSTRUCTED_SEQUENCE : OCTETSTRING;
pbWriteTokenData -= nTempLength;
nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGINIT_ELEMENT_MECHLISTMIC,
- OCTETSTRING, pbMechListMIC, ulMechListMICLen );
+ ucType, pbMechListMIC, ulMechListMICLen );
// Adjust Values and sanity check
nTotalBytesWritten += nTempLength;
@@ -325,12 +342,12 @@ int CreateSpnegoInitToken( SPNEGO_MECH_OID MechType,
} // IF ContextFlags
// Next is the MechList - This is REQUIRED
- nTempLength = ASNDerCalcMechListLength( MechType, &nInternalLength );
+ nTempLength = ASNDerCalcMechListLength( pMechTypeList, MechTypeCnt, &nInternalLength );
// Decrease the pbWriteTokenData, now we know the length and
// write it out.
pbWriteTokenData -= nTempLength;
- nTempLength = ASNDerWriteMechList( pbWriteTokenData, MechType );
+ nTempLength = ASNDerWriteMechList( pbWriteTokenData, pMechTypeList, MechTypeCnt );
// Adjust Values and sanity check
nTotalBytesWritten += nTempLength;
@@ -1281,8 +1298,6 @@ int InitSpnegoTokenElements( SPNEGO_TOKEN* pSpnegoToken, unsigned char* pbTokenD
long nElementLength = 0L;
long nActualTokenLength = 0L;
unsigned char* pbElements = NULL;
- unsigned char * ptok;
- long tlen, elen, len;
// Point to the correct array
switch( pSpnegoToken->ucTokenType )
@@ -1370,37 +1385,32 @@ int InitSpnegoTokenElements( SPNEGO_TOKEN* pSpnegoToken, unsigned char* pbTokenD
nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength,
OCTETSTRING, spnego_init_mechToken,
&pSpnegoToken->aElementArray[nCtr] );
- }
+ }
break;
- case SPNEGO_NEGINIT_ELEMENT_MECHLISTMIC:
+ case SPNEGO_NEGINIT_ELEMENT_MECHLISTMIC: // xA3
{
//
- // This is an OCTETSTRING which contains a message integrity BLOB.
+ // Don't yet know if this is a negTokenInit, or negTokenInit2.
+ // Unfortunately, both have the same type: SPNEGO_TOKEN_INIT
+ // If it's negTokenInit, this element should be an OCTETSTRING
+ // containing the MIC. If it's a negTokenInit2, this element
+ // should be an SPNEGO_CONSTRUCTED_SEQUENCE containing the
+ // negHints (GENERALSTR, ignored)
//
nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength,
- OCTETSTRING, spnego_init_mechListMIC,
- &pSpnegoToken->aElementArray[nCtr] );
- /*
- * don't believe everything you read in RFCs (and MS
- * sample code)... win2k is sending not an octet string,
- * but a "general string", wrapped in a sequence.
- */
- if (nReturn != SPNEGO_E_UNEXPECTED_TYPE)
- break;
- ptok = pbTokenData;
- elen = nElementLength;
- if ((nReturn = ASNDerCheckToken(ptok, SPNEGO_CONSTRUCTED_SEQUENCE, elen, elen, &len, &tlen)) != SPNEGO_E_SUCCESS)
- break;
- elen -= tlen;
- ptok += tlen;
-
- if ((nReturn = ASNDerCheckToken(ptok, SEQ_ELM(0), elen, elen, &len, &tlen)) != SPNEGO_E_SUCCESS)
- break;
- elen -= tlen;
- ptok += tlen;
- nReturn = InitSpnegoTokenElementFromBasicType(ptok, elen, GENERALSTR, spnego_init_mechListMIC, &pSpnegoToken->aElementArray[nCtr]);
+ OCTETSTRING, spnego_init_mechListMIC,
+ &pSpnegoToken->aElementArray[nCtr] );
+
+ if (nReturn == SPNEGO_E_UNEXPECTED_TYPE) {
+ // This is really a negHints element. Check the type and length,
+ // but otherwise just ignore it.
+ long elen, tlen;
+ nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_CONSTRUCTED_SEQUENCE,
+ nElementLength, nElementLength,
+ &elen, &tlen );
+ }
}
break;
@@ -1408,6 +1418,7 @@ int InitSpnegoTokenElements( SPNEGO_TOKEN* pSpnegoToken, unsigned char* pbTokenD
}
else
{
+ /* pSpnegoToken->ucTokenType == SPNEGO_TOKEN_TARG */
switch( pbElements[nCtr] )
{
@@ -1453,12 +1464,13 @@ int InitSpnegoTokenElements( SPNEGO_TOKEN* pSpnegoToken, unsigned char* pbTokenD
case SPNEGO_NEGTARG_ELEMENT_MECHLISTMIC:
{
//
- // This is an OCTETSTRING which specifies a message integrity BLOB.
+ // This is an OCTETSTRING, typically 16 bytes,
+ // which contains a message integrity BLOB.
//
nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength,
- OCTETSTRING, spnego_targ_mechListMIC,
- &pSpnegoToken->aElementArray[nCtr] );
+ OCTETSTRING, spnego_targ_mechListMIC,
+ &pSpnegoToken->aElementArray[nCtr] );
}
break;
diff --git a/usr/src/lib/libsmbfs/smb/spnegoparse.h b/usr/src/lib/libsmbfs/smb/spnegoparse.h
index b874dc453d..1f7fde7486 100644
--- a/usr/src/lib/libsmbfs/smb/spnegoparse.h
+++ b/usr/src/lib/libsmbfs/smb/spnegoparse.h
@@ -1,3 +1,4 @@
+// Copyright 2012 Nexenta Systems, Inc. All rights reserved.
// Copyright (C) 2002 Microsoft Corporation
// All rights reserved.
//
@@ -21,8 +22,6 @@
//
/////////////////////////////////////////////////////////////
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifndef __SPNEGOPARSE_H__
#define __SPNEGOPARSE_H__
@@ -136,13 +135,13 @@ int FindMechOIDInMechList( SPNEGO_ELEMENT* pSpnegoElement, SPNEGO_MECH_OID MechO
int * piMechTypeIndex );
int ValidateMechList( unsigned char* pbMechListData, long nBoundaryLength );
int CalculateMinSpnegoInitTokenSize( long nMechTokenLength, long nMechListMICLength,
- SPNEGO_MECH_OID mechOid, int nReqFlagsAvailable,
+ SPNEGO_MECH_OID *mechOid, int mechOidCnt, int nReqFlagsAvailable,
long* plTokenSize, long* plInternalLength );
int CalculateMinSpnegoTargTokenSize( SPNEGO_MECH_OID MechType, SPNEGO_NEGRESULT spnegoNegResult,
long nMechTokenLen,
long nMechTokenMIC, long* pnTokenSize,
long* pnInternalTokenLength );
-int CreateSpnegoInitToken( SPNEGO_MECH_OID MechType,
+int CreateSpnegoInitToken( SPNEGO_MECH_OID *MechTypeList, long nMechTypes,
unsigned char ucContextFlags, unsigned char* pbMechToken,
unsigned long ulMechTokenLen, unsigned char* pbMechListMIC,
unsigned long ulMechListMICLen, unsigned char* pbTokenData,
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com b/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com
index d40fa8d629..20c8f74f77 100644
--- a/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com
+++ b/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com
@@ -51,6 +51,7 @@ OBJS_LOCAL = \
OBJS_FS_SMBSRV = \
smb_acl.o \
smb_alloc.o \
+ smb_authenticate.o \
smb_close.o \
smb_common_open.o \
smb_common_transact.o \
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h
index 881535d2f3..685a760e16 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h
+++ b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h
@@ -70,6 +70,10 @@ extern void mlsvc_fini(void);
extern DWORD mlsvc_netlogon(char *, char *);
extern DWORD mlsvc_join(smb_domainex_t *, char *, char *);
+extern void smb_logon_domain(smb_logon_t *, smb_token_t *);
+extern uint32_t smb_decode_krb5_pac(smb_token_t *, char *, uint_t);
+extern boolean_t smb_token_setup_common(smb_token_t *);
+
/*
* The maximum number of domains (NT limit).
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers
index 29af98f2ac..eece54e174 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers
@@ -20,6 +20,7 @@
#
#
# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
#
#
@@ -53,6 +54,7 @@ SYMBOL_VERSION SUNWprivate {
mlsvc_netlogon;
smb_autohome_add;
smb_autohome_remove;
+ smb_decode_krb5_pac;
smb_locate_dc;
smb_logon;
smb_logon_abort;
@@ -76,6 +78,7 @@ SYMBOL_VERSION SUNWprivate {
smb_shr_stop;
smb_token_destroy;
smb_token_log;
+ smb_token_setup_common;
spoolss_register_copyfile;
local:
*;
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c
index 566837fe2d..a3fbb4d96f 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -61,6 +61,8 @@ static void netr_setup_identity(ndr_heap_t *, smb_logon_t *,
static boolean_t netr_isadmin(struct netr_validation_info3 *);
static uint32_t netr_setup_domain_groups(struct netr_validation_info3 *,
smb_ids_t *);
+static uint32_t netr_setup_token_info3(struct netr_validation_info3 *,
+ smb_token_t *);
static uint32_t netr_setup_token_wingrps(struct netr_validation_info3 *,
smb_token_t *);
@@ -75,6 +77,83 @@ static boolean_t netlogon_busy = B_FALSE;
static boolean_t netlogon_abort = B_FALSE;
/*
+ * Helper for Kerberos authentication
+ */
+uint32_t
+smb_decode_krb5_pac(smb_token_t *token, char *data, uint_t len)
+{
+ struct krb5_validation_info info;
+ ndr_buf_t *nbuf;
+ uint32_t status = NT_STATUS_NO_MEMORY;
+ int rc;
+
+ bzero(&info, sizeof (info));
+
+ /* Need to keep this until we're done with &info */
+ nbuf = ndr_buf_init(&TYPEINFO(netr_interface));
+ if (nbuf == NULL)
+ goto out;
+
+ rc = ndr_buf_decode(nbuf, NDR_PTYPE_PAC,
+ NETR_OPNUM_decode_krb5_pac, data, len, &info);
+ if (rc != NDR_DRC_OK) {
+ status = RPC_NT_PROTOCOL_ERROR;
+ goto out;
+ }
+
+ status = netr_setup_token_info3(&info.info3, token);
+
+ /* Deal with the "resource groups"? */
+
+
+out:
+ if (nbuf != NULL)
+ ndr_buf_fini(nbuf);
+
+ return (status);
+}
+
+/*
+ * Code factored out of netr_setup_token()
+ */
+static uint32_t
+netr_setup_token_info3(struct netr_validation_info3 *info3,
+ smb_token_t *token)
+{
+ smb_sid_t *domsid;
+
+ domsid = (smb_sid_t *)info3->LogonDomainId;
+
+ token->tkn_user.i_sid = smb_sid_splice(domsid,
+ info3->UserId);
+ if (token->tkn_user.i_sid == NULL)
+ goto errout;
+
+ token->tkn_primary_grp.i_sid = smb_sid_splice(domsid,
+ info3->PrimaryGroupId);
+ if (token->tkn_primary_grp.i_sid == NULL)
+ goto errout;
+
+ if (info3->EffectiveName.str) {
+ token->tkn_account_name =
+ strdup((char *)info3->EffectiveName.str);
+ if (token->tkn_account_name == NULL)
+ goto errout;
+ }
+
+ if (info3->LogonDomainName.str) {
+ token->tkn_domain_name =
+ strdup((char *)info3->LogonDomainName.str);
+ if (token->tkn_domain_name == NULL)
+ goto errout;
+ }
+
+ return (netr_setup_token_wingrps(info3, token));
+errout:
+ return (NT_STATUS_INSUFF_SERVER_RESOURCES);
+}
+
+/*
* Abort impending domain logon requests.
*/
void
@@ -254,13 +333,14 @@ netr_setup_token(struct netr_validation_info3 *info3, smb_logon_t *user_info,
* exclusively ored with the 16 byte UserSessionKey to recover
* the the clear form.
*/
- if ((token->tkn_session_key = malloc(SMBAUTH_SESSION_KEY_SZ)) == NULL)
+ if ((token->tkn_ssnkey.val = malloc(SMBAUTH_SESSION_KEY_SZ)) == NULL)
return (NT_STATUS_NO_MEMORY);
+ token->tkn_ssnkey.len = SMBAUTH_SESSION_KEY_SZ;
bzero(rc4key, SMBAUTH_SESSION_KEY_SZ);
bcopy(netr_info->session_key.key, rc4key, netr_info->session_key.len);
- bcopy(info3->UserSessionKey.data, token->tkn_session_key,
+ bcopy(info3->UserSessionKey.data, token->tkn_ssnkey.val,
SMBAUTH_SESSION_KEY_SZ);
- rand_hash((unsigned char *)token->tkn_session_key,
+ rand_hash((unsigned char *)token->tkn_ssnkey.val,
SMBAUTH_SESSION_KEY_SZ, rc4key, SMBAUTH_SESSION_KEY_SZ);
return (NT_STATUS_SUCCESS);
@@ -603,7 +683,14 @@ netr_setup_identity(ndr_heap_t *heap, smb_logon_t *user_info,
(void) mutex_unlock(&logon_id_mutex);
- identity->parameter_control = 0;
+ /*
+ * [MS-APDS] 3.1.5.2 "NTLM Network Logon" says to set
+ * ParameterControl to the 'E' + 'K' bits. Those are:
+ * (1 << 5) | (1 << 11), a.k.a
+ */
+ identity->parameter_control =
+ MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
+ MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
identity->logon_id.LowPart = logon_id;
identity->logon_id.HighPart = 0;
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c
index 8ffc4f6f28..c9e634f515 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/param.h>
@@ -82,6 +83,9 @@ smb_autohome_add(const smb_token_t *token)
uid_t uid;
gid_t gid;
+ if (token->tkn_flags & SMB_ATF_ANON)
+ return;
+
uid = token->tkn_user.i_id;
gid = token->tkn_primary_grp.i_id;
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c
index 4b7a1cd178..24baa848e7 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
#include <unistd.h>
@@ -44,7 +45,6 @@ static rwlock_t smb_logoninit_rwl;
typedef void (*smb_logonop_t)(smb_logon_t *, smb_token_t *);
-extern void smb_logon_domain(smb_logon_t *, smb_token_t *);
static void smb_logon_local(smb_logon_t *, smb_token_t *);
static void smb_logon_guest(smb_logon_t *, smb_token_t *);
static void smb_logon_anon(smb_logon_t *, smb_token_t *);
@@ -158,8 +158,8 @@ smb_token_sids2ids(smb_token_t *token)
}
stat = smb_idmap_batch_getmappings(&sib);
- smb_idmap_batch_destroy(&sib);
smb_idmap_check("smb_idmap_batch_getmappings", stat);
+ smb_idmap_batch_destroy(&sib);
return (stat == IDMAP_SUCCESS ? 0 : -1);
}
@@ -253,7 +253,7 @@ smb_token_destroy(smb_token_t *token)
free(token->tkn_posix_grps);
free(token->tkn_account_name);
free(token->tkn_domain_name);
- free(token->tkn_session_key);
+ free(token->tkn_ssnkey.val);
bzero(token, sizeof (smb_token_t));
free(token);
}
@@ -344,8 +344,10 @@ smb_token_set_flags(smb_token_t *token)
* has been done.
*
* Note that the order of calls in this function are important.
+ *
+ * Returns B_TRUE for success.
*/
-static boolean_t
+boolean_t
smb_token_setup_common(smb_token_t *token)
{
smb_token_set_flags(token);
@@ -475,7 +477,6 @@ smb_logon_local(smb_logon_t *user_info, smb_token_t *token)
char guest[SMB_USERNAME_MAXLEN];
smb_passwd_t smbpw;
uint32_t status;
- boolean_t isguest;
if (user_info->lg_secmode == SMB_SECMODE_DOMAIN) {
if ((user_info->lg_domain_type != SMB_DOMAIN_LOCAL) &&
@@ -483,16 +484,18 @@ smb_logon_local(smb_logon_t *user_info, smb_token_t *token)
return;
}
+ /*
+ * If the requested account name is "guest" (or whatever
+ * our guest account is named) then don't handle it here.
+ * Let this request fall through to smb_logon_guest().
+ */
smb_guest_account(guest, SMB_USERNAME_MAXLEN);
- isguest = (smb_strcasecmp(guest, user_info->lg_e_username, 0) == 0);
+ if (smb_strcasecmp(guest, user_info->lg_e_username, 0) == 0)
+ return;
status = smb_token_auth_local(user_info, token, &smbpw);
- if (status == NT_STATUS_SUCCESS) {
- if (isguest)
- status = smb_token_setup_guest(user_info, token);
- else
- status = smb_token_setup_local(&smbpw, token);
- }
+ if (status == NT_STATUS_SUCCESS)
+ status = smb_token_setup_local(&smbpw, token);
user_info->lg_status = status;
}
@@ -514,23 +517,31 @@ smb_logon_guest(smb_logon_t *user_info, smb_token_t *token)
char guest[SMB_USERNAME_MAXLEN];
smb_passwd_t smbpw;
char *temp;
- uint32_t status;
if (user_info->lg_status != NT_STATUS_NO_SUCH_USER)
return;
+ /* Get the name of the guest account. */
smb_guest_account(guest, SMB_USERNAME_MAXLEN);
- temp = user_info->lg_e_username;
- user_info->lg_e_username = guest;
- status = smb_token_auth_local(user_info, token, &smbpw);
- if ((status == NT_STATUS_SUCCESS) ||
- (status == NT_STATUS_NO_SUCH_USER)) {
- status = smb_token_setup_guest(user_info, token);
- }
+ /* Does the guest account exist? */
+ if (smb_pwd_getpwnam(guest, &smbpw) == NULL)
+ return;
+ /* Is it enabled? (empty p/w is OK) */
+ if (smbpw.pw_flags & SMB_PWF_DISABLE)
+ return;
+
+ /*
+ * OK, give the client a guest logon. Note that on entry,
+ * lg_e_username is typically something other than "guest"
+ * so we need to set the effective username when createing
+ * the guest token.
+ */
+ temp = user_info->lg_e_username;
+ user_info->lg_e_username = guest;
+ user_info->lg_status = smb_token_setup_guest(user_info, token);
user_info->lg_e_username = temp;
- user_info->lg_status = status;
}
/*
@@ -552,7 +563,7 @@ static uint32_t
smb_token_auth_local(smb_logon_t *user_info, smb_token_t *token,
smb_passwd_t *smbpw)
{
- boolean_t lm_ok, nt_ok;
+ boolean_t ok;
uint32_t status = NT_STATUS_SUCCESS;
if (smb_pwd_getpwnam(user_info->lg_e_username, smbpw) == NULL)
@@ -561,41 +572,42 @@ smb_token_auth_local(smb_logon_t *user_info, smb_token_t *token,
if (smbpw->pw_flags & SMB_PWF_DISABLE)
return (NT_STATUS_ACCOUNT_DISABLED);
- nt_ok = lm_ok = B_FALSE;
- if ((smbpw->pw_flags & SMB_PWF_LM) &&
- (user_info->lg_lm_password.len != 0)) {
- lm_ok = smb_auth_validate_lm(
- user_info->lg_challenge_key.val,
- user_info->lg_challenge_key.len,
- smbpw,
- user_info->lg_lm_password.val,
- user_info->lg_lm_password.len,
- user_info->lg_domain,
- user_info->lg_username);
- token->tkn_session_key = NULL;
- }
-
- if (!lm_ok && (user_info->lg_nt_password.len != 0)) {
- token->tkn_session_key = malloc(SMBAUTH_SESSION_KEY_SZ);
- if (token->tkn_session_key == NULL)
- return (NT_STATUS_NO_MEMORY);
- nt_ok = smb_auth_validate_nt(
- user_info->lg_challenge_key.val,
- user_info->lg_challenge_key.len,
- smbpw,
- user_info->lg_nt_password.val,
- user_info->lg_nt_password.len,
- user_info->lg_domain,
- user_info->lg_username,
- (uchar_t *)token->tkn_session_key);
+ if ((smbpw->pw_flags & (SMB_PWF_LM | SMB_PWF_NT)) == 0) {
+ /*
+ * The SMB passwords have not been set.
+ * Return an error that suggests the
+ * password needs to be set.
+ */
+ return (NT_STATUS_PASSWORD_EXPIRED);
}
- if (!nt_ok && !lm_ok) {
- status = NT_STATUS_WRONG_PASSWORD;
- syslog(LOG_NOTICE, "logon[%s\\%s]: %s",
- user_info->lg_e_domain, user_info->lg_e_username,
- xlate_nt_status(status));
- }
+ token->tkn_ssnkey.val = malloc(SMBAUTH_SESSION_KEY_SZ);
+ if (token->tkn_ssnkey.val == NULL)
+ return (NT_STATUS_NO_MEMORY);
+ token->tkn_ssnkey.len = SMBAUTH_SESSION_KEY_SZ;
+
+ ok = smb_auth_validate(
+ smbpw,
+ user_info->lg_domain,
+ user_info->lg_username,
+ user_info->lg_challenge_key.val,
+ user_info->lg_challenge_key.len,
+ user_info->lg_nt_password.val,
+ user_info->lg_nt_password.len,
+ user_info->lg_lm_password.val,
+ user_info->lg_lm_password.len,
+ token->tkn_ssnkey.val);
+ if (ok)
+ return (NT_STATUS_SUCCESS);
+
+ free(token->tkn_ssnkey.val);
+ token->tkn_ssnkey.val = NULL;
+ token->tkn_ssnkey.len = 0;
+
+ status = NT_STATUS_WRONG_PASSWORD;
+ syslog(LOG_NOTICE, "logon[%s\\%s]: %s",
+ user_info->lg_e_domain, user_info->lg_e_username,
+ xlate_nt_status(status));
return (status);
}
diff --git a/usr/src/lib/smbsrv/libsmb/Makefile.com b/usr/src/lib/smbsrv/libsmb/Makefile.com
index 0c972a66f0..78dc4fdcfa 100644
--- a/usr/src/lib/smbsrv/libsmb/Makefile.com
+++ b/usr/src/lib/smbsrv/libsmb/Makefile.com
@@ -54,7 +54,6 @@ OBJS_COMMON = \
smb_info.o \
smb_kmod.o \
smb_lgrp.o \
- smb_mac.o \
smb_nic.o \
smb_pwdutil.o \
smb_privilege.o \
@@ -73,14 +72,16 @@ include ../../../Makefile.lib
include ../../Makefile.lib
INCS += -I$(SRC)/common/smbsrv
+INCS += -I$(SRC)/lib/libsmbfs/smb
LINTCHECKFLAGS += -erroff=E_INCONS_ARG_DECL2
LINTCHECKFLAGS += -erroff=E_BAD_FORMAT_STR2
LDLIBS += $(MACH_LDLIBS)
+# perfer to keep libs ordered by dependence
LDLIBS += -lscf -lmd -luuid -lpkcs11 -lcryptoutil
-LDLIBS += -lsec -lidmap -lnsl -lsocket -lresolv
-LDLIBS += -lreparse -lnvpair -lcmdutils -lavl -lc
+LDLIBS += -lsec -lidmap -lreparse -lcmdutils -lavl
+LDLIBS += -lnvpair -lresolv -lsocket -lnsl -lc
CPPFLAGS += $(INCS) -D_REENTRANT
CPPFLAGS += -Dsyslog=smb_syslog
CERRWARN += -_gcc=-Wno-uninitialized
diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h
index 7c5f88976a..82bbe995c3 100644
--- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h
+++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _LIBSMB_H
@@ -139,6 +139,7 @@ typedef enum {
SMB_CI_DYNDNS_ENABLE,
SMB_CI_MACHINE_PASSWD,
+ SMB_CI_MACHINE_UUID,
SMB_CI_KPASSWD_SRV,
SMB_CI_KPASSWD_DOMAIN,
SMB_CI_KPASSWD_SEQNUM,
@@ -193,6 +194,7 @@ extern boolean_t smb_config_get_ads_enable(void);
extern int smb_config_get_debug(void);
extern uint8_t smb_config_get_fg_flag(void);
extern char *smb_config_get_localsid(void);
+extern int smb_config_get_localuuid(uuid_t);
extern int smb_config_secmode_fromstr(char *);
extern char *smb_config_secmode_tostr(int);
extern int smb_config_get_secmode(void);
@@ -202,7 +204,7 @@ extern int smb_config_refresh_idmap(void);
extern int smb_config_getip(smb_cfg_id_t, smb_inaddr_t *);
extern void smb_config_get_version(smb_version_t *);
uint32_t smb_config_get_execinfo(char *, char *, size_t);
-
+extern void smb_config_get_negtok(uchar_t *, uint32_t *);
extern void smb_load_kconfig(smb_kmod_cfg_t *kcfg);
extern uint32_t smb_crc_gen(uint8_t *, size_t);
@@ -303,7 +305,7 @@ void libsmb_redirect_syslog(__FILE_TAG *fp, int priority);
#define SMBAUTH_HASH_SZ 16 /* also LM/NTLM/NTLMv2 Hash size */
#define SMBAUTH_LM_RESP_SZ 24 /* also NTLM Response size */
#define SMBAUTH_LM_PWD_SZ 14 /* LM password size */
-#define SMBAUTH_V2_CLNT_CHALLENGE_SZ 8 /* both LMv2 and NTLMv2 */
+#define SMBAUTH_CHAL_SZ 8 /* both LMv2 and NTLMv2 */
#define SMBAUTH_SESSION_KEY_SZ SMBAUTH_HASH_SZ
#define SMBAUTH_HEXHASH_SZ (SMBAUTH_HASH_SZ * 2)
@@ -364,7 +366,7 @@ typedef struct smb_auth_data_blob {
unsigned char ndb_signature[4];
unsigned char ndb_reserved[4];
uint64_t ndb_timestamp;
- unsigned char ndb_clnt_challenge[SMBAUTH_V2_CLNT_CHALLENGE_SZ];
+ unsigned char ndb_clnt_challenge[SMBAUTH_CHAL_SZ];
unsigned char ndb_unknown[4];
smb_auth_name_entry_t ndb_names[2];
unsigned char ndb_unknown2[4];
@@ -488,6 +490,9 @@ extern int smb_auth_RC4(unsigned char *, int, unsigned char *, int,
extern int smb_auth_md4(unsigned char *, unsigned char *, int);
extern int smb_auth_lm_hash(const char *, unsigned char *);
extern int smb_auth_ntlm_hash(const char *, unsigned char *);
+extern void smb_auth_ntlm2_mkchallenge(char *, const char *, const char *);
+extern void smb_auth_ntlm2_kxkey(unsigned char *, const char *, const char *,
+ unsigned char *);
extern int smb_auth_set_info(char *, char *,
unsigned char *, char *, unsigned char *,
@@ -496,12 +501,8 @@ extern int smb_auth_set_info(char *, char *,
extern int smb_auth_ntlmv2_hash(unsigned char *,
char *, char *, unsigned char *);
-extern int smb_auth_gen_session_key(smb_auth_info_t *, unsigned char *);
-
-boolean_t smb_auth_validate_lm(unsigned char *, uint32_t, smb_passwd_t *,
- unsigned char *, int, char *, char *);
-boolean_t smb_auth_validate_nt(unsigned char *, uint32_t, smb_passwd_t *,
- unsigned char *, int, char *, char *, uchar_t *);
+boolean_t smb_auth_validate(smb_passwd_t *, char *, char *,
+ uchar_t *, uint_t, uchar_t *, uint_t, uchar_t *, uint_t, uchar_t *);
int smb_gen_random_passwd(char *passwd, size_t bufsz);
@@ -516,14 +517,6 @@ extern void smb_ipc_rollback(void);
extern void smb_ipc_set(char *, uint8_t *);
/*
- * SMB MAC Signing
- */
-
-#define SMB_MAC_KEY_SZ (SMBAUTH_SESSION_KEY_SZ + SMBAUTH_CS_MAXLEN)
-#define SMB_SIG_OFFS 14 /* signature field offset within header */
-#define SMB_SIG_SIZE 8 /* SMB signature size */
-
-/*
* Signing flags:
*
* SMB_SCF_ENABLE Signing is enabled.
@@ -547,38 +540,6 @@ extern void smb_ipc_set(char *, uint8_t *);
#define SMB_SCF_KEY_ISSET_THIS_LOGON 0x08
/*
- * smb_sign_ctx
- *
- * SMB signing context.
- *
- * ssc_seqnum sequence number
- * ssc_keylen mac key length
- * ssc_mid multiplex id - reserved
- * ssc_flags flags
- * ssc_mackey mac key
- * ssc_sign mac signature
- *
- */
-typedef struct smb_sign_ctx {
- unsigned int ssc_seqnum;
- unsigned short ssc_keylen;
- unsigned short ssc_mid;
- unsigned int ssc_flags;
- unsigned char ssc_mackey[SMB_MAC_KEY_SZ];
- unsigned char ssc_sign[SMB_SIG_SIZE];
-} smb_sign_ctx_t;
-
-extern int smb_mac_init(smb_sign_ctx_t *sign_ctx, smb_auth_info_t *auth);
-extern int smb_mac_calc(smb_sign_ctx_t *sign_ctx,
- const unsigned char *buf, size_t buf_len, unsigned char *mac_sign);
-extern int smb_mac_chk(smb_sign_ctx_t *sign_ctx,
- const unsigned char *buf, size_t buf_len);
-extern int smb_mac_sign(smb_sign_ctx_t *sign_ctx,
- unsigned char *buf, size_t buf_len);
-extern void smb_mac_inc_seqnum(smb_sign_ctx_t *sign_ctx);
-extern void smb_mac_dec_seqnum(smb_sign_ctx_t *sign_ctx);
-
-/*
* Each domain is categorized using the enum values below.
* The local domain refers to the local machine and is named
* after the local hostname. The primary domain is the domain
diff --git a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
index 3570d05ba4..c4c3814864 100644
--- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
+++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
@@ -75,13 +75,13 @@ SYMBOL_VERSION SUNWprivate {
smb_acl_to_zfs;
smb_auth_DES;
smb_auth_RC4;
- smb_auth_gen_session_key;
smb_auth_hmac_md5;
smb_auth_ntlm_hash;
+ smb_auth_ntlm2_kxkey;
+ smb_auth_ntlm2_mkchallenge;
smb_auth_ntlmv2_hash;
smb_auth_qnd_unicode;
- smb_auth_validate_lm;
- smb_auth_validate_nt;
+ smb_auth_validate;
smb_buf32_xdr;
smb_cache_add;
smb_cache_create;
@@ -265,11 +265,6 @@ SYMBOL_VERSION SUNWprivate {
smb_logon_xdr;
smb_lookup_name;
smb_lookup_sid;
- smb_mac_chk;
- smb_mac_dec_seqnum;
- smb_mac_inc_seqnum;
- smb_mac_init;
- smb_mac_sign;
smb_match_netlogon_seqnum;
smb_mbstos;
smb_mbstowcs;
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_auth.c b/usr/src/lib/smbsrv/libsmb/common/smb_auth.c
index 9f4100e805..29918639e7 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_auth.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_auth.c
@@ -21,15 +21,70 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ *
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#include <strings.h>
#include <stdlib.h>
+#include <syslog.h>
+#include <sys/md5.h>
#include <smbsrv/string.h>
#include <smbsrv/libsmb.h>
+#include <netsmb/spnego.h> /* libsmbfs */
#include <assert.h>
+#define NTLM_CHAL_SZ SMBAUTH_CHAL_SZ /* challenge size */
+
+/*
+ * Compute the combined (server+client) challenge per. [MS-NLMP 3.3.1]
+ * MD5(concat(ServerChallenge,ClientChallenge))
+ */
+void
+smb_auth_ntlm2_mkchallenge(char *result,
+ const char *srv_chal, const char *clnt_chal)
+{
+ MD5_CTX context;
+ uchar_t challenges[2 * NTLM_CHAL_SZ];
+ uchar_t digest[SMBAUTH_HASH_SZ];
+
+ /*
+ * challenges = ConcatenationOf(ServerChallenge, ClientChallenge)
+ */
+ (void) memcpy(challenges, srv_chal, NTLM_CHAL_SZ);
+ (void) memcpy(challenges + NTLM_CHAL_SZ, clnt_chal, NTLM_CHAL_SZ);
+
+ /*
+ * digest = MD5(challenges)
+ */
+ MD5Init(&context);
+ MD5Update(&context, challenges, sizeof (challenges));
+ MD5Final(digest, &context);
+
+ /*
+ * result = digest[0..7]
+ */
+ (void) memcpy(result, digest, NTLM_CHAL_SZ);
+}
+
+void
+smb_auth_ntlm2_kxkey(unsigned char *result, const char *srv_chal,
+ const char *clnt_chal, unsigned char *ssn_base_key)
+{
+ uchar_t challenges[2 * NTLM_CHAL_SZ];
+
+ /*
+ * challenges = ConcatenationOf(ServerChallenge, ClientChallenge)
+ */
+ (void) memcpy(challenges, srv_chal, NTLM_CHAL_SZ);
+ (void) memcpy(challenges + NTLM_CHAL_SZ, clnt_chal, NTLM_CHAL_SZ);
+
+ /* HMAC_MD5(SessionBaseKey, concat(...)) */
+ /* SMBAUTH_HMACT64 args: D, Dsz, K, Ksz, digest */
+ (void) SMBAUTH_HMACT64(challenges, sizeof (challenges),
+ ssn_base_key, SMBAUTH_HASH_SZ, result);
+}
+
/*
* smb_auth_qnd_unicode
*
@@ -117,7 +172,7 @@ smb_auth_lm_hash(const char *password, unsigned char *lm_hash)
*/
static int
smb_auth_lm_response(unsigned char *hash,
- unsigned char *challenge, int clen,
+ unsigned char *challenge, /* NTLM_CHAL_SZ */
unsigned char *lm_rsp)
{
unsigned char S21[21];
@@ -131,7 +186,7 @@ smb_auth_lm_response(unsigned char *hash,
/* padded LM Hash -> LM Response */
return (smb_auth_DES(lm_rsp, SMBAUTH_LM_RESP_SZ, S21, 21,
- challenge, clen));
+ challenge, NTLM_CHAL_SZ));
}
/*
@@ -174,7 +229,7 @@ smb_auth_ntlm_hash(const char *password, unsigned char *hash)
*/
static int
smb_auth_ntlm_response(unsigned char *hash,
- unsigned char *challenge, int clen,
+ unsigned char *challenge, /* NTLM_CHAL_SZ */
unsigned char *ntlm_rsp)
{
unsigned char S21[21];
@@ -182,7 +237,7 @@ smb_auth_ntlm_response(unsigned char *hash,
bcopy(hash, S21, SMBAUTH_HASH_SZ);
bzero(&S21[SMBAUTH_HASH_SZ], 5);
if (smb_auth_DES((unsigned char *)ntlm_rsp, SMBAUTH_LM_RESP_SZ,
- S21, 21, challenge, clen) == SMBAUTH_FAILURE)
+ S21, 21, challenge, NTLM_CHAL_SZ) == SMBAUTH_FAILURE)
return (0);
return (SMBAUTH_LM_RESP_SZ);
}
@@ -253,13 +308,14 @@ smb_auth_ntlmv2_hash(unsigned char *ntlm_hash,
static int
smb_auth_v2_response(
unsigned char *hash,
- unsigned char *srv_challenge, int slen,
+ unsigned char *srv_challenge, /* NTLM_CHAL_SZ */
unsigned char *clnt_data, int clen,
unsigned char *v2_rsp)
{
unsigned char *hmac_data;
+ int slen = NTLM_CHAL_SZ;
- hmac_data = (unsigned char *)malloc((slen + clen) * sizeof (char));
+ hmac_data = malloc(NTLM_CHAL_SZ + clen);
if (!hmac_data) {
return (-1);
}
@@ -275,70 +331,39 @@ smb_auth_v2_response(
return (SMBAUTH_HASH_SZ + clen);
}
-/*
- * smb_auth_gen_session_key
- *
- * Generate the NTLM user session key if LMCompatibilityLevel is 2 or
- * NTLMv2 user session key if LMCompatibilityLevel is 3 or above.
- *
- * NTLM_Session_Key = MD4(NTLM_Hash);
- *
- * NTLMv2_Session_Key = HMAC_MD5(NTLMv2Hash, 16, NTLMv2_HMAC, 16)
- *
- * Prior to calling this function, the auth instance should be set
- * via smb_auth_set_info().
- *
- * Returns the appropriate session key.
- */
-int
-smb_auth_gen_session_key(smb_auth_info_t *auth, unsigned char *session_key)
-{
- int rc;
-
- if (auth->lmcompatibility_lvl == 2)
- rc = smb_auth_md4(session_key, auth->hash, SMBAUTH_HASH_SZ);
- else
- rc = SMBAUTH_HMACT64((unsigned char *)auth->cs,
- SMBAUTH_HASH_SZ, (unsigned char *)auth->hash_v2,
- SMBAUTH_SESSION_KEY_SZ, session_key);
-
- return (rc);
-}
static boolean_t
smb_lm_password_ok(
unsigned char *challenge,
- uint32_t clen,
unsigned char *lm_hash,
- unsigned char *passwd)
+ unsigned char *lm_resp)
{
- unsigned char lm_resp[SMBAUTH_LM_RESP_SZ];
+ unsigned char ok_resp[SMBAUTH_LM_RESP_SZ];
int rc;
- rc = smb_auth_lm_response(lm_hash, challenge, clen, lm_resp);
+ rc = smb_auth_lm_response(lm_hash, challenge, ok_resp);
if (rc != SMBAUTH_SUCCESS)
return (B_FALSE);
- return (bcmp(lm_resp, passwd, SMBAUTH_LM_RESP_SZ) == 0);
+ return (bcmp(ok_resp, lm_resp, SMBAUTH_LM_RESP_SZ) == 0);
}
static boolean_t
smb_ntlm_password_ok(
unsigned char *challenge,
- uint32_t clen,
unsigned char *ntlm_hash,
- unsigned char *passwd,
+ unsigned char *nt_resp,
unsigned char *session_key)
{
- unsigned char ntlm_resp[SMBAUTH_LM_RESP_SZ];
+ unsigned char ok_resp[SMBAUTH_LM_RESP_SZ];
int rc;
boolean_t ok;
- rc = smb_auth_ntlm_response(ntlm_hash, challenge, clen, ntlm_resp);
+ rc = smb_auth_ntlm_response(ntlm_hash, challenge, ok_resp);
if (rc != SMBAUTH_LM_RESP_SZ)
return (B_FALSE);
- ok = (bcmp(ntlm_resp, passwd, SMBAUTH_LM_RESP_SZ) == 0);
+ ok = (bcmp(ok_resp, nt_resp, SMBAUTH_LM_RESP_SZ) == 0);
if (ok && (session_key)) {
rc = smb_auth_md4(session_key, ntlm_hash, SMBAUTH_HASH_SZ);
if (rc != SMBAUTH_SUCCESS)
@@ -350,7 +375,6 @@ smb_ntlm_password_ok(
static boolean_t
smb_ntlmv2_password_ok(
unsigned char *challenge,
- uint32_t clen,
unsigned char *ntlm_hash,
unsigned char *passwd,
int pwdlen,
@@ -404,7 +428,7 @@ smb_ntlmv2_password_ok(
break;
if (smb_auth_v2_response(ntlmv2_hash, challenge,
- clen, clnt_blob, clnt_blob_len, ntlmv2_resp) < 0)
+ clnt_blob, clnt_blob_len, ntlmv2_resp) < 0)
break;
ok = (bcmp(passwd, ntlmv2_resp, pwdlen) == 0);
@@ -426,8 +450,7 @@ smb_ntlmv2_password_ok(
static boolean_t
smb_lmv2_password_ok(
- unsigned char *challenge,
- uint32_t clen,
+ unsigned char *srv_challenge,
unsigned char *ntlm_hash,
unsigned char *passwd,
char *domain,
@@ -469,8 +492,8 @@ smb_lmv2_password_ok(
ntlmv2_hash) != SMBAUTH_SUCCESS)
break;
- if (smb_auth_v2_response(ntlmv2_hash, challenge,
- clen, clnt_challenge, SMBAUTH_V2_CLNT_CHALLENGE_SZ,
+ if (smb_auth_v2_response(ntlmv2_hash, srv_challenge,
+ clnt_challenge, SMBAUTH_CHAL_SZ,
lmv2_resp) < 0)
break;
@@ -484,81 +507,83 @@ smb_lmv2_password_ok(
}
/*
- * smb_auth_validate_lm
+ * smb_auth_validate
*
- * Validates given LM/LMv2 client response, passed in passwd arg, against
- * stored user's password, passed in smbpw
- *
- * If LM level <=3 server accepts LM responses, otherwise LMv2
+ * Validates given NTLMv2 (or NTLM, LMv2, LM) client responses against
+ * the stored user's password, passed in smbpw. Try those in the order
+ * strongest to weakest, stopping at a point determined by the configured
+ * lmauth_level (LM Compatibility Level).
*/
boolean_t
-smb_auth_validate_lm(
- unsigned char *challenge,
- uint32_t clen,
+smb_auth_validate(
smb_passwd_t *smbpw,
- unsigned char *passwd,
- int pwdlen,
char *domain,
- char *username)
+ char *username,
+ unsigned char *challenge,
+ uint_t clen,
+ unsigned char *nt_resp,
+ uint_t nt_len,
+ unsigned char *lm_resp,
+ uint_t lm_len,
+ uchar_t *session_key)
{
- boolean_t ok = B_FALSE;
int64_t lmlevel;
-
- if (pwdlen != SMBAUTH_LM_RESP_SZ)
- return (B_FALSE);
+ boolean_t ok = B_FALSE;
if (smb_config_getnum(SMB_CI_LM_LEVEL, &lmlevel) != SMBD_SMF_OK)
return (B_FALSE);
- if (lmlevel <= 3) {
- ok = smb_lm_password_ok(challenge, clen, smbpw->pw_lmhash,
- passwd);
- }
-
- if (!ok)
- ok = smb_lmv2_password_ok(challenge, clen, smbpw->pw_nthash,
- passwd, domain, username);
+ if (lmlevel > 5)
+ return (B_FALSE);
- return (ok);
-}
+ if (clen != NTLM_CHAL_SZ)
+ return (B_FALSE);
-/*
- * smb_auth_validate_nt
- *
- * Validates given NTLM/NTLMv2 client response, passed in passwd arg, against
- * stored user's password, passed in smbpw
- *
- * If LM level <=4 server accepts NTLM/NTLMv2 responses, otherwise only NTLMv2
- */
-boolean_t
-smb_auth_validate_nt(
- unsigned char *challenge,
- uint32_t clen,
- smb_passwd_t *smbpw,
- unsigned char *passwd,
- int pwdlen,
- char *domain,
- char *username,
- uchar_t *session_key)
-{
- int64_t lmlevel;
- boolean_t ok;
+ /*
+ * Accept NTLMv2 at any LM level (0-5).
+ */
+ if (nt_len > SMBAUTH_LM_RESP_SZ) {
+ ok = smb_ntlmv2_password_ok(challenge,
+ smbpw->pw_nthash, nt_resp, nt_len,
+ domain, username, session_key);
+ if (ok)
+ return (ok);
+ }
- if (smb_config_getnum(SMB_CI_LM_LEVEL, &lmlevel) != SMBD_SMF_OK)
+ if (lmlevel == 5)
return (B_FALSE);
- if ((lmlevel == 5) && (pwdlen <= SMBAUTH_LM_RESP_SZ))
+ /*
+ * Accept NTLM at levels 0-4
+ */
+ if (nt_len == SMBAUTH_LM_RESP_SZ) {
+ ok = smb_ntlm_password_ok(challenge, smbpw->pw_nthash,
+ nt_resp, session_key);
+ if (ok)
+ return (ok);
+ }
+
+ if (lmlevel == 4)
return (B_FALSE);
- if (pwdlen > SMBAUTH_LM_RESP_SZ)
- ok = smb_ntlmv2_password_ok(challenge, clen,
- smbpw->pw_nthash, passwd, pwdlen,
- domain, username, session_key);
- else
- ok = smb_ntlm_password_ok(challenge, clen,
- smbpw->pw_nthash, passwd, session_key);
- return (ok);
+ /*
+ * Accept LM/LMv2 auth at levels 0-3
+ */
+ if (lm_len != SMBAUTH_LM_RESP_SZ)
+ return (B_FALSE);
+ if (session_key)
+ (void) smb_auth_md4(session_key, smbpw->pw_nthash,
+ SMBAUTH_HASH_SZ);
+ ok = smb_lmv2_password_ok(challenge, smbpw->pw_nthash,
+ lm_resp, domain, username);
+ if (ok)
+ return (ok);
+ ok = smb_lm_password_ok(challenge, smbpw->pw_lmhash, lm_resp);
+ if (ok)
+ return (ok);
+
+ return (B_FALSE);
}
/*
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c
index 08ab3376be..1110fd8792 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c
@@ -58,6 +58,7 @@ typedef struct smb_cfg_param {
/* idmap SMF fmri and Property Group */
#define IDMAP_FMRI_PREFIX "system/idmap"
#define MACHINE_SID "machine_sid"
+#define MACHINE_UUID "machine_uuid"
#define IDMAP_DOMAIN "domain_name"
#define IDMAP_PG_NAME "config"
@@ -121,14 +122,12 @@ static smb_cfg_param_t smb_cfg_table[] =
{SMB_CI_MACHINE_PASSWD, "machine_passwd", SCF_TYPE_ASTRING,
SMB_CF_PROTECTED},
- {SMB_CI_KPASSWD_SRV, "kpasswd_server", SCF_TYPE_ASTRING,
- 0},
- {SMB_CI_KPASSWD_DOMAIN, "kpasswd_domain", SCF_TYPE_ASTRING,
- 0},
- {SMB_CI_KPASSWD_SEQNUM, "kpasswd_seqnum", SCF_TYPE_INTEGER,
- 0},
- {SMB_CI_NETLOGON_SEQNUM, "netlogon_seqnum", SCF_TYPE_INTEGER,
- 0},
+
+ {SMB_CI_MACHINE_UUID, "machine_uuid", SCF_TYPE_ASTRING, 0},
+ {SMB_CI_KPASSWD_SRV, "kpasswd_server", SCF_TYPE_ASTRING, 0},
+ {SMB_CI_KPASSWD_DOMAIN, "kpasswd_domain", SCF_TYPE_ASTRING, 0},
+ {SMB_CI_KPASSWD_SEQNUM, "kpasswd_seqnum", SCF_TYPE_INTEGER, 0},
+ {SMB_CI_NETLOGON_SEQNUM, "netlogon_seqnum", SCF_TYPE_INTEGER, 0},
{SMB_CI_IPV6_ENABLE, "ipv6_enable", SCF_TYPE_BOOLEAN, 0},
{SMB_CI_PRINT_ENABLE, "print_enable", SCF_TYPE_BOOLEAN, 0},
{SMB_CI_MAP, "map", SCF_TYPE_ASTRING, SMB_CF_EXEC},
@@ -136,6 +135,7 @@ static smb_cfg_param_t smb_cfg_table[] =
{SMB_CI_DISPOSITION, "disposition", SCF_TYPE_ASTRING, SMB_CF_EXEC},
{SMB_CI_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0},
{SMB_CI_TRAVERSE_MOUNTS, "traverse_mounts", SCF_TYPE_BOOLEAN, 0},
+
/* SMB_CI_MAX */
};
@@ -800,7 +800,7 @@ smb_config_get_ads_enable(void)
*
* Returns value of the "config/machine_sid" parameter
* from the IDMAP SMF configuration repository.
- *
+ * Result is allocated; caller should free.
*/
char *
smb_config_get_localsid(void)
@@ -810,6 +810,32 @@ smb_config_get_localsid(void)
}
/*
+ * smb_config_get_localuuid
+ *
+ * Returns value of the "config/machine_uuid" parameter
+ * from the IDMAP SMF configuration repository.
+ *
+ */
+int
+smb_config_get_localuuid(uuid_t uu)
+{
+ char *s;
+
+ uuid_clear(uu);
+ s = smb_config_getenv_generic(MACHINE_UUID, IDMAP_FMRI_PREFIX,
+ IDMAP_PG_NAME);
+ if (s == NULL)
+ return (-1);
+
+ if (uuid_parse(s, uu) < 0) {
+ free(s);
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
* smb_config_set_idmap_domain
*
* Set the "config/domain_name" parameter from IDMAP SMF repository.
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_info.c b/usr/src/lib/smbsrv/libsmb/common/smb_info.c
index ea6707951e..0dcae43179 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_info.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_info.c
@@ -20,11 +20,14 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
-#include <assert.h>
#include <sys/types.h>
+#include <sys/sockio.h>
+#include <sys/socket.h>
+#include <sys/utsname.h>
+
#include <stdarg.h>
#include <unistd.h>
#include <stdlib.h>
@@ -39,11 +42,11 @@
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
-#include <sys/sockio.h>
-#include <sys/socket.h>
+
#include <smbsrv/smbinfo.h>
#include <smbsrv/netbios.h>
#include <smbsrv/libsmb.h>
+#include <assert.h>
static mutex_t seqnum_mtx;
@@ -67,6 +70,7 @@ static rwlock_t smb_ipc_lock;
void
smb_load_kconfig(smb_kmod_cfg_t *kcfg)
{
+ struct utsname uts;
int64_t citem;
bzero(kcfg, sizeof (smb_kmod_cfg_t));
@@ -106,6 +110,18 @@ smb_load_kconfig(smb_kmod_cfg_t *kcfg)
sizeof (kcfg->skc_system_comment));
smb_config_get_version(&kcfg->skc_version);
kcfg->skc_execflags = smb_config_get_execinfo(NULL, NULL, 0);
+ if (smb_config_get_localuuid(kcfg->skc_machine_uuid) < 0) {
+ syslog(LOG_ERR, "smb_load_kconfig: no machine_uuid");
+ uuid_generate_time(kcfg->skc_machine_uuid);
+ }
+ /* skc_negtok, skc_negtok_len: see smbd_authsvc.c */
+
+ (void) uname(&uts);
+ (void) snprintf(kcfg->skc_native_os, sizeof (kcfg->skc_native_os),
+ "%s %s %s", uts.sysname, uts.release, uts.version);
+
+ (void) strlcpy(kcfg->skc_native_lm, "Native SMB service",
+ sizeof (kcfg->skc_native_lm));
}
/*
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c b/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c
index 145d8da21c..8b7b32fb19 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c
@@ -69,6 +69,7 @@ smb_kmod_isbound(void)
return ((smbdrv_fd == -1) ? B_FALSE : B_TRUE);
}
+/* See also: smbsrv smb_server_store_cfg */
int
smb_kmod_setcfg(smb_kmod_cfg_t *cfg)
{
@@ -83,13 +84,21 @@ smb_kmod_setcfg(smb_kmod_cfg_t *cfg)
ioc.oplock_enable = cfg->skc_oplock_enable;
ioc.sync_enable = cfg->skc_sync_enable;
ioc.secmode = cfg->skc_secmode;
- ioc.ipv6_enable = cfg->skc_ipv6_enable;
ioc.netbios_enable = cfg->skc_netbios_enable;
+ ioc.ipv6_enable = cfg->skc_ipv6_enable;
ioc.print_enable = cfg->skc_print_enable;
ioc.traverse_mounts = cfg->skc_traverse_mounts;
ioc.exec_flags = cfg->skc_execflags;
+ ioc.negtok_len = cfg->skc_negtok_len;
ioc.version = cfg->skc_version;
+ (void) memcpy(ioc.machine_uuid, cfg->skc_machine_uuid, sizeof (uuid_t));
+ (void) memcpy(ioc.negtok, cfg->skc_negtok, sizeof (ioc.negtok));
+ (void) memcpy(ioc.native_os, cfg->skc_native_os,
+ sizeof (ioc.native_os));
+ (void) memcpy(ioc.native_lm, cfg->skc_native_lm,
+ sizeof (ioc.native_lm));
+
(void) strlcpy(ioc.nbdomain, cfg->skc_nbdomain, sizeof (ioc.nbdomain));
(void) strlcpy(ioc.fqdn, cfg->skc_fqdn, sizeof (ioc.fqdn));
(void) strlcpy(ioc.hostname, cfg->skc_hostname, sizeof (ioc.hostname));
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_mac.c b/usr/src/lib/smbsrv/libsmb/common/smb_mac.c
deleted file mode 100644
index 57fb74530c..0000000000
--- a/usr/src/lib/smbsrv/libsmb/common/smb_mac.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * SMB MAC Signing support.
- */
-
-#include <strings.h>
-#include <security/cryptoki.h>
-#include <security/pkcs11.h>
-
-#include <smbsrv/libsmb.h>
-
-#include <smbsrv/smb.h>
-
-/*
- * smb_mac_init
- *
- * Calculates the MAC key using the specified user session
- * key (NTLM or NTLMv2).
- *
- * Returns SMBAUTH_SUCCESS if key generation was successful,
- * SMBAUTH_FAILURE if not.
- */
-int
-smb_mac_init(smb_sign_ctx_t *sign_ctx, smb_auth_info_t *auth)
-{
- unsigned char S16[SMBAUTH_SESSION_KEY_SZ];
-
- if (smb_auth_gen_session_key(auth, S16) != SMBAUTH_SUCCESS)
- return (SMBAUTH_FAILURE);
- bcopy(S16, sign_ctx->ssc_mackey, SMBAUTH_SESSION_KEY_SZ);
- bcopy(auth->cs, &(sign_ctx->ssc_mackey[SMBAUTH_SESSION_KEY_SZ]),
- auth->cs_len);
- sign_ctx->ssc_keylen = SMBAUTH_SESSION_KEY_SZ + auth->cs_len;
- return (SMBAUTH_SUCCESS);
-}
-
-/*
- * smb_mac_calc
- *
- * Calculates MAC signature for the given buffer and returns
- * it in the mac_sign parameter.
- *
- * The MAC signature is calculated as follows:
- *
- * data = concat(MAC_Key, MAC_Key_Len, SMB_Msg, SMB_Msg_Len);
- * hash = MD5(data);
- * MAC = head(hash, 8);
- *
- * The tricky part is that a sequence number should be used
- * in calculation instead of the signature field in the
- * SMB header.
- *
- * Returns SMBAUTH_SUCCESS if cryptology framework use was successful,
- * SMBAUTH_FAILURE if not.
- */
-int
-smb_mac_calc(smb_sign_ctx_t *sign_ctx, const unsigned char *buf,
- size_t buf_len, unsigned char *mac_sign)
-{
- CK_RV rv;
- CK_MECHANISM mechanism;
- CK_SESSION_HANDLE hSession;
- unsigned long diglen = MD_DIGEST_LEN;
- int rc = SMBAUTH_FAILURE;
-
- int offset_end_of_sig = (SMB_SIG_OFFS + SMB_SIG_SIZE);
- unsigned char seq_buf[SMB_SIG_SIZE];
- unsigned char mac[16];
-
- /*
- * put seq_num into the first 4 bytes and
- * zero out the next 4 bytes
- */
- bcopy(&sign_ctx->ssc_seqnum, seq_buf, 4);
- bzero(seq_buf + 4, 4);
-
- mechanism.mechanism = CKM_MD5;
- mechanism.pParameter = 0;
- mechanism.ulParameterLen = 0;
-
- rv = SUNW_C_GetMechSession(mechanism.mechanism, &hSession);
- if (rv != CKR_OK)
- return (SMBAUTH_FAILURE);
-
- /* Initialize the digest operation in the session */
- rv = C_DigestInit(hSession, &mechanism);
- if (rv != CKR_OK)
- goto smbmacdone;
-
- /* init with the MAC key */
- rv = C_DigestUpdate(hSession, sign_ctx->ssc_mackey,
- sign_ctx->ssc_keylen);
- if (rv != CKR_OK)
- goto smbmacdone;
-
- /* copy in SMB packet info till signature field */
- rv = C_DigestUpdate(hSession, (CK_BYTE_PTR)buf, SMB_SIG_OFFS);
- if (rv != CKR_OK)
- goto smbmacdone;
-
- /* copy in the seq_buf instead of the signature */
- rv = C_DigestUpdate(hSession, seq_buf, sizeof (seq_buf));
- if (rv != CKR_OK)
- goto smbmacdone;
-
- /* copy in the rest of the packet, skipping the signature */
- rv = C_DigestUpdate(hSession, (CK_BYTE_PTR)buf + offset_end_of_sig,
- buf_len - offset_end_of_sig);
- if (rv != CKR_OK)
- goto smbmacdone;
-
- rv = C_DigestFinal(hSession, mac, &diglen);
- if (rv != CKR_OK)
- goto smbmacdone;
-
- bcopy(mac, mac_sign, SMB_SIG_SIZE);
- rc = SMBAUTH_SUCCESS;
-
-smbmacdone:
- (void) C_CloseSession(hSession);
- return (rc);
-}
-
-/*
- * smb_mac_chk
- *
- * Calculates MAC signature for the given buffer
- * and compares it to the signature in the given context.
- * Return 1 if the signature are match, otherwise, return (0);
- */
-int
-smb_mac_chk(smb_sign_ctx_t *sign_ctx,
- const unsigned char *buf, size_t buf_len)
-{
- unsigned char mac_sign[SMB_SIG_SIZE];
-
- /* calculate mac signature */
- if (smb_mac_calc(sign_ctx, buf, buf_len, mac_sign) != SMBAUTH_SUCCESS)
- return (0);
-
- /* compare the signatures */
- if (memcmp(sign_ctx->ssc_sign, mac_sign, SMB_SIG_SIZE) == 0)
- return (1);
-
- return (0);
-}
-
-/*
- * smb_mac_sign
- *
- * Calculates MAC signature for the given buffer,
- * and write it to the buffer's signature field.
- *
- * Returns SMBAUTH_SUCCESS if cryptology framework use was successful,
- * SMBAUTH_FAILURE if not.
- */
-int
-smb_mac_sign(smb_sign_ctx_t *sign_ctx, unsigned char *buf, size_t buf_len)
-{
- unsigned char mac_sign[SMB_SIG_SIZE];
-
- /* calculate mac signature */
- if (smb_mac_calc(sign_ctx, buf, buf_len, mac_sign) != SMBAUTH_SUCCESS)
- return (SMBAUTH_FAILURE);
-
- /* put mac signature in the header's signature field */
- (void) memcpy(buf + SMB_SIG_OFFS, mac_sign, SMB_SIG_SIZE);
- return (SMBAUTH_SUCCESS);
-}
-
-void
-smb_mac_inc_seqnum(smb_sign_ctx_t *sign_ctx)
-{
- sign_ctx->ssc_seqnum++;
-}
-
-void
-smb_mac_dec_seqnum(smb_sign_ctx_t *sign_ctx)
-{
- sign_ctx->ssc_seqnum--;
-}
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c b/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c
index b359d32d5d..19cb5166a1 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c
@@ -21,6 +21,8 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#include <syslog.h>
@@ -262,10 +264,13 @@ smb_pwd_getpwnam(const char *name, smb_passwd_t *smbpw)
return (smb_pwd_ops.pwop_getpwnam(name, smbpw));
err = smb_pwd_lock();
- if (err != SMB_PWE_SUCCESS)
+ if (err != SMB_PWE_SUCCESS) {
+ syslog(LOG_WARNING, "smb_pwdutil: lock failed, err=%d", err);
return (NULL);
+ }
if ((fp = fopen(SMB_PASSWD, "rF")) == NULL) {
+ syslog(LOG_WARNING, "smb_pwdutil: open failed, %m");
(void) smb_pwd_unlock();
return (NULL);
}
@@ -274,8 +279,7 @@ smb_pwd_getpwnam(const char *name, smb_passwd_t *smbpw)
while (smb_pwd_fgetent(fp, &pwbuf, SMB_PWD_GETF_ALL) != NULL) {
if (strcmp(name, smbpw->pw_name) == 0) {
- if ((smbpw->pw_flags & (SMB_PWF_LM | SMB_PWF_NT)))
- found = B_TRUE;
+ found = B_TRUE;
break;
}
}
@@ -311,10 +315,13 @@ smb_pwd_getpwuid(uid_t uid, smb_passwd_t *smbpw)
return (smb_pwd_ops.pwop_getpwuid(uid, smbpw));
err = smb_pwd_lock();
- if (err != SMB_PWE_SUCCESS)
+ if (err != SMB_PWE_SUCCESS) {
+ syslog(LOG_WARNING, "smb_pwdutil: lock failed, err=%d", err);
return (NULL);
+ }
if ((fp = fopen(SMB_PASSWD, "rF")) == NULL) {
+ syslog(LOG_WARNING, "smb_pwdutil: open failed, %m");
(void) smb_pwd_unlock();
return (NULL);
}
@@ -323,8 +330,7 @@ smb_pwd_getpwuid(uid_t uid, smb_passwd_t *smbpw)
while (smb_pwd_fgetent(fp, &pwbuf, SMB_PWD_GETF_ALL) != NULL) {
if (uid == smbpw->pw_uid) {
- if ((smbpw->pw_flags & (SMB_PWF_LM | SMB_PWF_NT)))
- found = B_TRUE;
+ found = B_TRUE;
break;
}
}
@@ -1002,10 +1008,13 @@ smb_lucache_do_update(void)
void *cookie = NULL;
FILE *fp;
- if ((rc = smb_pwd_lock()) != SMB_PWE_SUCCESS)
+ if ((rc = smb_pwd_lock()) != SMB_PWE_SUCCESS) {
+ syslog(LOG_WARNING, "smb_pwdutil: lock failed, err=%d", rc);
return (rc);
+ }
if ((fp = fopen(SMB_PASSWD, "rF")) == NULL) {
+ syslog(LOG_WARNING, "smb_pwdutil: open failed, %m");
(void) smb_pwd_unlock();
return (SMB_PWE_OPEN_FAILED);
}
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h
index 279634afc2..d60bca8785 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SMBSRV_SMB_KRB_H
@@ -40,6 +41,7 @@ extern "C" {
#define SMB_PN_SALT 0x0008 /* w/ REALM */
#define SMB_PN_SVC_HOST "host"
+#define SMB_PN_SVC_CIFS "cifs"
#define SMB_PN_SVC_NFS "nfs"
#define SMB_PN_SVC_HTTP "HTTP"
#define SMB_PN_SVC_ROOT "root"
@@ -47,7 +49,11 @@ extern "C" {
/* Assign an identifier for each principal name format */
typedef enum smb_krb5_pn_id {
SMB_KRB5_PN_ID_SALT,
- SMB_KRB5_PN_ID_HOST_FQHN,
+ SMB_KRB5_PN_ID_HOST_FQHN, /* fully qualified name */
+ SMB_KRB5_PN_ID_HOST_SHORT, /* short name */
+ SMB_KRB5_PN_ID_CIFS_FQHN,
+ SMB_KRB5_PN_ID_CIFS_SHORT,
+ SMB_KRB5_PN_ID_MACHINE, /* the machine account */
SMB_KRB5_PN_ID_NFS_FQHN,
SMB_KRB5_PN_ID_HTTP_FQHN,
SMB_KRB5_PN_ID_ROOT_FQHN,
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_ksetpwd.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_ksetpwd.c
index 946ca6461a..7a6a3491a1 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ksetpwd.c
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ksetpwd.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#include <stdio.h>
@@ -49,9 +50,17 @@ static smb_krb5_pn_t smb_krb5_pn_tab[] = {
*/
{SMB_KRB5_PN_ID_SALT, SMB_PN_SVC_HOST, SMB_PN_SALT},
- /* HOST */
+ /* CIFS SPNs. (HOST, CIFS, ...) */
{SMB_KRB5_PN_ID_HOST_FQHN, SMB_PN_SVC_HOST,
SMB_PN_KEYTAB_ENTRY | SMB_PN_SPN_ATTR | SMB_PN_UPN_ATTR},
+ {SMB_KRB5_PN_ID_HOST_SHORT, SMB_PN_SVC_HOST,
+ SMB_PN_KEYTAB_ENTRY | SMB_PN_SPN_ATTR},
+ {SMB_KRB5_PN_ID_CIFS_FQHN, SMB_PN_SVC_CIFS,
+ SMB_PN_KEYTAB_ENTRY | SMB_PN_SPN_ATTR},
+ {SMB_KRB5_PN_ID_CIFS_SHORT, SMB_PN_SVC_CIFS,
+ SMB_PN_KEYTAB_ENTRY | SMB_PN_SPN_ATTR},
+ {SMB_KRB5_PN_ID_MACHINE, NULL,
+ SMB_PN_KEYTAB_ENTRY},
/* NFS */
{SMB_KRB5_PN_ID_NFS_FQHN, SMB_PN_SVC_NFS,
@@ -529,12 +538,30 @@ smb_krb5_get_pn_by_id(smb_krb5_pn_id_t id, uint32_t type,
break;
case SMB_KRB5_PN_ID_HOST_FQHN:
+ case SMB_KRB5_PN_ID_CIFS_FQHN:
case SMB_KRB5_PN_ID_NFS_FQHN:
case SMB_KRB5_PN_ID_HTTP_FQHN:
case SMB_KRB5_PN_ID_ROOT_FQHN:
(void) asprintf(&buf, "%s/%s.%s",
pn->p_svc, hostname, fqdn);
break;
+
+ case SMB_KRB5_PN_ID_HOST_SHORT:
+ case SMB_KRB5_PN_ID_CIFS_SHORT:
+ (void) asprintf(&buf, "%s/%s",
+ pn->p_svc, nbname);
+ break;
+
+ /*
+ * SPN for the machine account, which is simply the
+ * (short) machine name with a dollar sign appended.
+ */
+ case SMB_KRB5_PN_ID_MACHINE:
+ (void) asprintf(&buf, "%s$", nbname);
+ break;
+
+ default:
+ return (NULL);
}
/*