summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2003-12-04 20:35:40 +0000
committerGerald Carter <jerry@samba.org>2003-12-04 20:35:40 +0000
commit99da99932f88aae5d20541fd2494e28da20715cc (patch)
treee32232b10164fcc9e2279c3ffae5b4c7cc9afbba
parenta60584a1439ca7c3c1e2ecfcbfc73ab220525690 (diff)
downloadsamba-99da99932f88aae5d20541fd2494e28da20715cc.tar.gz
syncing tree for 3.0.1rc1
-rw-r--r--WHATSNEW.txt8
-rw-r--r--examples/LDAP/samba.schema7
-rw-r--r--examples/nss/wbtest.c375
-rw-r--r--packaging/Mandrake/samba2.spec.tmpl214
-rw-r--r--packaging/Mandrake/smb.conf29
-rwxr-xr-xpackaging/Solaris/samba.server.master2
-rw-r--r--source/Makefile.in11
-rw-r--r--source/VERSION4
-rw-r--r--source/auth/auth.c18
-rw-r--r--source/auth/auth_ntlmssp.c81
-rw-r--r--source/auth/auth_sam.c64
-rw-r--r--source/auth/auth_server.c2
-rw-r--r--source/auth/auth_util.c24
-rw-r--r--source/configure.in61
-rw-r--r--source/groupdb/mapping.c38
-rw-r--r--source/include/auth.h7
-rw-r--r--source/include/client.h4
-rw-r--r--source/include/includes.h2
-rw-r--r--source/include/ntdomain.h2
-rw-r--r--source/include/ntlmssp.h98
-rw-r--r--source/include/passdb.h4
-rw-r--r--source/include/rpc_samr.h14
-rw-r--r--source/include/smb.h2
-rw-r--r--source/include/smbldap.h1
-rw-r--r--source/lib/access.c2
-rw-r--r--source/lib/charcnv.c13
-rw-r--r--source/lib/data_blob.c14
-rw-r--r--source/lib/module.c5
-rw-r--r--source/lib/privileges.c6
-rw-r--r--source/lib/smbldap.c1
-rw-r--r--source/lib/time.c5
-rw-r--r--source/lib/util.c2
-rw-r--r--source/lib/util_str.c14
-rw-r--r--source/libads/kerberos_verify.c2
-rw-r--r--source/libads/ldap.c2
-rw-r--r--source/libsmb/cliconnect.c103
-rw-r--r--source/libsmb/clientgen.c5
-rw-r--r--source/libsmb/clikrb5.c16
-rw-r--r--source/libsmb/clispnego.c2
-rw-r--r--source/libsmb/clitrans.c50
-rw-r--r--source/libsmb/ntlmssp.c750
-rw-r--r--source/libsmb/ntlmssp_parse.c33
-rw-r--r--source/libsmb/ntlmssp_sign.c126
-rw-r--r--source/libsmb/smb_signing.c73
-rw-r--r--source/libsmb/smbdes.c40
-rw-r--r--source/libsmb/smbencrypt.c6
-rw-r--r--source/libsmb/trusts_util.c1
-rw-r--r--source/nsswitch/wbinfo.c42
-rw-r--r--source/nsswitch/winbind_nss_freebsd.c81
-rw-r--r--source/nsswitch/winbind_nss_linux.c149
-rw-r--r--source/nsswitch/winbindd.c2
-rw-r--r--source/nsswitch/winbindd_cm.c5
-rw-r--r--source/nsswitch/winbindd_group.c89
-rw-r--r--source/nsswitch/winbindd_nss.h3
-rw-r--r--source/nsswitch/winbindd_pam.c12
-rw-r--r--source/nsswitch/winbindd_rpc.c51
-rw-r--r--source/nsswitch/winbindd_sid.c19
-rw-r--r--source/param/loadparm.c126
-rw-r--r--source/passdb/passdb.c31
-rw-r--r--source/passdb/pdb_ldap.c18
-rw-r--r--source/passdb/util_sam_sid.c4
-rw-r--r--source/printing/print_cups.c15
-rw-r--r--source/printing/printing.c10
-rw-r--r--source/rpc_client/cli_netlogon.c12
-rw-r--r--source/rpc_client/cli_pipe.c44
-rw-r--r--source/rpc_client/cli_samr.c14
-rw-r--r--source/rpc_parse/parse_misc.c6
-rw-r--r--source/rpc_parse/parse_net.c11
-rw-r--r--source/rpc_parse/parse_samr.c50
-rw-r--r--source/rpc_server/srv_dfs_nt.c3
-rw-r--r--source/rpc_server/srv_lsa_nt.c9
-rw-r--r--source/rpc_server/srv_netlog_nt.c23
-rw-r--r--source/rpc_server/srv_pipe.c12
-rw-r--r--source/rpc_server/srv_pipe_hnd.c6
-rw-r--r--source/rpc_server/srv_samr.c20
-rw-r--r--source/rpc_server/srv_samr_nt.c335
-rw-r--r--source/rpc_server/srv_srvsvc_nt.c5
-rw-r--r--source/rpc_server/srv_util.c17
-rw-r--r--source/smbd/chgpasswd.c9
-rw-r--r--source/smbd/dosmode.c3
-rw-r--r--source/smbd/ipc.c8
-rw-r--r--source/smbd/lanman.c9
-rw-r--r--source/smbd/mangle_hash.c18
-rw-r--r--source/smbd/mangle_hash2.c2
-rw-r--r--source/smbd/nttrans.c8
-rw-r--r--source/smbd/open.c16
-rw-r--r--source/smbd/password.c23
-rw-r--r--source/smbd/posix_acls.c42
-rw-r--r--source/smbd/process.c15
-rw-r--r--source/smbd/quotas.c51
-rw-r--r--source/smbd/sesssetup.c60
-rw-r--r--source/smbd/trans2.c8
-rw-r--r--source/smbd/vfs-wrap.c100
-rw-r--r--source/torture/nbio.c4
-rw-r--r--source/utils/net.c1
-rw-r--r--source/utils/net_ads.c4
-rw-r--r--source/utils/net_help.c13
-rw-r--r--source/utils/net_rpc.c141
-rw-r--r--source/utils/net_rpc_join.c8
-rw-r--r--source/utils/ntlm_auth.c184
-rw-r--r--source/utils/pdbedit.c13
-rw-r--r--source/web/cgi.c3
-rw-r--r--source/web/diagnose.c6
-rw-r--r--source/web/swat.c12
-rw-r--r--testsuite/build_farm/runlist4
105 files changed, 3106 insertions, 1226 deletions
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index f01dc7456d4..3b5b6a44bf6 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -21,6 +21,14 @@ Changes since 3.0.1pre2
Please refer to the CVS log for the SAMBA_3_0 branch for complete
details:
+1) Fix for pdbedit error code returns (bug 763).
+
+Changes since 3.0.1pre3
+-----------------------
+
+Please refer to the CVS log for the SAMBA_3_0 branch for complete
+details:
+
1) Skip over the winbind separator when looking up a user.
This fixes the bug that prevented local users from
matching an AD user when not running winbindd (bug 698).
diff --git a/examples/LDAP/samba.schema b/examples/LDAP/samba.schema
index 14cd7205880..a2225faa584 100644
--- a/examples/LDAP/samba.schema
+++ b/examples/LDAP/samba.schema
@@ -236,6 +236,11 @@ attributetype ( 1.3.6.1.4.1.7165.2.1.38 NAME 'sambaDomainName'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+attributetype ( 1.3.6.1.4.1.7165.2.1.47 NAME 'sambaMungedDial'
+ DESC ''
+ EQUALITY caseExactMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1050} )
+
##
## SID, of any type
##
@@ -308,7 +313,7 @@ objectclass ( 1.3.6.1.4.1.7165.2.2.6 NAME 'sambaSamAccount' SUP top AUXILIARY
sambaPwdCanChange $ sambaPwdMustChange $ sambaAcctFlags $
displayName $ sambaHomePath $ sambaHomeDrive $ sambaLogonScript $
sambaProfilePath $ description $ sambaUserWorkstations $
- sambaPrimaryGroupSID $ sambaDomainName ))
+ sambaPrimaryGroupSID $ sambaDomainName $ sambaMungedDial))
##
## Group mapping info
diff --git a/examples/nss/wbtest.c b/examples/nss/wbtest.c
new file mode 100644
index 00000000000..fc8f575ef06
--- /dev/null
+++ b/examples/nss/wbtest.c
@@ -0,0 +1,375 @@
+/*
+ nss sample code for extended winbindd functionality
+
+ Copyright (C) Andrew Tridgell (tridge@samba.org)
+
+ you are free to use this code in any way you see fit, including
+ without restriction, using this code in your own products. You do
+ not need to give any attribution.
+*/
+
+/*
+ compile like this:
+
+ cc -o wbtest wbtest.c -ldl
+
+ and run like this:
+
+ ./wbtest /lib/libnss_winbind.so
+*/
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <nss.h>
+#include <dlfcn.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+typedef enum nss_status NSS_STATUS;
+
+struct nss_state {
+ void *dl_handle;
+ char *nss_name;
+ char pwnam_buf[512];
+};
+
+/*
+ find a function in the nss library
+*/
+static void *find_fn(struct nss_state *nss, const char *name)
+{
+ void *res;
+ char *s = NULL;
+
+ asprintf(&s, "_nss_%s_%s", nss->nss_name, name);
+ if (!s) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ res = dlsym(nss->dl_handle, s);
+ free(s);
+ if (!res) {
+ errno = ENOENT;
+ return NULL;
+ }
+ return res;
+}
+
+/*
+ establish a link to the nss library
+ Return 0 on success and -1 on error
+*/
+int nss_open(struct nss_state *nss, const char *nss_path)
+{
+ char *p;
+ p = strrchr(nss_path, '_');
+ if (!p) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ nss->nss_name = strdup(p+1);
+ p = strchr(nss->nss_name, '.');
+ if (p) *p = 0;
+
+ nss->dl_handle = dlopen(nss_path, RTLD_LAZY);
+ if (!nss->dl_handle) {
+ free(nss->nss_name);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ close and cleanup a nss state
+*/
+void nss_close(struct nss_state *nss)
+{
+ free(nss->nss_name);
+ dlclose(nss->dl_handle);
+}
+
+/*
+ make a getpwnam call.
+ Return 0 on success and -1 on error
+*/
+int nss_getpwent(struct nss_state *nss, struct passwd *pwd)
+{
+ NSS_STATUS (*_nss_getpwent_r)(struct passwd *, char *,
+ size_t , int *) = find_fn(nss, "getpwent_r");
+ NSS_STATUS status;
+ int nss_errno = 0;
+
+ if (!_nss_getpwent_r) {
+ return -1;
+ }
+
+ status = _nss_getpwent_r(pwd, nss->pwnam_buf, sizeof(nss->pwnam_buf), &nss_errno);
+ if (status == NSS_STATUS_NOTFOUND) {
+ errno = ENOENT;
+ return -1;
+ }
+ if (status != NSS_STATUS_SUCCESS) {
+ errno = nss_errno;
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ make a setpwent call.
+ Return 0 on success and -1 on error
+*/
+int nss_setpwent(struct nss_state *nss)
+{
+ NSS_STATUS (*_nss_setpwent)(void) = find_fn(nss, "setpwent");
+ NSS_STATUS status;
+ if (!_nss_setpwent) {
+ return -1;
+ }
+ status = _nss_setpwent();
+ if (status != NSS_STATUS_SUCCESS) {
+ errno = EINVAL;
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ make a endpwent call.
+ Return 0 on success and -1 on error
+*/
+int nss_endpwent(struct nss_state *nss)
+{
+ NSS_STATUS (*_nss_endpwent)(void) = find_fn(nss, "endpwent");
+ NSS_STATUS status;
+ if (!_nss_endpwent) {
+ return -1;
+ }
+ status = _nss_endpwent();
+ if (status != NSS_STATUS_SUCCESS) {
+ errno = EINVAL;
+ return -1;
+ }
+ return 0;
+}
+
+
+/*
+ convert a name to a SID
+ caller frees
+ Return 0 on success and -1 on error
+*/
+int nss_nametosid(struct nss_state *nss, const char *name, char **sid)
+{
+ NSS_STATUS (*_nss_nametosid)(const char *, char **, char *, size_t, int *) =
+ find_fn(nss, "nametosid");
+ NSS_STATUS status;
+ int nss_errno = 0;
+ char buf[200];
+
+ if (!_nss_nametosid) {
+ return -1;
+ }
+
+ status = _nss_nametosid(name, sid, buf, sizeof(buf), &nss_errno);
+ if (status == NSS_STATUS_NOTFOUND) {
+ errno = ENOENT;
+ return -1;
+ }
+ if (status != NSS_STATUS_SUCCESS) {
+ errno = nss_errno;
+ return -1;
+ }
+
+ *sid = strdup(*sid);
+
+ return 0;
+}
+
+/*
+ convert a SID to a name
+ caller frees
+ Return 0 on success and -1 on error
+*/
+int nss_sidtoname(struct nss_state *nss, char *sid, char **name)
+{
+ NSS_STATUS (*_nss_sidtoname)(const char *, char **, char *, size_t, int *) =
+ find_fn(nss, "sidtoname");
+ NSS_STATUS status;
+ int nss_errno = 0;
+ char buf[200];
+
+ if (!_nss_sidtoname) {
+ return -1;
+ }
+
+ status = _nss_sidtoname(sid, name, buf, sizeof(buf), &nss_errno);
+ if (status == NSS_STATUS_NOTFOUND) {
+ errno = ENOENT;
+ return -1;
+ }
+ if (status != NSS_STATUS_SUCCESS) {
+ errno = nss_errno;
+ return -1;
+ }
+
+ *name = strdup(*name);
+
+ return 0;
+}
+
+/*
+ return a list of group SIDs for a user SID
+ the returned list is NULL terminated
+ Return 0 on success and -1 on error
+*/
+int nss_getusersids(struct nss_state *nss, const char *user_sid, char ***sids)
+{
+ NSS_STATUS (*_nss_getusersids)(const char *, char **, int *, char *, size_t, int *) =
+ find_fn(nss, "getusersids");
+ NSS_STATUS status;
+ int nss_errno = 0;
+ char *s;
+ int i, num_groups = 0;
+ unsigned bufsize = 10;
+ char *buf;
+
+ if (!_nss_getusersids) {
+ return -1;
+ }
+
+again:
+ buf = malloc(bufsize);
+ if (!buf) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ status = _nss_getusersids(user_sid, &s, &num_groups, buf, bufsize, &nss_errno);
+ if (status == NSS_STATUS_NOTFOUND) {
+ errno = ENOENT;
+ free(buf);
+ return -1;
+ }
+
+ if (status == NSS_STATUS_TRYAGAIN) {
+ bufsize *= 2;
+ free(buf);
+ goto again;
+ }
+
+ if (status != NSS_STATUS_SUCCESS) {
+ free(buf);
+ errno = nss_errno;
+ return -1;
+ }
+
+ if (num_groups == 0) {
+ free(buf);
+ return 0;
+ }
+
+ *sids = (char **)malloc(sizeof(char *) * (num_groups+1));
+ if (! *sids) {
+ errno = ENOMEM;
+ free(buf);
+ return -1;
+ }
+
+ for (i=0;i<num_groups;i++) {
+ (*sids)[i] = strdup(s);
+ s += strlen(s) + 1;
+ }
+ (*sids)[i] = NULL;
+
+ free(buf);
+
+ return 0;
+}
+
+
+static int nss_test_users(struct nss_state *nss)
+{
+ struct passwd pwd;
+
+ if (nss_setpwent(nss) != 0) {
+ perror("setpwent");
+ return -1;
+ }
+
+ /* loop over all users */
+ while ((nss_getpwent(nss, &pwd) == 0)) {
+ char *sid, **group_sids, *name2;
+ int i;
+
+ printf("User %s\n", pwd.pw_name);
+ if (nss_nametosid(nss, pwd.pw_name, &sid) != 0) {
+ perror("nametosid");
+ return -1;
+ }
+ printf("\tSID %s\n", sid);
+
+ if (nss_sidtoname(nss, sid, &name2) != 0) {
+ perror("sidtoname");
+ return -1;
+ }
+ printf("\tSID->name %s\n", name2);
+
+ if (nss_getusersids(nss, sid, &group_sids) != 0) {
+ perror("getusersids");
+ return -1;
+ }
+
+ printf("\tGroups:\n");
+ for (i=0; group_sids[i]; i++) {
+ printf("\t\t%s\n", group_sids[i]);
+ free(group_sids[i]);
+ }
+
+ free(sid);
+ free(name2);
+ free(group_sids);
+ }
+
+
+ if (nss_endpwent(nss) != 0) {
+ perror("endpwent");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
+ main program. It lists all users, listing user SIDs for each user
+ */
+int main(int argc, char *argv[])
+{
+ struct nss_state nss;
+ const char *so_path = "/lib/libnss_winbind.so";
+ int ret;
+
+ if (argc > 1) {
+ so_path = argv[1];
+ }
+
+ if (nss_open(&nss, so_path) != 0) {
+ perror("nss_open");
+ exit(1);
+ }
+
+ ret = nss_test_users(&nss);
+
+ nss_close(&nss);
+
+ return ret;
+}
diff --git a/packaging/Mandrake/samba2.spec.tmpl b/packaging/Mandrake/samba2.spec.tmpl
index 28bc8f9dafb..cff54d146b6 100644
--- a/packaging/Mandrake/samba2.spec.tmpl
+++ b/packaging/Mandrake/samba2.spec.tmpl
@@ -13,8 +13,8 @@
# cvs should be submitted for inclusion in samba cvs.
%define pkg_name samba
-%define ver 3.0.0rc4
-%define rel 2mdk
+%define ver 3.0.1pre3
+%define rel 3mdk
%define vscanver 0.3.3beta1
%define libsmbmajor 0
@@ -58,6 +58,7 @@
# We now do detection of the Mandrake release we are building on:
#%define build_cooker %(if [ `awk '{print $3}' /etc/mandrake-release` = "Cooker" ];then echo 1; else echo 0; fi)
#%define build_cooker %(if [[ `cat /etc/mandrake-release|grep Cooker` ]];then echo 1; else echo 0; fi)
+%define build_mdk100 %(if [ `awk '{print $4}' /etc/mandrake-release` = 10.0 ];then echo 1; else echo 0; fi)
%define build_mdk92 %(if [ `awk '{print $4}' /etc/mandrake-release` = 9.2 ];then echo 1; else echo 0; fi)
%define build_mdk91 %(if [ `awk '{print $4}' /etc/mandrake-release` = 9.1 ];then echo 1; else echo 0; fi)
%define build_mdk90 %(if [ `awk '{print $4}' /etc/mandrake-release` = 9.0 ];then echo 1; else echo 0; fi)
@@ -82,6 +83,12 @@
%define have_rpmhelper 1
# Set defaults for each version
+%if %build_mdk100
+%define build_system 1
+%define build_alternatives 1
+%define build_cupspc 1
+%endif
+
%if %build_mdk92
%define build_alternatives 1
%define build_cupspc 1
@@ -182,7 +189,7 @@
#Standard texts for descriptions:
%define message_bugzilla() %(echo -e -n "Please file bug reports for this package at Mandrake bugzilla \\n(http://qa.mandrakesoft.com) under the product name %{1}")
-%define message_system %(echo -e -n "NOTE: This is a prerelease of samba-%{samba_major}, not intended for production\\n use. Rather these packages are provided, parallel installable\\nwith samba-2.2.x, for testing purposes")
+%define message_system %(echo -e -n "NOTE: These packages of samba-%{version}, are provided, parallel installable\\nwith samba-2.2.x, to allow easy migration from samba-2.2.x to samba-%{version},\\nbut are not officially supported")
#check gcc version to disable some optimisations on gcc-3.3.1
%define gcc331 %(gcc -dumpversion|awk '{if ($1>3.3) print 1; else print 0}')
@@ -190,8 +197,8 @@
#Define sets of binaries that we can use in globs and loops:
%global commonbin net,ntlm_auth,rpcclient,smbcacls,smbcquotas,smbpasswd,smbtree,testparm,testprns
-%global serverbin editreg,pdbedit,profiles,smbcontrol,smbstatus,tdbbackup
-%global serversbin nmbd,samba,smbd
+%global serverbin editreg,pdbedit,profiles,smbcontrol,smbstatus,tdbbackup,tdbdump
+%global serversbin nmbd,samba,smbd,mkntpwd
%global clientbin findsmb,nmblookup,smbclient,smbmnt,smbmount,smbprint,smbspool,smbtar,smbumount
%global client_bin mount.cifs
@@ -222,7 +229,6 @@
%endif
Summary: Samba SMB server.
-Vendor: Samba Team
Name: %{pkg_name}%{samba_major}
%if %have_pre
@@ -258,13 +264,10 @@ Source7: README.%{name}-mandrake-rpm
Source8: samba-vscan-%{vscanver}.tar.bz2
%endif
Source10: samba-print-pdf.sh.bz2
-Source11: mount.cifs.8.bz2
Patch1: smbw.patch.bz2
-Patch3: samba-2.2.0-buildroot.patch.bz2
Patch4: samba-3.0-smbmount-sbin.patch.bz2
%if !%have_pversion
# Version specific patches: current version
-Patch100: samba-3.0.0rc4-mandrake-packaging.patch.bz2
%else
# Version specific patches: upcoming version
%endif
@@ -486,6 +489,11 @@ URL: http://www.samba.org
Summary: Samba-winbind daemon, utilities and documentation
Group: System/Servers
Requires: %{name}-common = %{version}
+%endif
+%if %build_winbind && !%build_system
+Conflicts: samba-winbind
+%endif
+%if %build_winbind
%description winbind
Provides the winbind daemon and testing tools to allow authentication
and group/user enumeration from a Windows or Samba domain controller.
@@ -504,6 +512,11 @@ Summary: Name Service Switch service for WINS
Group: System/Servers
Requires: %{name}-common = %{version}
PreReq: glibc
+%endif
+%if %build_wins && !%build_system
+Conflicts: nss_wins
+%endif
+%if %build_wins
%description -n nss_wins%{samba_major}
Provides the libnss_wins shared library which resolves NetBIOS names to
IP addresses.
@@ -525,7 +538,8 @@ Requires: %{name}-common = %{version}
%if %build_system && %{?_with_test:1}%{!?_with_test:0}
Provides: samba3-test samba3-debug
Obsoletes: samba3-test samba3-debug
-%else
+%endif
+%if !%build_system && %{?_with_test:1}%{!?_with_test:0}
Provides: samba-test samba3-debug
Obsoletes: samba3-debug
%endif
@@ -607,23 +621,29 @@ allowing the development of other software to access SMB shares.
URL: http://www.samba.org
Summary: Samba password database plugin for MySQL
Group: System/Libraries
+Requires: %{name}-server = %{version}-%{release}
+%endif
+%ifnarch alpha && %build_system
+Obsoletes: samba3-passdb-mysql
+Provides: samba3-passdb-mysql
+%endif
+%ifnarch alpha
%description passdb-mysql
The passdb-mysql package for samba provides a password database
backend allowing samba to store account details in a MySQL
database
%endif
-%ifnarch alpha && %have_pversion
-%message_bugzilla samba3-passdb-mysql
-%endif
-%ifnarch alpha && !%build_system
-%message_system
-%endif
%package passdb-xml
URL: http://www.samba.org
Summary: Samba password database plugin for XML files
Group: System/Libraries
+Requires: %{name}-server = %{version}-%{release}
+%if %build_system
+Obsoletes: samba3-passdb-xml
+Provides: samba3-passdb-xml
+%endif
%description passdb-xml
The passdb-xml package for samba provides a password database
@@ -792,12 +812,10 @@ echo -e "\n%{name}-%{version}-%{release}\n">>%{SOURCE7}
%endif
#%patch111 -p1
%patch1 -p1 -b .smbw
-%patch3 -p1 -b .buildroot
%patch4 -p1 -b .sbin
# Version specific patches: current version
%if !%have_pversion
echo "Applying patches for current version: %{ver}"
-%patch100 -p1 -b .mdk
%else
# Version specific patches: upcoming version
echo "Applying patches for new versions: %{pversion}"
@@ -990,7 +1008,7 @@ mkdir -p $RPM_BUILD_ROOT%{_datadir}/%{name}/scripts
#smbwrapper and pam_winbind not handled by make, pam_smbpass.so doesn't build
#install -m 755 source/bin/smbwrapper.so $RPM_BUILD_ROOT%{_libdir}/smbwrapper%{samba_major}.so
install -m 755 source/bin/pam_smbpass.so $RPM_BUILD_ROOT/%{_lib}/security/pam_smbpass%{samba_major}.so
-install -m 755 source/nsswitch/pam_winbind.so $RPM_BUILD_ROOT/%{_lib}/security/pam_winbind%{samba_major}.so
+install -m 755 source/nsswitch/pam_winbind.so $RPM_BUILD_ROOT/%{_lib}/security/pam_winbind.so
install -m755 source/bin/libsmbclient.a $RPM_BUILD_ROOT%{_libdir}/libsmbclient.a
pushd $RPM_BUILD_ROOT/%{_libdir}
@@ -1022,10 +1040,10 @@ popd
#libnss_* not handled by make:
# Install the nsswitch library extension file
for i in wins winbind; do
- install -m755 source/nsswitch/libnss_${i}.so $RPM_BUILD_ROOT/%{_lib}/libnss_${i}%{samba_major}.so
+ install -m755 source/nsswitch/libnss_${i}.so $RPM_BUILD_ROOT/%{_lib}/libnss_${i}.so
done
# Make link for wins and winbind resolvers
-( cd $RPM_BUILD_ROOT/%{_lib}; ln -s libnss_wins%{samba_major}.so libnss_wins%{samba_major}.so.2; ln -s libnss_winbind%{samba_major}.so libnss_winbind%{samba_major}.so.2)
+( cd $RPM_BUILD_ROOT/%{_lib}; ln -s libnss_wins.so libnss_wins.so.2; ln -s libnss_winbind.so libnss_winbind.so.2)
%if %{?_with_test:1}%{!?_with_test:0}
for i in {%{testbin}};do
@@ -1042,11 +1060,11 @@ done
install -m755 packaging/Mandrake/findsmb $RPM_BUILD_ROOT/%{_bindir}
install -m755 packaging/Mandrake/smb.init $RPM_BUILD_ROOT/%{_initrddir}/smb%{samba_major}
install -m755 packaging/Mandrake/smb.init $RPM_BUILD_ROOT/%{_sbindir}/%{name}
- install -m755 packaging/Mandrake/winbind.init $RPM_BUILD_ROOT/%{_initrddir}/winbind%{samba_major}
+ install -m755 packaging/Mandrake/winbind.init $RPM_BUILD_ROOT/%{_initrddir}/winbind
# install -m755 packaging/Mandrake/wrepld.init $RPM_BUILD_ROOT/%{_initrddir}/wrepld%{samba_major}
- install -m755 packaging/Mandrake/winbind.init $RPM_BUILD_ROOT/%{_sbindir}/winbind%{samba_major}
+ install -m755 packaging/Mandrake/winbind.init $RPM_BUILD_ROOT/%{_sbindir}/winbind
install -m644 packaging/Mandrake/samba.pamd $RPM_BUILD_ROOT/%{_sysconfdir}/pam.d/%{name}
- install -m644 packaging/Mandrake/system-auth-winbind.pamd $RPM_BUILD_ROOT/%{_sysconfdir}/pam.d/system-auth-winbind%{samba_major}
+ install -m644 packaging/Mandrake/system-auth-winbind.pamd $RPM_BUILD_ROOT/%{_sysconfdir}/pam.d/system-auth-winbind
#
install -m644 %{SOURCE1} $RPM_BUILD_ROOT/%{_sysconfdir}/logrotate.d/%{name}
# install -m644 packaging/Mandrake/samba-slapd-include.conf $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/samba-slapd.include
@@ -1070,6 +1088,7 @@ perl -pi -e 's/^(use|package)(\s+)smbldap_(\w+);$/${1}${2}smbldap_${3}%{samba_ma
perl -pi -e 's,/usr/local/sbin/mkntpwd,/usr/sbin/mkntpwd%{samba_major},g;s,553,421,g' %{buildroot}/%{_sysconfdir}/%{name}/smbldap_conf.pm
perl -pi -e 's,\$smbldap_conf::SID,\$smbldap_conf3::SID,g' %{buildroot}/%{_datadir}/%{name}/scripts/smbldap*.p?
%endif
+perl -pi -e 's,/usr/local/sbin/smbldap-passwd.pl,%{_datadir}/%{name}/scripts/smbldap-passwd.pl,g' %{buildroot}/%{_datadir}/%{name}/scripts/smbldap-useradd.pl
# Link both smbldap*.pm into vendor-perl (any better ideas?)
mkdir -p %{buildroot}/%{perl_vendorlib}
@@ -1102,7 +1121,6 @@ perl -pi -e 's/printcap name = lpstat/printcap name = cups/g' $RPM_BUILD_ROOT/%{
#install mount.cifs
install -m755 source/client/mount.cifs %{buildroot}/bin/mount.cifs%{samba_major}
-#bzcat %{SOURCE11} > %{buildroot}/%{_mandir}/man8/mount.cifs%{samba_major}.8
echo 127.0.0.1 localhost > $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/lmhosts
@@ -1173,13 +1191,13 @@ done
)
# Server/common binaries are versioned only if not system samba:
%if !%build_system
-for OLD in %{buildroot}/%{_bindir}/{%{commonbin}} %{buildroot}/%{_bindir}/{%{serverbin},wbinfo} %{buildroot}/%{_sbindir}/{%{serversbin},winbindd,swat}
+for OLD in %{buildroot}/%{_bindir}/{%{commonbin}} %{buildroot}/%{_bindir}/{%{serverbin}} %{buildroot}/%{_sbindir}/{%{serversbin},swat}
do
NEW=`echo ${OLD}%{alternative_major}`
mv $OLD $NEW -f ||:
done
# And the man pages too:
-for OLD in %{buildroot}/%{_mandir}/man?/{%{commonbin},%{serverbin},wbinfo,%{serversbin},winbindd,swat,{%testbin},smb.conf,lmhosts}*
+for OLD in %{buildroot}/%{_mandir}/man?/{%{commonbin},%{serverbin},%{serversbin},swat,{%testbin},smb.conf,lmhosts}*
do
if [ -e $OLD ]
then
@@ -1191,14 +1209,12 @@ do
fi
done
# Replace paths in config files and init scripts:
-for i in smb winbind;do
+for i in smb ;do
perl -pi -e 's,/subsys/'$i',/subsys/'$i'%{samba_major},g' $RPM_BUILD_ROOT/%{_initrddir}/${i}%{samba_major}
done
-for i in %{_sysconfdir}/%{name}/smb.conf %{_initrddir}/smb%{samba_major} %{_sbindir}/%{name} %{_initrddir}/winbind%{samba_major} %{_sbindir}/winbind%{samba_major} /%{_sysconfdir}/logrotate.d/%{name} /%{_sysconfdir}/xinetd.d/swat%{samba_major} %{_initrddir}/wrepld%{samba_major}; do
- perl -pi -e 's,/%{pkg_name},/%{name},g; s,smbd,%{_sbindir}/smbd%{samba_major},g; s,nmbd,%{_sbindir}/nmbd%{samba_major},g; s,winbindd,%{_sbindir}/winbindd%{samba_major},g; s,/usr/sbin/swat,%{_sbindir}/swat%{samba_major},g;s,wrepld,%{_sbindir}/wrepld%{samba_major},g' $RPM_BUILD_ROOT/$i;
+for i in %{_sysconfdir}/%{name}/smb.conf %{_initrddir}/smb%{samba_major} %{_sbindir}/%{name} %{_initrddir}/winbind /%{_sysconfdir}/logrotate.d/%{name} /%{_sysconfdir}/xinetd.d/swat%{samba_major} %{_initrddir}/wrepld%{samba_major}; do
+ perl -pi -e 's,/%{pkg_name},/%{name},g; s,smbd,%{_sbindir}/smbd%{samba_major},g; s,nmbd,%{_sbindir}/nmbd%{samba_major},g; s,/usr/sbin/swat,%{_sbindir}/swat%{samba_major},g;s,wrepld,%{_sbindir}/wrepld%{samba_major},g' $RPM_BUILD_ROOT/$i;
done
-# Fix pam files
-perl -pi -e 's/winbind/winbind%{samba_major}/g' $RPM_BUILD_ROOT/%{_sysconfdir}/pam.d/system-auth-winbind%{samba_major}
# Fix xinetd file for swat:
perl -pi -e 's,/usr/sbin,%{_sbindir},g' $RPM_BUILD_ROOT/%{_sysconfdir}/xinetd.d/swat%{samba_major}
%endif
@@ -1229,17 +1245,6 @@ if [ -f $i ]; then
fi
done
-# Remove the transient tdb files (modified from version in off. samba spec:
-for TDB in brlock unexpected locking messages; do
- if [ -e /var/cache/%{name}/$TDB.tdb ]; then
- rm -f /var/cache/%{name}/$TDB.tdb;
- fi;
-done
-
-if [ -d /var/lock/samba ]; then
- rm -rf /var/lock/samba
-fi
-
%post common
# Basic migration script for pre-2.2.1 users,
# since smb config moved from /etc to %{_sysconfdir}/samba
@@ -1258,12 +1263,6 @@ fi
# Let's define the proper paths for config files
perl -pi -e 's/(\/etc\/)(smb)/\1%{name}\/\2/' %{_sysconfdir}/%{name}/smb.conf
-# Let's replace lpstat with cups in older smb.conf:
-%if %build_cupspc
-echo "Updating samba printing configuration if necessary..."
-perl -pi -e 's/= lpstat/= cups/' %{_sysconfdir}/%{name}/smb.conf
-%endif
-
# Fix the logrotate.d file from smb and nmb to smbd and nmbd
if [ -f %{_sysconfdir}/logrotate.d/samba ]; then
perl -pi -e 's/smb /smbd /' %{_sysconfdir}/logrotate.d/samba
@@ -1276,14 +1275,14 @@ fi
%if %build_winbind
%post winbind
if [ $1 = 1 ]; then
- /sbin/chkconfig winbind%{samba_major} on
+ /sbin/chkconfig winbind on
cp -af %{_sysconfdir}/nsswitch.conf %{_sysconfdir}/nsswitch.conf.rpmsave
cp -af %{_sysconfdir}/nsswitch.conf %{_sysconfdir}/nsswitch.conf.rpmtemp
for i in passwd group;do
- grep ^$i %{_sysconfdir}/nsswitch.conf |grep -v 'winbind%{samba_major}' >/dev/null
+ grep ^$i %{_sysconfdir}/nsswitch.conf |grep -v 'winbind' >/dev/null
if [ $? = 0 ];then
- echo "Adding a winbind%{samba_major} entry to the $i section of %{_sysconfdir}/nsswitch.conf"
- awk '/^'$i'/ {print $0 " winbind%{samba_major}"};!/^'$i'/ {print}' %{_sysconfdir}/nsswitch.conf.rpmtemp >%{_sysconfdir}/nsswitch.conf;
+ echo "Adding a winbind entry to the $i section of %{_sysconfdir}/nsswitch.conf"
+ awk '/^'$i'/ {print $0 " winbind"};!/^'$i'/ {print}' %{_sysconfdir}/nsswitch.conf.rpmtemp >%{_sysconfdir}/nsswitch.conf;
cp -af %{_sysconfdir}/nsswitch.conf %{_sysconfdir}/nsswitch.conf.rpmtemp
else
echo "$i entry found in %{_sysconfdir}/nsswitch.conf"
@@ -1294,10 +1293,10 @@ fi
%preun winbind
if [ $1 = 0 ]; then
- echo "Removing winbind%{samba_major} entries from %{_sysconfdir}/nsswitch.conf"
- perl -pi -e 's/ winbind%{samba_major}//' %{_sysconfdir}/nsswitch.conf
+ echo "Removing winbind entries from %{_sysconfdir}/nsswitch.conf"
+ perl -pi -e 's/ winbind//' %{_sysconfdir}/nsswitch.conf
- /sbin/chkconfig winbind%{samba_major} reset
+ /sbin/chkconfig winbind reset
fi
%endif %build_winbind
@@ -1305,10 +1304,10 @@ fi
%post -n nss_wins%{samba_major}
if [ $1 = 1 ]; then
cp -af %{_sysconfdir}/nsswitch.conf %{_sysconfdir}/nsswitch.conf.rpmsave
- grep '^hosts' %{_sysconfdir}/nsswitch.conf |grep -v 'wins%{samba_major}' >/dev/null
+ grep '^hosts' %{_sysconfdir}/nsswitch.conf |grep -v 'wins' >/dev/null
if [ $? = 0 ];then
echo "Adding a wins entry to the hosts section of %{_sysconfdir}/nsswitch.conf"
- awk '/^hosts/ {print $0 " wins%{samba_major}"};!/^hosts/ {print}' %{_sysconfdir}/nsswitch.conf.rpmsave >%{_sysconfdir}/nsswitch.conf;
+ awk '/^hosts/ {print $0 " wins"};!/^hosts/ {print}' %{_sysconfdir}/nsswitch.conf.rpmsave >%{_sysconfdir}/nsswitch.conf;
else
echo "wins entry found in %{_sysconfdir}/nsswitch.conf"
fi
@@ -1319,7 +1318,7 @@ fi
%preun -n nss_wins%{samba_major}
if [ $1 = 0 ]; then
echo "Removing wins entry from %{_sysconfdir}/nsswitch.conf"
- perl -pi -e 's/ wins%{samba_major}//' %{_sysconfdir}/nsswitch.conf
+ perl -pi -e 's/ wins//' %{_sysconfdir}/nsswitch.conf
#else
# echo "Leaving %{_sysconfdir}/nsswitch.conf intact"
fi
@@ -1334,15 +1333,6 @@ if [ $1 = 0 ] ; then
# /sbin/chkconfig --level 35 smb reset
# Let's not loose /var/cache/samba
-# for i in browse.dat wins.dat brlock.tdb unexpected.tdb connections.tdb \
-#locking.tdb messages.tdb;do
-# if [ -e /var/cache/samba/$i ]; then
-# mv -f /var/cache/samba/$i /var/cache/samba/$i.BAK
-# fi;
-# done
- if [ -d /var/log/%{name} ]; then
- rm -rf /var/log/%{name}/*
- fi
if [ -d /var/cache/%{name} ]; then
mv -f /var/cache/%{name} /var/cache/%{name}.BAK
fi
@@ -1384,37 +1374,30 @@ echo -n " --slave ${i} ${j} ${i}%{alternative_major}";done) \
update-alternatives --auto smbclient
%preun client
-[ $1 = 0 ] && update-alternatives --remove smbclient %{_bindir}/smbclient%{alternative_major}
+[ $1 = 0 ] && update-alternatives --remove smbclient %{_bindir}/smbclient%{alternative_major} ||:
%endif
-%triggerpostun -- samba < 1.9.18p7
-
-if [ $1 != 0 ]; then
- /sbin/chkconfig --level 35 smb on
-fi
-
-%triggerpostun -- samba < 2.0.5a-3, samba >= 2.0.0
-
-if [ $1 != 0 ]; then
- [ ! -d /var/lock/samba ] && mkdir -m 0755 /var/lock/samba ||:
- [ ! -d /var/spool/samba ] && mkdir -m 1777 /var/spool/samba ||:
- [ -f %{_sysconfdir}/inetd.conf ] && chmod 644 %{_sysconfdir}/services %{_sysconfdir}/inetd.conf ||:
-fi
+%if %build_alternatives
+%triggerpostun client -- samba-client, samba2-client
+[ ! -e %{_bindir}/smbclient ] && update-alternatives --auto smbclient || :
+%endif
%files server
%defattr(-,root,root)
#%attr(-,root,root) /sbin/*
-%{_sbindir}/%{name}
-%{_sbindir}/smbd%{samba_major}
-%{_sbindir}/nmbd%{samba_major}
+%(for i in %{_sbindir}/{%{serversbin}}%{samba_major};do echo $i;done)
+#%{_sbindir}/%{name}
+#%{_sbindir}/smbd%{samba_major}
+#%{_sbindir}/nmbd%{samba_major}
+#%{_sbindir}/mkntpwd%{samba_major}
#%{_sbindir}/wrepld%{samba_major}
-%{_bindir}/smbcontrol%{samba_major}
-%{_sbindir}/mkntpwd%{samba_major}
-%{_bindir}/smbstatus%{samba_major}
-%{_bindir}/pdbedit%{samba_major}
-%{_bindir}/tdbbackup%{samba_major}
-%{_bindir}/profiles%{samba_major}
-%{_bindir}/editreg%{samba_major}
+%(for i in %{_bindir}/{%{serverbin}}%{samba_major};do echo $i;done)
+#%{_bindir}/smbcontrol%{samba_major}
+#%{_bindir}/smbstatus%{samba_major}
+#%{_bindir}/pdbedit%{samba_major}
+#%{_bindir}/tdbbackup%{samba_major}
+#%{_bindir}/profiles%{samba_major}
+#%{_bindir}/editreg%{samba_major}
%attr(755,root,root) /%{_lib}/security/pam_smbpass*
%dir %{_libdir}/%{name}/vfs
%{_libdir}/%{name}/vfs/*.so
@@ -1439,7 +1422,7 @@ fi
%attr(775,root,adm) %dir %{_localstatedir}/%{name}/netlogon
%attr(755,root,root) %dir %{_localstatedir}/%{name}/profiles
%attr(755,root,root) %dir %{_localstatedir}/%{name}/printers
-%attr(775,root,adm) %dir %{_localstatedir}/%{name}/printers/*
+%attr(2775,root,adm) %dir %{_localstatedir}/%{name}/printers/*
%attr(1777,root,root) %dir /var/spool/%{name}
%dir %{_datadir}/%{name}
%dir %{_datadir}/%{name}/scripts
@@ -1477,6 +1460,14 @@ fi
%lang(ja) %{_datadir}/swat%{samba_major}/lang/ja
%lang(tr) %{_datadir}/swat%{samba_major}/lang/tr
%{_mandir}/man8/swat*.8*
+%lang(de) %{_libdir}/%{name}/de.msg
+%lang(en) %{_libdir}/%{name}/en.msg
+%lang(fr) %{_libdir}/%{name}/fr.msg
+%lang(it) %{_libdir}/%{name}/it.msg
+%lang(ja) %{_libdir}/%{name}/ja.msg
+%lang(nl) %{_libdir}/%{name}/nl.msg
+%lang(pl) %{_libdir}/%{name}/pl.msg
+%lang(tr) %{_libdir}/%{name}/tr.msg
#%doc swat/README
%files client
@@ -1521,18 +1512,18 @@ fi
%attr(-,root,root) %{_localstatedir}/%{name}/codepages
%{_mandir}/man5/smb.conf*.5*
%{_mandir}/man5/lmhosts*.5*
-%{_mandir}/man7/Samba*.7*
+#%{_mandir}/man7/Samba*.7*
%dir %{_datadir}/swat%{samba_major}
%if %build_winbind
%files winbind
%defattr(-,root,root)
-%{_sbindir}/winbindd%{samba_major}
-%{_sbindir}/winbind%{samba_major}
-%{_bindir}/wbinfo%{samba_major}
+%{_sbindir}/winbindd
+%{_sbindir}/winbind
+%{_bindir}/wbinfo
%attr(755,root,root) /%{_lib}/security/pam_winbind*
-%attr(755,root,root) /%{_lib}/libnss_winbind%{samba_major}*
-%attr(-,root,root) %config(noreplace) %{_initrddir}/winbind%{samba_major}
+%attr(755,root,root) /%{_lib}/libnss_winbind*
+%attr(-,root,root) %config(noreplace) %{_initrddir}/winbind
%attr(-,root,root) %config(noreplace) %{_sysconfdir}/pam.d/system-auth-winbind*
%{_mandir}/man8/winbindd*.8*
%{_mandir}/man1/wbinfo*.1*
@@ -1541,7 +1532,7 @@ fi
%if %build_wins
%files -n nss_wins%{samba_major}
%defattr(-,root,root)
-%attr(755,root,root) /%{_lib}/libnss_wins%{samba_major}.so*
+%attr(755,root,root) /%{_lib}/libnss_wins.so*
%endif
%if %{?_with_test:1}%{!?_with_test:0}
@@ -1656,6 +1647,29 @@ fi
%exclude %{_mandir}/man1/smbsh*.1*
%changelog
+* Sun Nov 16 2003 Buchan Milne <bgmilne@linux-mandrake.com> 3.0.1-0.rpe3.3mdk
+- Ensure printer drivers keep permissions by default (setgid and inherit perms)
+
+* Fri Nov 14 2003 Buchan Milne <bgmilne@linux-mandrake.com> 3.0.1-0.pre3.2mdk
+- 3.0.1pre3
+- Add support for Mandrake 10.0 (as system samba)
+- Fix alternatives triggers
+- Fix obsoletes
+
+* Mon Nov 10 2003 Buchan Milne <bgmilne@linux-mandrake.com> 3.0.1-0.pre2.2mdk
+- 3.0.1pre2
+- misc spec files (pointed out by Luca Olivetti)
+- Fix path to smbldap-passwd.pl
+- Only allow one copy of winbind and nss_wins
+- Add trigger for alternatives
+
+* Sun Oct 12 2003 Buchan Milne <bgmilne@linux-mandrake.com> 3.0.1-0.pre1.2mdk
+- 3.0.1pre1
+- remove buildroot patch (p3), fixed upstream
+
+* Thu Sep 25 2003 Buchan Milne <bgmilne@linux-mandrake.com> 3.0.0-2mdk
+- 3.0.0 final
+
* Sat Sep 13 2003 Buchan Milne <bgmilne@linux-mandrake.com> 3.0.0-0.rc4.2mdk
- rc4
- Don't update alternatives in pre/post scripts when not using alternatives
diff --git a/packaging/Mandrake/smb.conf b/packaging/Mandrake/smb.conf
index 4981d22174b..6c1c05fa52e 100644
--- a/packaging/Mandrake/smb.conf
+++ b/packaging/Mandrake/smb.conf
@@ -263,7 +263,10 @@
# Use the samba2 LDAP schema:
; passdb backend = ldapsam_compat:ldaps://ldap.mydomain.com smbpasswd guest
-# idmap uid account range:
+# Idmap settings:
+# Idmap backend to use:
+; idmap backend = ldap:ldap://ldap.mydomain.com
+
# This is a range of unix user-id's that samba will map non-unix RIDs to,
# such as when using Winbind
; idmap uid = 10000-20000
@@ -388,10 +391,13 @@
# NOTE: If you have a CUPS print system there is no need to
# specifically define each individual printer.
# You must configure the samba printers with the appropriate Windows
-# drivers on your Windows clients. On the Samba server no filtering is
+# drivers on your Windows clients or upload the printer driver to the
+# server from Windows (NT/2000/XP). On the Samba server no filtering is
# done. If you wish that the server provides the driver and the clients
# send PostScript ("Generic PostScript Printer" under Windows), you have
-# to swap the 'print command' line below with the commented one.
+# to use 'printcap name = cups' or swap the 'print command' line below
+# with the commented one. Note that print commands only work if not using
+# 'printing=cups'
[printers]
comment = All Printers
path = /var/spool/samba
@@ -406,10 +412,6 @@
# =====================================
print command = lpr-cups -P %p -o raw %s -r # using client side printer drivers.
; print command = lpr-cups -P %p %s # using cups own drivers (use generic PostScript on clients).
-# The following two commands are the samba defaults for printing=cups
-# change them only if you need different options:
-; lpq command = lpq -P %p
-; lprm command = cancel %p-%j
# This share is used for Windows NT-style point-and-print support.
# To be able to install drivers, you need to be either root, or listed
@@ -417,17 +419,26 @@
# to the directory and share definition to be able to upload the drivers.
# For more information on this, please see the Printing Support Section of
# /usr/share/doc/samba-<version>/docs/Samba-HOWTO-Collection.pdf
+#
+# A special case is using the CUPS Windows Postscript driver, which allows
+# all features available via CUPS on the client, by publishing the ppd file
+# and the cups driver by using the 'cupsaddsmb' tool. This requires the
+# installation of the CUPS driver (http://www.cups.org/windows.php)
+# on the server, but doesn't require you to use Windows at all :-).
[print$]
path = /var/lib/samba/printers
browseable = yes
- read only = yes
write list = @adm root
guest ok = yes
+ inherit permissions = yes
+ # Settings suitable for Winbind:
+ ; write list = @"Domain Admins" root
+ ; force group = +@"Domain Admins"
# A useful application of samba is to make a PDF-generation service
# To streamline this, install windows postscript drivers (preferably colour)
# on the samba server, so that clients can automatically install them.
-# Note that this only works if 'printcap name' is *not* set to 'cups'
+# Note that this only works if 'printing' is *not* set to 'cups'
[pdf-generator]
path = /var/tmp
diff --git a/packaging/Solaris/samba.server.master b/packaging/Solaris/samba.server.master
index 6de77780b34..d8bea2421c3 100755
--- a/packaging/Solaris/samba.server.master
+++ b/packaging/Solaris/samba.server.master
@@ -37,7 +37,7 @@ case "$1" in
'restart')
killproc nmbd
killproc smbd
- BASE=/usr/local/samba
+ BASE=__BASEDIR__/samba
$BASE/bin/smbd -D -s$BASE/lib/smb.conf
$BASE/bin/nmbd -D -l$BASE/var/log -s$BASE/lib/smb.conf
;;
diff --git a/source/Makefile.in b/source/Makefile.in
index 4aa34020d6c..7ac07dbad72 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -294,6 +294,7 @@ MYSQL_OBJ = passdb/pdb_mysql.o
DEVEL_HELP_WEIRD_OBJ = modules/weird.o
CP850_OBJ = modules/CP850.o
CP437_OBJ = modules/CP437.o
+CHARSET_MACOSXFS_OBJ = modules/charset_macosxfs.o
GROUPDB_OBJ = groupdb/mapping.o
@@ -494,7 +495,8 @@ CLIENT_OBJ = $(CLIENT_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \
NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_ads_cldap.o utils/net_help.o \
utils/net_rap.o utils/net_rpc.o utils/net_rpc_samsync.o \
utils/net_rpc_join.o utils/net_time.o utils/net_lookup.o \
- utils/net_cache.o utils/net_groupmap.o utils/net_idmap.o
+ utils/net_cache.o utils/net_groupmap.o utils/net_idmap.o \
+ utils/net_status.o
NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \
$(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
@@ -1019,7 +1021,7 @@ bin/librpc_echo.@SHLIBEXT@: $(RPC_ECHO_OBJ)
bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy
@echo "Linking $@"
- @$(LINK) -o $@ $(WINBINDD_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
+ @$(LINK) -o $@ $(WINBINDD_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS)
# Please don't add .o files to libnss_winbind, libnss_wins, or the pam_winbind
# libraries. Add to the appropriate PICOBJ variable instead.
@@ -1103,6 +1105,11 @@ bin/CP437.@SHLIBEXT@: $(CP437_OBJ:.o=.@PICSUFFIX@)
@$(SHLD) $(LDSHFLAGS) -o $@ $(CP437_OBJ:.o=.@PICSUFFIX@) \
@SONAMEFLAG@`basename $@`
+bin/macosxfs.@SHLIBEXT@: $(CHARSET_MACOSXFS_OBJ:.o=.po)
+ @echo "Building plugin $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(CHARSET_MACOSXFS_OBJ:.o=.po) \
+ -framework CoreFoundation @SONAMEFLAG@`basename $@`
+
bin/xml.@SHLIBEXT@: $(XML_OBJ:.o=.@PICSUFFIX@)
@echo "Building plugin $@"
@$(SHLD) $(LDSHFLAGS) -o $@ $(XML_OBJ:.o=.@PICSUFFIX@) @XML_LIBS@ \
diff --git a/source/VERSION b/source/VERSION
index 3ee23fd66a3..d727326a6ac 100644
--- a/source/VERSION
+++ b/source/VERSION
@@ -41,7 +41,7 @@ SAMBA_VERSION_REVISION=
# e.g. SAMBA_VERSION_PRE_RELEASE=1 #
# -> "2.2.9pre1" #
########################################################
-SAMBA_VERSION_PRE_RELEASE=3
+SAMBA_VERSION_PRE_RELEASE=
########################################################
# For 'rc' releases the version will be #
@@ -51,7 +51,7 @@ SAMBA_VERSION_PRE_RELEASE=3
# e.g. SAMBA_VERSION_RC_RELEASE=1 #
# -> "3.0.0rc1" #
########################################################
-SAMBA_VERSION_RC_RELEASE=
+SAMBA_VERSION_RC_RELEASE=1
########################################################
# For 'beta' releases the version will be #
diff --git a/source/auth/auth.c b/source/auth/auth.c
index 553d9a686e3..1b49699fbca 100644
--- a/source/auth/auth.c
+++ b/source/auth/auth.c
@@ -88,6 +88,8 @@ static const uint8 *get_ntlm_challenge(struct auth_context *auth_context)
return auth_context->challenge.data;
}
+ auth_context->challenge_may_be_modified = False;
+
for (auth_method = auth_context->auth_method_list; auth_method; auth_method = auth_method->next) {
if (auth_method->get_chal == NULL) {
DEBUG(5, ("auth_get_challenge: module %s did not want to specify a challenge\n", auth_method->name));
@@ -127,6 +129,7 @@ static const uint8 *get_ntlm_challenge(struct auth_context *auth_context)
chal, sizeof(chal));
challenge_set_by = "random";
+ auth_context->challenge_may_be_modified = True;
}
DEBUG(5, ("auth_context challenge created by %s\n", challenge_set_by));
@@ -318,9 +321,20 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
static void free_auth_context(struct auth_context **auth_context)
{
- if (*auth_context != NULL)
+ auth_methods *auth_method;
+
+ if (*auth_context) {
+ /* Free private data of context's authentication methods */
+ for (auth_method = (*auth_context)->auth_method_list; auth_method; auth_method = auth_method->next) {
+ if (auth_method->free_private_data) {
+ auth_method->free_private_data (&auth_method->private_data);
+ auth_method->private_data = NULL;
+ }
+ }
+
talloc_destroy((*auth_context)->mem_ctx);
- *auth_context = NULL;
+ *auth_context = NULL;
+ }
}
/***************************************************************************
diff --git a/source/auth/auth_ntlmssp.c b/source/auth/auth_ntlmssp.c
index 3af0cbaada4..a5ce101e5e7 100644
--- a/source/auth/auth_ntlmssp.c
+++ b/source/auth/auth_ntlmssp.c
@@ -23,13 +23,59 @@
#include "includes.h"
-static const uint8 *auth_ntlmssp_get_challenge(struct ntlmssp_state *ntlmssp_state)
+/**
+ * Return the challenge as determined by the authentication subsystem
+ * @return an 8 byte random challenge
+ */
+
+static const uint8 *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state)
{
AUTH_NTLMSSP_STATE *auth_ntlmssp_state = ntlmssp_state->auth_context;
return auth_ntlmssp_state->auth_context->get_ntlm_challenge(auth_ntlmssp_state->auth_context);
}
-static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state)
+/**
+ * Some authentication methods 'fix' the challenge, so we may not be able to set it
+ *
+ * @return If the effective challenge used by the auth subsystem may be modified
+ */
+static BOOL auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
+{
+ AUTH_NTLMSSP_STATE *auth_ntlmssp_state = ntlmssp_state->auth_context;
+ struct auth_context *auth_context = auth_ntlmssp_state->auth_context;
+
+ return auth_context->challenge_may_be_modified;
+}
+
+/**
+ * NTLM2 authentication modifies the effective challange,
+ * @param challenge The new challenge value
+ */
+static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
+{
+ AUTH_NTLMSSP_STATE *auth_ntlmssp_state = ntlmssp_state->auth_context;
+ struct auth_context *auth_context = auth_ntlmssp_state->auth_context;
+
+ SMB_ASSERT(challenge->length == 8);
+
+ auth_context->challenge = data_blob_talloc(auth_context->mem_ctx,
+ challenge->data, challenge->length);
+
+ auth_context->challenge_set_by = "NTLMSSP callback (NTLM2)";
+
+ DEBUG(5, ("auth_context challenge set by %s\n", auth_context->challenge_set_by));
+ DEBUG(5, ("challenge is: \n"));
+ dump_data(5, (const char *)auth_context->challenge.data, auth_context->challenge.length);
+ return NT_STATUS_OK;
+}
+
+/**
+ * Check the password on an NTLMSSP login.
+ *
+ * Return the session keys used on the connection.
+ */
+
+static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *nt_session_key, DATA_BLOB *lm_session_key)
{
AUTH_NTLMSSP_STATE *auth_ntlmssp_state = ntlmssp_state->auth_context;
uint32 auth_flags = AUTH_FLAG_NONE;
@@ -45,7 +91,7 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state)
auth_flags |= AUTH_FLAG_NTLM_RESP;
} else if (auth_ntlmssp_state->ntlmssp_state->nt_resp.length > 24) {
auth_flags |= AUTH_FLAG_NTLMv2_RESP;
- };
+ }
/* the client has given us its machine name (which we otherwise would not get on port 445).
we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
@@ -71,10 +117,26 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state)
return nt_status;
}
- nt_status = auth_ntlmssp_state->auth_context->check_ntlm_password(auth_ntlmssp_state->auth_context, user_info, &auth_ntlmssp_state->server_info);
-
+ nt_status = auth_ntlmssp_state->auth_context->check_ntlm_password(auth_ntlmssp_state->auth_context,
+ user_info, &auth_ntlmssp_state->server_info);
+
free_user_info(&user_info);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+ if (auth_ntlmssp_state->server_info->nt_session_key.length) {
+ DEBUG(10, ("Got NT session key of length %u\n", auth_ntlmssp_state->server_info->nt_session_key.length));
+ *nt_session_key = data_blob_talloc(auth_ntlmssp_state->mem_ctx,
+ auth_ntlmssp_state->server_info->nt_session_key.data,
+ auth_ntlmssp_state->server_info->nt_session_key.length);
+ }
+ if (auth_ntlmssp_state->server_info->lm_session_key.length) {
+ DEBUG(10, ("Got LM session key of length %u\n", auth_ntlmssp_state->server_info->lm_session_key.length));
+ *lm_session_key = data_blob_talloc(auth_ntlmssp_state->mem_ctx,
+ auth_ntlmssp_state->server_info->lm_session_key.data,
+ auth_ntlmssp_state->server_info->lm_session_key.length);
+ }
return nt_status;
}
@@ -106,18 +168,20 @@ NTSTATUS auth_ntlmssp_start(AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
(*auth_ntlmssp_state)->ntlmssp_state->auth_context = (*auth_ntlmssp_state);
(*auth_ntlmssp_state)->ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
+ (*auth_ntlmssp_state)->ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
+ (*auth_ntlmssp_state)->ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
(*auth_ntlmssp_state)->ntlmssp_state->check_password = auth_ntlmssp_check_password;
(*auth_ntlmssp_state)->ntlmssp_state->server_role = lp_server_role();
return NT_STATUS_OK;
}
-NTSTATUS auth_ntlmssp_end(AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
+void auth_ntlmssp_end(AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
{
TALLOC_CTX *mem_ctx = (*auth_ntlmssp_state)->mem_ctx;
if ((*auth_ntlmssp_state)->ntlmssp_state) {
- ntlmssp_server_end(&(*auth_ntlmssp_state)->ntlmssp_state);
+ ntlmssp_end(&(*auth_ntlmssp_state)->ntlmssp_state);
}
if ((*auth_ntlmssp_state)->auth_context) {
((*auth_ntlmssp_state)->auth_context->free)(&(*auth_ntlmssp_state)->auth_context);
@@ -127,11 +191,10 @@ NTSTATUS auth_ntlmssp_end(AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
}
talloc_destroy(mem_ctx);
*auth_ntlmssp_state = NULL;
- return NT_STATUS_OK;
}
NTSTATUS auth_ntlmssp_update(AUTH_NTLMSSP_STATE *auth_ntlmssp_state,
const DATA_BLOB request, DATA_BLOB *reply)
{
- return ntlmssp_server_update(auth_ntlmssp_state->ntlmssp_state, request, reply);
+ return ntlmssp_update(auth_ntlmssp_state->ntlmssp_state, request, reply);
}
diff --git a/source/auth/auth_sam.c b/source/auth/auth_sam.c
index 2a00b6fb807..7352a9685be 100644
--- a/source/auth/auth_sam.c
+++ b/source/auth/auth_sam.c
@@ -33,7 +33,7 @@
static BOOL smb_pwd_check_ntlmv1(const DATA_BLOB *nt_response,
const uchar *part_passwd,
const DATA_BLOB *sec_blob,
- uint8 user_sess_key[16])
+ DATA_BLOB *user_sess_key)
{
/* Finish the encryption of part_passwd. */
uchar p24[24];
@@ -56,7 +56,8 @@ static BOOL smb_pwd_check_ntlmv1(const DATA_BLOB *nt_response,
SMBOWFencrypt(part_passwd, sec_blob->data, p24);
if (user_sess_key != NULL) {
- SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key);
+ *user_sess_key = data_blob(NULL, 16);
+ SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key->data);
}
@@ -83,7 +84,7 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB *ntv2_response,
const uchar *part_passwd,
const DATA_BLOB *sec_blob,
const char *user, const char *domain,
- uint8 user_sess_key[16])
+ DATA_BLOB *user_sess_key)
{
/* Finish the encryption of part_passwd. */
uchar kr[16];
@@ -120,7 +121,8 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB *ntv2_response,
SMBOWFencrypt_ntv2(kr, sec_blob, &client_key_data, value_from_encryption);
if (user_sess_key != NULL) {
- SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key);
+ *user_sess_key = data_blob(NULL, 16);
+ SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key->data);
}
#if DEBUG_PASSWORD
@@ -148,7 +150,8 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
TALLOC_CTX *mem_ctx,
SAM_ACCOUNT *sampass,
const auth_usersupplied_info *user_info,
- uint8 user_sess_key[16])
+ DATA_BLOB *user_sess_key,
+ DATA_BLOB *lm_sess_key)
{
uint16 acct_ctrl;
const uint8 *nt_pw, *lm_pw;
@@ -225,6 +228,16 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
if (smb_pwd_check_ntlmv1(&user_info->nt_resp,
nt_pw, &auth_context->challenge,
user_sess_key)) {
+ /* The LM session key for this response is not very secure,
+ so use it only if we otherwise allow LM authentication */
+ lm_pw = pdb_get_lanman_passwd(sampass);
+
+ if (lp_lanman_auth() && lm_pw) {
+ uint8 first_8_lm_hash[16];
+ memcpy(first_8_lm_hash, lm_pw, 8);
+ memset(first_8_lm_hash + 8, '\0', 8);
+ *lm_sess_key = data_blob(first_8_lm_hash, 16);
+ }
return NT_STATUS_OK;
} else {
DEBUG(3,("sam_password_ok: NT MD4 password check failed for user %s\n",pdb_get_username(sampass)));
@@ -252,7 +265,12 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
DEBUG(4,("sam_password_ok: Checking LM password\n"));
if (smb_pwd_check_ntlmv1(&user_info->lm_resp,
lm_pw, &auth_context->challenge,
- user_sess_key)) {
+ NULL)) {
+ uint8 first_8_lm_hash[16];
+ memcpy(first_8_lm_hash, lm_pw, 8);
+ memset(first_8_lm_hash + 8, '\0', 8);
+ *user_sess_key = data_blob(first_8_lm_hash, 16);
+ *lm_sess_key = data_blob(first_8_lm_hash, 16);
return NT_STATUS_OK;
}
}
@@ -272,7 +290,7 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
nt_pw, &auth_context->challenge,
user_info->smb_name.str,
user_info->client_domain.str,
- user_sess_key)) {
+ NULL)) {
return NT_STATUS_OK;
}
@@ -281,7 +299,7 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
nt_pw, &auth_context->challenge,
user_info->smb_name.str,
"",
- user_sess_key)) {
+ NULL)) {
return NT_STATUS_OK;
}
@@ -292,7 +310,19 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
if (lp_ntlm_auth()) {
if (smb_pwd_check_ntlmv1(&user_info->lm_resp,
nt_pw, &auth_context->challenge,
- user_sess_key)) {
+ NULL)) {
+ /* The session key for this response is still very odd.
+ It not very secure, so use it only if we otherwise
+ allow LM authentication */
+ lm_pw = pdb_get_lanman_passwd(sampass);
+
+ if (lp_lanman_auth() && lm_pw) {
+ uint8 first_8_lm_hash[16];
+ memcpy(first_8_lm_hash, lm_pw, 8);
+ memset(first_8_lm_hash + 8, '\0', 8);
+ *user_sess_key = data_blob(first_8_lm_hash, 16);
+ *lm_sess_key = data_blob(first_8_lm_hash, 16);
+ }
return NT_STATUS_OK;
}
DEBUG(3,("sam_password_ok: LM password, NT MD4 password in LM field and LMv2 failed for user %s\n",pdb_get_username(sampass)));
@@ -301,7 +331,6 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
DEBUG(3,("sam_password_ok: LM password and LMv2 failed for user %s, and NT MD4 password in LM field not permitted\n",pdb_get_username(sampass)));
return NT_STATUS_WRONG_PASSWORD;
}
-
}
/* Should not be reached, but if they send nothing... */
@@ -421,8 +450,8 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
SAM_ACCOUNT *sampass=NULL;
BOOL ret;
NTSTATUS nt_status;
- uint8 user_sess_key[16];
- const uint8* lm_hash;
+ DATA_BLOB user_sess_key = data_blob(NULL, 0);
+ DATA_BLOB lm_sess_key = data_blob(NULL, 0);
if (!user_info || !auth_context) {
return NT_STATUS_UNSUCCESSFUL;
@@ -446,7 +475,8 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
return NT_STATUS_NO_SUCH_USER;
}
- nt_status = sam_password_ok(auth_context, mem_ctx, sampass, user_info, user_sess_key);
+ nt_status = sam_password_ok(auth_context, mem_ctx, sampass,
+ user_info, &user_sess_key, &lm_sess_key);
if (!NT_STATUS_IS_OK(nt_status)) {
pdb_free_sam(&sampass);
@@ -465,12 +495,8 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
return nt_status;
}
- lm_hash = pdb_get_lanman_passwd((*server_info)->sam_account);
- if (lm_hash) {
- memcpy((*server_info)->first_8_lm_hash, lm_hash, 8);
- }
-
- memcpy((*server_info)->session_key, user_sess_key, sizeof(user_sess_key));
+ (*server_info)->nt_session_key = user_sess_key;
+ (*server_info)->lm_session_key = lm_sess_key;
return nt_status;
}
diff --git a/source/auth/auth_server.c b/source/auth/auth_server.c
index b57293943c0..41adc217841 100644
--- a/source/auth/auth_server.c
+++ b/source/auth/auth_server.c
@@ -143,8 +143,10 @@ static void free_server_private_data(void **private_data_pointer)
{
struct cli_state **cli = (struct cli_state **)private_data_pointer;
if (*cli && (*cli)->initialised) {
+ DEBUG(10, ("Shutting down smbserver connection\n"));
cli_shutdown(*cli);
}
+ *private_data_pointer = NULL;
}
/****************************************************************************
diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c
index d7d7f53e2d4..5d3f8f02777 100644
--- a/source/auth/auth_util.c
+++ b/source/auth/auth_util.c
@@ -900,7 +900,13 @@ NTSTATUS make_server_info_guest(auth_serversupplied_info **server_info)
nt_status = make_server_info_sam(server_info, sampass);
if (NT_STATUS_IS_OK(nt_status)) {
+ static const char zeros[16];
(*server_info)->guest = True;
+
+ /* annoying, but the Guest really does have a session key,
+ and it is all zeros! */
+ (*server_info)->nt_session_key = data_blob(zeros, sizeof(zeros));
+ (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
}
return nt_status;
@@ -992,6 +998,8 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
auth_serversupplied_info **server_info,
NET_USER_INFO_3 *info3)
{
+ static const char zeros[16];
+
NTSTATUS nt_status = NT_STATUS_OK;
char *found_username;
const char *nt_domain;
@@ -1210,10 +1218,20 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
(*server_info)->ptok = token;
SAFE_FREE(all_group_SIDs);
+
+ /* ensure we are never given NULL session keys */
- memcpy((*server_info)->session_key, info3->user_sess_key, sizeof((*server_info)->session_key)/* 16 */);
- memcpy((*server_info)->first_8_lm_hash, info3->padding, 8);
+ if (memcmp(info3->user_sess_key, zeros, sizeof(zeros)) == 0) {
+ (*server_info)->nt_session_key = data_blob(NULL, 0);
+ } else {
+ (*server_info)->nt_session_key = data_blob(info3->user_sess_key, sizeof(info3->user_sess_key));
+ }
+ if (memcmp(info3->padding, zeros, sizeof(zeros)) == 0) {
+ (*server_info)->lm_session_key = data_blob(NULL, 0);
+ } else {
+ (*server_info)->lm_session_key = data_blob(info3->padding, 16);
+ }
return NT_STATUS_OK;
}
@@ -1256,6 +1274,8 @@ void free_server_info(auth_serversupplied_info **server_info)
delete_nt_token( &(*server_info)->ptok );
SAFE_FREE((*server_info)->groups);
SAFE_FREE((*server_info)->unix_name);
+ data_blob_free(&(*server_info)->lm_session_key);
+ data_blob_free(&(*server_info)->nt_session_key);
ZERO_STRUCT(**server_info);
}
SAFE_FREE(*server_info);
diff --git a/source/configure.in b/source/configure.in
index 6a9a8f0f15e..174a48b87e3 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -126,6 +126,25 @@ AC_ARG_WITH(logfilebase,
;;
esac])
+AC_ARG_WITH(cfenc,
+[ --with-cfenc=HEADERDIR Use internal CoreFoundation encoding API
+ for optimization (Mac OS X/Darwin only)],
+[
+# May be in source $withval/CoreFoundation/StringEncodings.subproj.
+# Should have been in framework $withval/CoreFoundation.framework/Headers.
+for d in \
+ $withval/CoreFoundation/StringEncodings.subproj \
+ $withval/StringEncodings.subproj \
+ $withval/CoreFoundation.framework/Headers \
+ $withval/Headers \
+ $withval
+do
+ if test -r $d/CFStringEncodingConverter.h; then
+ ln -sfh $d include/CoreFoundation
+ fi
+done
+])
+
AC_SUBST(configdir)
AC_SUBST(lockdir)
AC_SUBST(piddir)
@@ -201,6 +220,10 @@ OLD_CFLAGS=${CFLAGS}
AC_PROG_CC
CFLAGS=${OLD_CFLAGS}
+OLD_CFLAGS=${CFLAGS}
+AC_PROG_CPP
+CFLAGS=${OLD_CFLAGS}
+
AC_PROG_INSTALL
AC_PROG_AWK
AC_PATH_PROG(PERL, perl)
@@ -430,7 +453,7 @@ case "$host_os" in
*)
CPPFLAGS="$CPPFLAGS -D_SYSV"
AC_DEFINE(_SYSV, 1, [Whether to enable System V compatibility])
- esac
+ esac
;;
#
# Tests needed for SINIX large file support.
@@ -502,15 +525,15 @@ main() {
#endif
}
], [LINUX_LFS_SUPPORT=yes], [LINUX_LFS_SUPPORT=no], [LINUX_LFS_SUPPORT=cross])
- CPPFLAGS="$old_CPPFLAGS"
- if test x$LINUX_LFS_SUPPORT = xyes ; then
- CPPFLAGS="-D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE $CPPFLAGS"
- AC_DEFINE(_LARGEFILE64_SOURCE, 1, [Whether to enable large file support])
- AC_DEFINE(_FILE_OFFSET_BITS, 64, [File offset bits])
- AC_DEFINE(_GNU_SOURCE, 1, [Whether to use GNU libc extensions])
- fi
- AC_MSG_RESULT([$LINUX_LFS_SUPPORT])
- ;;
+ CPPFLAGS="$old_CPPFLAGS"
+ if test x$LINUX_LFS_SUPPORT = xyes ; then
+ CPPFLAGS="-D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE $CPPFLAGS"
+ AC_DEFINE(_LARGEFILE64_SOURCE, 1, [Whether to enable large file support])
+ AC_DEFINE(_FILE_OFFSET_BITS, 64, [File offset bits])
+ AC_DEFINE(_GNU_SOURCE, 1, [Whether to use GNU libc extensions])
+ fi
+ AC_MSG_RESULT([$LINUX_LFS_SUPPORT])
+ ;;
#
# MacOS X is the *only* system that uses compose character in utf8. This
@@ -528,10 +551,16 @@ main() {
# use that instead of plain dlsym.
AC_CHECK_LIB(dl,dlopen)
- AC_CHECK_FUNCS(dlsym_prepend_underscore,
- [CPPFLAGS="$CPPFLAGS -Ddlsym=dlsym_prepend_underscore"])
+ AC_CHECK_FUNCS(dlsym_prepend_underscore,[CPPFLAGS="$CPPFLAGS -Ddlsym=dlsym_prepend_underscore"])
- ;;
+#Add a system specific charset module.
+
+ default_shared_modules="$default_shared_modules charset_macosxfs"
+ old_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="-Iinclude $CPPFLAGS"
+ AC_CHECK_HEADERS([CoreFoundation/CFStringEncodingConverter.h], [], [AC_CHECK_HEADERS([CFStringEncodingConverter.h])])
+ CPPFLAGS="$old_CPPFLAGS"
+ ;;
*hurd*)
AC_MSG_CHECKING([for LFS support])
old_CPPFLAGS="$CPPFLAGS"
@@ -3931,9 +3960,12 @@ WINBIND_WINS_NSS="nsswitch/libnss_wins.$SHLIBEXT"
WINBIND_NSS_LDSHFLAGS=$LDSHFLAGS
case "$host_os" in
- *linux*|*freebsd*)
+ *linux*)
WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_linux.o"
;;
+ *freebsd5*)
+ WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_freebsd.o"
+ ;;
*irix*)
# IRIX has differently named shared libraries
WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_irix.o"
@@ -4164,6 +4196,7 @@ SMB_SUBSYSTEM(IDMAP,sam/idmap.o)
SMB_MODULE(charset_weird, modules/weird.o, "bin/weird.$SHLIBEXT", CHARSET)
SMB_MODULE(charset_CP850, modules/CP850.o, "bin/CP850.$SHLIBEXT", CHARSET)
SMB_MODULE(charset_CP437, modules/CP437.o, "bin/CP437.$SHLIBEXT", CHARSET)
+SMB_MODULE(charset_macosxfs, modules/charset_macosxfs.o,"bin/macosxfs.$SHLIBEXT", CHARSET)
SMB_SUBSYSTEM(CHARSET,lib/iconv.o)
SMB_MODULE(auth_rhosts, \$(AUTH_RHOSTS_OBJ), "bin/rhosts.$SHLIBEXT", AUTH)
diff --git a/source/groupdb/mapping.c b/source/groupdb/mapping.c
index 7a07b5c3448..b1c260581ee 100644
--- a/source/groupdb/mapping.c
+++ b/source/groupdb/mapping.c
@@ -547,27 +547,28 @@ BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map)
{
- struct group *grp;
-
if(!init_group_mapping()) {
DEBUG(0,("failed to initialize group mapping"));
return(False);
}
/* The group is in the mapping table */
- if(pdb_getgrsid(map, sid)) {
- if (map->sid_name_use!=SID_NAME_ALIAS) {
- return False;
- }
+
+ if( !pdb_getgrsid(map, sid) )
+ return False;
- if (map->gid==-1) {
- return False;
- }
-
- if ( (grp=getgrgid(map->gid)) == NULL) {
- return False;
- }
- } else {
+ if ( (map->sid_name_use != SID_NAME_ALIAS)
+ || (map->gid == -1)
+ || (getgrgid(map->gid) == NULL) )
+ {
+ return False;
+ }
+
+#if 0 /* JERRY */
+ /* local groups only exist in the group mapping DB so this
+ is not necessary */
+
+ else {
/* the group isn't in the mapping table.
* make one based on the unix information */
uint32 alias_rid;
@@ -588,6 +589,7 @@ BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map)
sid_copy(&map->sid, &sid);
}
+#endif
return True;
}
@@ -629,6 +631,7 @@ Returns a GROUP_MAP struct based on the gid.
BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map)
{
struct group *grp;
+ BOOL ret;
if(!init_group_mapping()) {
DEBUG(0,("failed to initialize group mapping"));
@@ -641,7 +644,12 @@ BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map)
/*
* make a group map from scratch if doesn't exist.
*/
- if (!pdb_getgrgid(map, gid)) {
+
+ become_root();
+ ret = pdb_getgrgid(map, gid);
+ unbecome_root();
+
+ if ( !ret ) {
map->gid=gid;
map->sid_name_use=SID_NAME_ALIAS;
diff --git a/source/include/auth.h b/source/include/auth.h
index 6b42418be8d..ecf4d539d8c 100644
--- a/source/include/auth.h
+++ b/source/include/auth.h
@@ -87,10 +87,9 @@ typedef struct auth_serversupplied_info
NT_USER_TOKEN *ptok;
- uint8 session_key[16];
+ DATA_BLOB nt_session_key;
+ DATA_BLOB lm_session_key;
- uint8 first_8_lm_hash[8];
-
uint32 sam_fill_level; /* How far is this structure filled? */
SAM_ACCOUNT *sam_account;
@@ -107,6 +106,8 @@ struct auth_context {
/* Who set this up in the first place? */
const char *challenge_set_by;
+ BOOL challenge_may_be_modified;
+
struct auth_methods *challenge_set_method;
/* What order are the various methods in? Try to stop it changing under us */
struct auth_methods *auth_method_list;
diff --git a/source/include/client.h b/source/include/client.h
index 598e6c0bda5..968b73f0b41 100644
--- a/source/include/client.h
+++ b/source/include/client.h
@@ -113,7 +113,7 @@ struct cli_state {
/* the session key for this CLI, outside
any per-pipe authenticaion */
- unsigned char user_session_key[16];
+ DATA_BLOB user_session_key;
/*
* Only used in NT domain calls.
@@ -133,7 +133,7 @@ struct cli_state {
schannel. */
struct netsec_auth_struct auth_info;
- NTLMSSP_CLIENT_STATE *ntlmssp_pipe_state;
+ NTLMSSP_STATE *ntlmssp_pipe_state;
unsigned char sess_key[16]; /* Current session key. */
DOM_CRED clnt_cred; /* Client credential. */
diff --git a/source/include/includes.h b/source/include/includes.h
index ebb09b6c6ce..638648dc44d 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -1298,7 +1298,7 @@ krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt);
krb5_error_code krb5_locate_kdc(krb5_context ctx, const krb5_data *realm, struct sockaddr **addr_pp, int *naddrs, int get_masters);
krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes);
void free_kerberos_etypes(krb5_context context, krb5_enctype *enctypes);
-BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16], BOOL remote);
+BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, DATA_BLOB *session_key, BOOL remote);
#endif /* HAVE_KRB5 */
/* TRUE and FALSE are part of the C99 standard and gcc, but
diff --git a/source/include/ntdomain.h b/source/include/ntdomain.h
index 3fe8f41d8d4..b1a4107980d 100644
--- a/source/include/ntdomain.h
+++ b/source/include/ntdomain.h
@@ -229,7 +229,7 @@ typedef struct pipes_struct
fstring pipe_user_name;
struct current_user pipe_user;
- uint8 session_key[16];
+ DATA_BLOB session_key;
/*
* Set to true when an RPC bind has been done on this pipe.
diff --git a/source/include/ntlmssp.h b/source/include/ntlmssp.h
index f1b1bc25e43..681d4071dbb 100644
--- a/source/include/ntlmssp.h
+++ b/source/include/ntlmssp.h
@@ -30,6 +30,7 @@ enum NTLMSSP_ROLE
/* NTLMSSP message types */
enum NTLM_MESSAGE_TYPE
{
+ NTLMSSP_INITIAL = 0 /* samba internal state */,
NTLMSSP_NEGOTIATE = 1,
NTLMSSP_CHALLENGE = 2,
NTLMSSP_AUTH = 3,
@@ -70,29 +71,10 @@ enum NTLM_MESSAGE_TYPE
typedef struct ntlmssp_state
{
TALLOC_CTX *mem_ctx;
+ unsigned int ref_count;
enum NTLMSSP_ROLE role;
- BOOL unicode;
- char *user;
- char *domain;
- char *workstation;
- DATA_BLOB lm_resp;
- DATA_BLOB nt_resp;
- DATA_BLOB chal;
- void *auth_context;
- const uint8 *(*get_challenge)(struct ntlmssp_state *ntlmssp_state);
- NTSTATUS (*check_password)(struct ntlmssp_state *ntlmssp_state);
-
- const char *(*get_global_myname)(void);
- const char *(*get_domain)(void);
-
- int server_role;
+ enum server_types server_role;
uint32 expected_state;
-} NTLMSSP_STATE;
-
-typedef struct ntlmssp_client_state
-{
- TALLOC_CTX *mem_ctx;
- unsigned int ref_count;
BOOL unicode;
BOOL use_ntlmv2;
@@ -102,30 +84,78 @@ typedef struct ntlmssp_client_state
char *password;
char *server_domain;
- const char *(*get_global_myname)(void);
- const char *(*get_domain)(void);
+ DATA_BLOB internal_chal; /* Random challenge as supplied to the client for NTLM authentication */
- DATA_BLOB chal;
+ DATA_BLOB chal; /* Random challenge as input into the actual NTLM (or NTLM2) authentication */
DATA_BLOB lm_resp;
DATA_BLOB nt_resp;
DATA_BLOB session_key;
- uint32 neg_flags;
+ uint32 neg_flags; /* the current state of negotiation with the NTLMSSP partner */
+ void *auth_context;
+
+ /**
+ * Callback to get the 'challenge' used for NTLM authentication.
+ *
+ * @param ntlmssp_state This structure
+ * @return 8 bytes of challnege data, determined by the server to be the challenge for NTLM authentication
+ *
+ */
+ const uint8 *(*get_challenge)(const struct ntlmssp_state *ntlmssp_state);
+
+ /**
+ * Callback to find if the challenge used by NTLM authentication may be modified
+ *
+ * The NTLM2 authentication scheme modifies the effective challenge, but this is not compatiable with the
+ * current 'security=server' implementation..
+ *
+ * @param ntlmssp_state This structure
+ * @return Can the challenge be set to arbitary values?
+ *
+ */
+ BOOL (*may_set_challenge)(const struct ntlmssp_state *ntlmssp_state);
+
+ /**
+ * Callback to set the 'challenge' used for NTLM authentication.
+ *
+ * The callback may use the void *auth_context to store state information, but the same value is always available
+ * from the DATA_BLOB chal on this structure.
+ *
+ * @param ntlmssp_state This structure
+ * @param challange 8 bytes of data, agreed by the client and server to be the effective challenge for NTLM2 authentication
+ *
+ */
+ NTSTATUS (*set_challenge)(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge);
+
+ /**
+ * Callback to check the user's password.
+ *
+ * The callback must reads the feilds of this structure for the information it needs on the user
+ * @param ntlmssp_state This structure
+ * @param nt_session_key If an NT session key is returned by the authentication process, return it here
+ * @param lm_session_key If an LM session key is returned by the authentication process, return it here
+ *
+ */
+ NTSTATUS (*check_password)(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *nt_session_key, DATA_BLOB *lm_session_key);
+
+ const char *(*get_global_myname)(void);
+ const char *(*get_domain)(void);
+
/* SMB Signing */
uint32 ntlmssp_seq_num;
/* ntlmv2 */
- char cli_sign_const[16];
- char cli_seal_const[16];
- char srv_sign_const[16];
- char srv_seal_const[16];
+ char send_sign_const[16];
+ char send_seal_const[16];
+ char recv_sign_const[16];
+ char recv_seal_const[16];
- unsigned char cli_sign_hash[258];
- unsigned char cli_seal_hash[258];
- unsigned char srv_sign_hash[258];
- unsigned char srv_seal_hash[258];
+ unsigned char send_sign_hash[258];
+ unsigned char send_seal_hash[258];
+ unsigned char recv_sign_hash[258];
+ unsigned char recv_seal_hash[258];
/* ntlmv1 */
unsigned char ntlmssp_hash[258];
@@ -135,5 +165,5 @@ typedef struct ntlmssp_client_state
Store it here, until we need it */
DATA_BLOB stored_response;
-} NTLMSSP_CLIENT_STATE;
+} NTLMSSP_STATE;
diff --git a/source/include/passdb.h b/source/include/passdb.h
index a4b2bcff3fd..3e9036aef77 100644
--- a/source/include/passdb.h
+++ b/source/include/passdb.h
@@ -98,7 +98,7 @@ typedef struct sam_passwd
struct pdb_methods *methods;
struct user_data {
- /* initiailization flags */
+ /* initialization flags */
struct bitmap *change_flags;
struct bitmap *set_flags;
@@ -161,7 +161,7 @@ typedef struct sam_group {
struct pdb_methods *methods;
struct group_data {
- /* initiailization flags */
+ /* initialization flags */
struct bitmap *change_flags;
struct bitmap *set_flags;
diff --git a/source/include/rpc_samr.h b/source/include/rpc_samr.h
index 3b81042df37..787535d0e90 100644
--- a/source/include/rpc_samr.h
+++ b/source/include/rpc_samr.h
@@ -127,7 +127,7 @@ SamrTestPrivateFunctionsUser
#define SAMR_UNKNOWN_2a 0x2a
#define SAMR_UNKNOWN_2b 0x2b
#define SAMR_GET_USRDOM_PWINFO 0x2c
-#define SAMR_REMOVE_USER_FOREIGN_DOMAIN 0x2d
+#define SAMR_REMOVE_SID_FOREIGN_DOMAIN 0x2d
#define SAMR_UNKNOWN_2E 0x2e /* looks like an alias for SAMR_QUERY_DOMAIN_INFO */
#define SAMR_UNKNOWN_2f 0x2f
#define SAMR_QUERY_DISPINFO3 0x30 /* Alias for SAMR_QUERY_DISPINFO
@@ -1790,21 +1790,21 @@ typedef struct r_samr_chgpasswd_user_info
} SAMR_R_CHGPASSWD_USER;
-/* SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN */
-typedef struct q_samr_remove_user_foreign_domain_info
+/* SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN */
+typedef struct q_samr_remove_sid_foreign_domain_info
{
POLICY_HND dom_pol; /* policy handle */
DOM_SID2 sid; /* SID */
-} SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN;
+} SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN;
-/* SAMR_R_REMOVE_USER_FOREIGN_DOMAIN */
-typedef struct r_samr_remove_user_foreign_domain_info
+/* SAMR_R_REMOVE_SID_FOREIGN_DOMAIN */
+typedef struct r_samr_remove_sid_foreign_domain_info
{
NTSTATUS status; /* return status */
-} SAMR_R_REMOVE_USER_FOREIGN_DOMAIN;
+} SAMR_R_REMOVE_SID_FOREIGN_DOMAIN;
diff --git a/source/include/smb.h b/source/include/smb.h
index e41b5834f70..4bd40216d7b 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -1546,7 +1546,7 @@ typedef struct user_struct
NT_USER_TOKEN *nt_user_token;
- uint8 session_key[16];
+ DATA_BLOB session_key;
char *session_keystr; /* used by utmp and pam session code.
TDB key string */
diff --git a/source/include/smbldap.h b/source/include/smbldap.h
index 9765b9fbd60..17584c4fe4c 100644
--- a/source/include/smbldap.h
+++ b/source/include/smbldap.h
@@ -90,6 +90,7 @@
#define LDAP_ATTR_NEXT_RID 34
#define LDAP_ATTR_BAD_PASSWORD_COUNT 35
#define LDAP_ATTR_LOGON_COUNT 36
+#define LDAP_ATTR_MUNGED_DIAL 37
typedef struct _attrib_map_entry {
int attrib;
diff --git a/source/lib/access.c b/source/lib/access.c
index a642a92d716..81eab7c738e 100644
--- a/source/lib/access.c
+++ b/source/lib/access.c
@@ -114,7 +114,7 @@ static BOOL string_match(const char *tok,const char *s, char *invalid_char)
} else if (strequal(tok, "LOCAL")) { /* local: no dots */
if (strchr_m(s, '.') == 0 && !strequal(s, "unknown"))
return (True);
- } else if (!strequal(tok, s)) { /* match host name or address */
+ } else if (strequal(tok, s)) { /* match host name or address */
return (True);
} else if (tok[(tok_len = strlen(tok)) - 1] == '.') { /* network */
if (strncmp(tok, s, tok_len) == 0)
diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c
index 0a6a1fc75d6..6a004021939 100644
--- a/source/lib/charcnv.c
+++ b/source/lib/charcnv.c
@@ -488,7 +488,6 @@ convert:
}
}
-
/**
* Convert between character sets, allocating a new buffer using talloc for the result.
*
@@ -581,19 +580,19 @@ char *strdup_upper(const char *s)
size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
{
size_t size;
- smb_ucs2_t *buffer;
+ smb_ucs2_t *buffer = NULL;
size = convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, srclen,
(void **) &buffer);
- if (size == -1) {
+ if (size == -1 || !buffer) {
smb_panic("failed to create UCS2 buffer");
}
if (!strlower_w(buffer) && (dest == src)) {
- free(buffer);
+ SAFE_FREE(buffer);
return srclen;
}
size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
- free(buffer);
+ SAFE_FREE(buffer);
return size;
}
@@ -604,11 +603,11 @@ size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
char *strdup_lower(const char *s)
{
size_t size;
- smb_ucs2_t *buffer;
+ smb_ucs2_t *buffer = NULL;
char *out_buffer;
size = push_ucs2_allocate(&buffer, s);
- if (size == -1) {
+ if (size == -1 || !buffer) {
return NULL;
}
diff --git a/source/lib/data_blob.c b/source/lib/data_blob.c
index 4056212fc56..83afc591a15 100644
--- a/source/lib/data_blob.c
+++ b/source/lib/data_blob.c
@@ -61,14 +61,20 @@ DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length)
{
DATA_BLOB ret;
- if (!p || !length) {
+ if (!length) {
ZERO_STRUCT(ret);
return ret;
}
- ret.data = talloc_memdup(mem_ctx, p, length);
- if (ret.data == NULL)
- smb_panic("data_blob_talloc: talloc_memdup failed.\n");
+ if (p) {
+ ret.data = talloc_memdup(mem_ctx, p, length);
+ if (ret.data == NULL)
+ smb_panic("data_blob_talloc: talloc_memdup failed.\n");
+ } else {
+ ret.data = talloc(mem_ctx, length);
+ if (ret.data == NULL)
+ smb_panic("data_blob_talloc: talloc failed.\n");
+ }
ret.length = length;
ret.free = NULL;
diff --git a/source/lib/module.c b/source/lib/module.c
index 38fcf0f3297..2abe918ef44 100644
--- a/source/lib/module.c
+++ b/source/lib/module.c
@@ -42,9 +42,8 @@ static NTSTATUS do_smb_load_module(const char *module_name, BOOL is_probe)
if(!handle) {
int level = is_probe ? 3 : 0;
- DEBUG(level, ("Error loading module '%s': %s\n", module_name,
- sys_dlerror()));
-
+ error = sys_dlerror();
+ DEBUG(level, ("Error loading module '%s': %s\n", module_name, error ? error : ""));
return NT_STATUS_UNSUCCESSFUL;
}
diff --git a/source/lib/privileges.c b/source/lib/privileges.c
index 1ed583382de..b9d4df301d9 100644
--- a/source/lib/privileges.c
+++ b/source/lib/privileges.c
@@ -69,6 +69,12 @@ NTSTATUS dupalloc_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *
{
NTSTATUS ret;
+ /* don't crash if the source pointer is NULL (since we don't
+ do priviledges now anyways) */
+
+ if ( !old_la )
+ return NT_STATUS_OK;
+
*new_la = (LUID_ATTR *)talloc(mem_ctx, sizeof(LUID_ATTR));
ALLOC_CHECK(new_la, ret, done, "dupalloc_luid_attr");
diff --git a/source/lib/smbldap.c b/source/lib/smbldap.c
index fe34cfb852e..8f6394ea928 100644
--- a/source/lib/smbldap.c
+++ b/source/lib/smbldap.c
@@ -97,6 +97,7 @@ ATTRIB_MAP_ENTRY attrib_map_v30[] = {
{ LDAP_ATTR_DOMAIN, "sambaDomainName" },
{ LDAP_ATTR_OBJCLASS, "objectClass" },
{ LDAP_ATTR_ACB_INFO, "sambaAcctFlags" },
+ { LDAP_ATTR_MUNGED_DIAL, "sambaMungedDial" },
{ LDAP_ATTR_LIST_END, NULL }
};
diff --git a/source/lib/time.c b/source/lib/time.c
index 635ede9be22..faca2cba879 100644
--- a/source/lib/time.c
+++ b/source/lib/time.c
@@ -465,10 +465,9 @@ void unix_to_nt_time_abs(NTTIME *nt, time_t t)
nt->low=~nt->low;
}
-
/****************************************************************************
-take an NTTIME structure, containing high / low time. convert to unix time.
-lkclXXXX this may need 2 SIVALs not a memcpy. we'll see...
+take a Unix time and convert to an NTTIME structure and place in buffer
+pointed to by p.
****************************************************************************/
void put_long_date(char *p,time_t t)
{
diff --git a/source/lib/util.c b/source/lib/util.c
index ce1389c8e9c..39515c65991 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -2234,7 +2234,7 @@ char *parent_dirname(const char *path)
Determine if a pattern contains any Microsoft wildcard characters.
*******************************************************************/
-BOOL ms_has_wild(char *s)
+BOOL ms_has_wild(const char *s)
{
char c;
while ((c = *s++)) {
diff --git a/source/lib/util_str.c b/source/lib/util_str.c
index c244a6b34bf..2928584b8af 100644
--- a/source/lib/util_str.c
+++ b/source/lib/util_str.c
@@ -62,7 +62,7 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
/* copy over the token */
pbuf = buff;
for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
- if (*s == '\"') {
+ if (*s == '\"' || *s == '\'') {
quoted = !quoted;
} else {
len++;
@@ -574,7 +574,7 @@ char *safe_strcpy_fn(const char *fn, int line, char *dest,const char *src, size_
size_t len;
if (!dest) {
- DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
+ DEBUG(0,("ERROR: NULL dest in safe_strcpy, called from [%s][%d]\n", fn, line));
return NULL;
}
@@ -610,7 +610,7 @@ char *safe_strcat_fn(const char *fn, int line, char *dest, const char *src, size
size_t src_len, dest_len;
if (!dest) {
- DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
+ DEBUG(0,("ERROR: NULL dest in safe_strcat, called from [%s][%d]\n", fn, line));
return NULL;
}
@@ -654,7 +654,7 @@ char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, con
#endif
if (!dest) {
- DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
+ DEBUG(0,("ERROR: NULL dest in alpha_strcpy, called from [%s][%d]\n", fn, line));
return NULL;
}
@@ -695,9 +695,11 @@ char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
clobber_region(fn, line, dest, n+1);
#endif
- if (!dest)
+ if (!dest) {
+ DEBUG(0,("ERROR: NULL dest in StrnCpy, called from [%s][%d]\n", fn, line));
return(NULL);
-
+ }
+
if (!src) {
*dest = 0;
return(dest);
diff --git a/source/libads/kerberos_verify.c b/source/libads/kerberos_verify.c
index cdea5a2fe42..b0efb8f598f 100644
--- a/source/libads/kerberos_verify.c
+++ b/source/libads/kerberos_verify.c
@@ -162,7 +162,7 @@ static BOOL setup_keytab(krb5_context context,
NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
char **principal, DATA_BLOB *auth_data,
DATA_BLOB *ap_rep,
- uint8 session_key[16])
+ DATA_BLOB *session_key)
{
NTSTATUS sret = NT_STATUS_LOGON_FAILURE;
krb5_context context = NULL;
diff --git a/source/libads/ldap.c b/source/libads/ldap.c
index b3706cb2403..072f42513cb 100644
--- a/source/libads/ldap.c
+++ b/source/libads/ldap.c
@@ -1933,7 +1933,7 @@ bin/net -Uadministrator%XXXXX ads search '(&(objectclass=crossref)(dnsroot=VNET3
but you need to force the bind path to match the configurationNamingContext from the rootDSE
*/
-ADS_STATUS ads_workgroup_name(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **workgroup)
+ADS_STATUS ads_workgroup_name(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **workgroup)
{
char *expr;
ADS_STATUS rc;
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c
index b5f7b97ae83..f6dfd400068 100644
--- a/source/libsmb/cliconnect.c
+++ b/source/libsmb/cliconnect.c
@@ -241,9 +241,16 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user,
return True;
}
-static void set_cli_session_key (struct cli_state *cli, DATA_BLOB session_key)
+/**
+ * Set the user session key for a connection
+ * @param cli The cli structure to add it too
+ * @param session_key The session key used. (A copy of this is taken for the cli struct)
+ *
+ */
+
+static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
{
- memcpy(cli->user_session_key, session_key.data, MIN(session_key.length, sizeof(cli->user_session_key)));
+ cli->user_session_key = data_blob(session_key.data, session_key.length);
}
/****************************************************************************
@@ -311,7 +318,7 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
session_key = data_blob(NULL, 16);
SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
}
- cli_simple_set_signing(cli, session_key.data, nt_response);
+ cli_simple_set_signing(cli, session_key, nt_response);
} else {
/* pre-encrypted password supplied. Only used for
security=server, can't do
@@ -373,14 +380,16 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
if (session_key.data) {
/* Have plaintext orginal */
- set_cli_session_key(cli, session_key);
+ cli_set_session_key(cli, session_key);
}
ret = True;
end:
data_blob_free(&lm_response);
data_blob_free(&nt_response);
- data_blob_free(&session_key);
+
+ if (!ret)
+ data_blob_free(&session_key);
return ret;
}
@@ -484,19 +493,19 @@ static void use_in_memory_ccache(void) {
Do a spnego/kerberos encrypted session setup.
****************************************************************************/
-static BOOL cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
+static NTSTATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
{
DATA_BLOB blob2, negTokenTarg;
- unsigned char session_key_krb5[16];
+ DATA_BLOB session_key_krb5;
DATA_BLOB null_blob = data_blob(NULL, 0);
DEBUG(2,("Doing kerberos session setup\n"));
/* generate the encapsulated kerberos5 ticket */
- negTokenTarg = spnego_gen_negTokenTarg(principal, 0, session_key_krb5);
+ negTokenTarg = spnego_gen_negTokenTarg(principal, 0, &session_key_krb5);
if (!negTokenTarg.data)
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
#if 0
file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
@@ -509,9 +518,16 @@ static BOOL cli_session_setup_kerberos(struct cli_state *cli, const char *princi
/* we don't need this blob for kerberos */
data_blob_free(&blob2);
+ cli_set_session_key(cli, session_key_krb5);
+
data_blob_free(&negTokenTarg);
- return !cli_is_error(cli);
+ if (cli_is_error(cli)) {
+ if (NT_STATUS_IS_OK(cli_nt_error(cli))) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ return NT_STATUS_OK;
}
#endif /* HAVE_KRB5 */
@@ -520,10 +536,10 @@ static BOOL cli_session_setup_kerberos(struct cli_state *cli, const char *princi
Do a spnego/NTLMSSP encrypted session setup.
****************************************************************************/
-static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
+static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
const char *pass, const char *workgroup)
{
- struct ntlmssp_client_state *ntlmssp_state;
+ struct ntlmssp_state *ntlmssp_state;
NTSTATUS nt_status;
int turn = 1;
DATA_BLOB msg1;
@@ -534,21 +550,21 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
cli_temp_set_signing(cli);
if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
- return False;
+ return nt_status;
}
if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
- return False;
+ return nt_status;
}
if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, workgroup))) {
- return False;
+ return nt_status;
}
if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
- return False;
+ return nt_status;
}
do {
- nt_status = ntlmssp_client_update(ntlmssp_state,
+ nt_status = ntlmssp_update(ntlmssp_state,
blob_in, &blob_out);
data_blob_free(&blob_in);
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
@@ -562,18 +578,27 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
}
cli_simple_set_signing(cli,
- ntlmssp_state->session_key.data,
+ data_blob(ntlmssp_state->session_key.data, ntlmssp_state->session_key.length),
null_blob);
/* now send that blob on its way */
if (!cli_session_setup_blob_send(cli, msg1)) {
- return False;
+ DEBUG(3, ("Failed to send NTLMSSP/SPENGO blob to server!\n"));
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ } else {
+ data_blob_free(&msg1);
+
+ blob = cli_session_setup_blob_receive(cli);
+
+ nt_status = cli_nt_error(cli);
+ if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
+ if (cli->smb_rw_error == READ_BAD_SIG) {
+ nt_status = NT_STATUS_ACCESS_DENIED;
+ } else {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ }
+ }
}
- data_blob_free(&msg1);
-
- blob = cli_session_setup_blob_receive(cli);
-
- nt_status = cli_nt_error(cli);
}
if (!blob.length) {
@@ -606,24 +631,22 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
if (NT_STATUS_IS_OK(nt_status)) {
fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
- set_cli_session_key(cli, ntlmssp_state->session_key);
+ cli_set_session_key(cli, ntlmssp_state->session_key);
}
/* we have a reference conter on ntlmssp_state, if we are signing
then the state will be kept by the signing engine */
- if (!NT_STATUS_IS_OK(ntlmssp_client_end(&ntlmssp_state))) {
- return False;
- }
-
- return (NT_STATUS_IS_OK(nt_status));
+ ntlmssp_end(&ntlmssp_state);
+
+ return nt_status;
}
/****************************************************************************
Do a spnego encrypted session setup.
****************************************************************************/
-BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user,
+NTSTATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
const char *pass, const char *workgroup)
{
char *principal;
@@ -651,7 +674,7 @@ BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user,
reply */
if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
data_blob_free(&blob);
- return False;
+ return NT_STATUS_INVALID_PARAMETER;
}
data_blob_free(&blob);
@@ -681,7 +704,7 @@ BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user,
if (ret){
DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
- return False;
+ return NT_STATUS_LOGON_FAILURE;
}
}
@@ -773,8 +796,14 @@ BOOL cli_session_setup(struct cli_state *cli,
/* if the server supports extended security then use SPNEGO */
- if (cli->capabilities & CAP_EXTENDED_SECURITY)
- return cli_session_setup_spnego(cli, user, pass, workgroup);
+ if (cli->capabilities & CAP_EXTENDED_SECURITY) {
+ NTSTATUS nt_status;
+ if (!NT_STATUS_IS_OK(nt_status = cli_session_setup_spnego(cli, user, pass, workgroup))) {
+ DEBUG(3, ("SPENGO login failed: %s\n", get_friendly_nt_error_msg(nt_status)));
+ return False;
+ }
+ return True;
+ }
/* otherwise do a NT1 style session setup */
@@ -992,7 +1021,7 @@ BOOL cli_negprot(struct cli_state *cli)
cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
- DEBUG(1,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
+ DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
return False;
}
@@ -1028,7 +1057,7 @@ BOOL cli_negprot(struct cli_state *cli)
if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
/* Fail if server says signing is mandatory and we don't want to support it. */
if (!cli->sign_info.allow_smb_signing) {
- DEBUG(1,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
+ DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
return False;
}
cli->sign_info.negotiated_smb_signing = True;
diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c
index 9b54acf7756..0873700fc0a 100644
--- a/source/libsmb/clientgen.c
+++ b/source/libsmb/clientgen.c
@@ -339,7 +339,7 @@ close the session
void cli_nt_session_close(struct cli_state *cli)
{
if (cli->ntlmssp_pipe_state) {
- ntlmssp_client_end(&cli->ntlmssp_pipe_state);
+ ntlmssp_end(&cli->ntlmssp_pipe_state);
}
if (cli->nt_pipe_fnum != 0)
@@ -375,9 +375,10 @@ void cli_close_connection(struct cli_state *cli)
cli_free_signing_context(cli);
data_blob_free(&cli->secblob);
+ data_blob_free(&cli->user_session_key);
if (cli->ntlmssp_pipe_state)
- ntlmssp_client_end(&cli->ntlmssp_pipe_state);
+ ntlmssp_end(&cli->ntlmssp_pipe_state);
if (cli->mem_ctx) {
talloc_destroy(cli->mem_ctx);
diff --git a/source/libsmb/clikrb5.c b/source/libsmb/clikrb5.c
index 1fccc04a013..5568b5e0332 100644
--- a/source/libsmb/clikrb5.c
+++ b/source/libsmb/clikrb5.c
@@ -307,7 +307,7 @@ cleanup_princ:
/*
get a kerberos5 ticket for the given service
*/
-DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, unsigned char session_key_krb5[16])
+DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, DATA_BLOB *session_key_krb5)
{
krb5_error_code retval;
krb5_data packet;
@@ -369,7 +369,7 @@ failed:
return data_blob(NULL, 0);
}
- BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16], BOOL remote)
+ BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, DATA_BLOB *session_key, BOOL remote)
{
krb5_keyblock *skey;
krb5_error_code err;
@@ -383,11 +383,11 @@ failed:
err = krb5_auth_con_getlocalsubkey(context, auth_context, &skey);
if (err == 0 && skey != NULL) {
DEBUG(10, ("Got KRB5 session key of length %d\n", KRB5_KEY_LENGTH(skey)));
- if (KRB5_KEY_LENGTH(skey) == 16) {
- memcpy(session_key, KRB5_KEY_DATA(skey), KRB5_KEY_LENGTH(skey));
- dump_data_pw("KRB5 Session Key:\n", session_key, 16);
- ret = True;
- }
+ *session_key = data_blob(KRB5_KEY_DATA(skey), KRB5_KEY_LENGTH(skey));
+ dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length);
+
+ ret = True;
+
krb5_free_keyblock(context, skey);
} else {
DEBUG(10, ("KRB5 error getting session key %d\n", err));
@@ -410,7 +410,7 @@ failed:
#else /* HAVE_KRB5 */
/* this saves a few linking headaches */
-DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, unsigned char session_key_krb5[16])
+DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, DATA_BLOB *session_key_krb5)
{
DEBUG(0,("NO KERBEROS SUPPORT\n"));
return data_blob(NULL, 0);
diff --git a/source/libsmb/clispnego.c b/source/libsmb/clispnego.c
index 63076a1a1ce..92543736ff2 100644
--- a/source/libsmb/clispnego.c
+++ b/source/libsmb/clispnego.c
@@ -323,7 +323,7 @@ BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2])
generate a SPNEGO negTokenTarg packet, ready for a EXTENDED_SECURITY
kerberos session setup
*/
-DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset, unsigned char session_key_krb5[16])
+DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset, DATA_BLOB *session_key_krb5)
{
DATA_BLOB tkt, tkt_wrapped, targ;
const char *krb_mechs[] = {OID_KERBEROS5_OLD, OID_NTLMSSP, NULL};
diff --git a/source/libsmb/clitrans.c b/source/libsmb/clitrans.c
index 92c1cc99eeb..ae44ca1a779 100644
--- a/source/libsmb/clitrans.c
+++ b/source/libsmb/clitrans.c
@@ -50,6 +50,12 @@ BOOL cli_send_trans(struct cli_state *cli, int trans,
SCVAL(cli->outbuf,smb_com,trans);
SSVAL(cli->outbuf,smb_tid, cli->cnum);
cli_setup_packet(cli);
+
+ /*
+ * Save the mid we're using. We need this for finding
+ * signing replies.
+ */
+
mid = cli->mid;
if (pipe_name) {
@@ -87,16 +93,13 @@ BOOL cli_send_trans(struct cli_state *cli, int trans,
show_msg(cli->outbuf);
- cli_signing_trans_start(cli);
if (!cli_send_smb(cli)) {
- cli_signing_trans_stop(cli);
return False;
}
if (this_ldata < ldata || this_lparam < lparam) {
/* receive interim response */
if (!cli_receive_smb(cli) || cli_is_error(cli)) {
- cli_signing_trans_stop(cli);
return(False);
}
@@ -130,21 +133,29 @@ BOOL cli_send_trans(struct cli_state *cli, int trans,
memcpy(outdata,data+tot_data,this_ldata);
cli_setup_bcc(cli, outdata+this_ldata);
- /* Ensure this packet has the same MID as
- * the primary. Important in signing. JRA. */
- cli->mid = mid;
+ /*
+ * Save the mid we're using. We need this for finding
+ * signing replies.
+ */
+ mid = cli->mid;
show_msg(cli->outbuf);
if (!cli_send_smb(cli)) {
- cli_signing_trans_stop(cli);
return False;
}
+
+ /* Ensure we use the same mid for the secondaries. */
+ cli->mid = mid;
tot_data += this_ldata;
tot_param += this_lparam;
}
}
+ /* Note we're in a trans state. Save the sequence
+ * numbers for replies. */
+
+ cli_signing_trans_start(cli, mid);
return(True);
}
@@ -352,6 +363,12 @@ BOOL cli_send_nt_trans(struct cli_state *cli,
SCVAL(cli->outbuf,smb_com,SMBnttrans);
SSVAL(cli->outbuf,smb_tid, cli->cnum);
cli_setup_packet(cli);
+
+ /*
+ * Save the mid we're using. We need this for finding
+ * signing replies.
+ */
+
mid = cli->mid;
outparam = smb_buf(cli->outbuf)+3;
@@ -381,16 +398,13 @@ BOOL cli_send_nt_trans(struct cli_state *cli,
cli_setup_bcc(cli, outdata+this_ldata);
show_msg(cli->outbuf);
- cli_signing_trans_start(cli);
if (!cli_send_smb(cli)) {
- cli_signing_trans_stop(cli);
return False;
}
if (this_ldata < ldata || this_lparam < lparam) {
/* receive interim response */
if (!cli_receive_smb(cli) || cli_is_error(cli)) {
- cli_signing_trans_stop(cli);
return(False);
}
@@ -423,22 +437,30 @@ BOOL cli_send_nt_trans(struct cli_state *cli,
memcpy(outdata,data+tot_data,this_ldata);
cli_setup_bcc(cli, outdata+this_ldata);
- /* Ensure this packet has the same MID as
- * the primary. Important in signing. JRA. */
- cli->mid = mid;
+ /*
+ * Save the mid we're using. We need this for finding
+ * signing replies.
+ */
+ mid = cli->mid;
show_msg(cli->outbuf);
if (!cli_send_smb(cli)) {
- cli_signing_trans_stop(cli);
return False;
}
+ /* Ensure we use the same mid for the secondaries. */
+ cli->mid = mid;
+
tot_data += this_ldata;
tot_param += this_lparam;
}
}
+ /* Note we're in a trans state. Save the sequence
+ * numbers for replies. */
+
+ cli_signing_trans_start(cli, mid);
return(True);
}
diff --git a/source/libsmb/ntlmssp.c b/source/libsmb/ntlmssp.c
index c51b599b041..ca1aa674031 100644
--- a/source/libsmb/ntlmssp.c
+++ b/source/libsmb/ntlmssp.c
@@ -23,6 +23,35 @@
#include "includes.h"
+static NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state,
+ DATA_BLOB reply, DATA_BLOB *next_request);
+static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
+ const DATA_BLOB in, DATA_BLOB *out);
+static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
+ const DATA_BLOB reply, DATA_BLOB *next_request);
+static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
+ const DATA_BLOB request, DATA_BLOB *reply);
+
+/**
+ * Callbacks for NTLMSSP - for both client and server operating modes
+ *
+ */
+
+static const struct ntlmssp_callbacks {
+ enum NTLMSSP_ROLE role;
+ enum NTLM_MESSAGE_TYPE ntlmssp_command;
+ NTSTATUS (*fn)(struct ntlmssp_state *ntlmssp_state,
+ DATA_BLOB in, DATA_BLOB *out);
+} ntlmssp_callbacks[] = {
+ {NTLMSSP_CLIENT, NTLMSSP_INITIAL, ntlmssp_client_initial},
+ {NTLMSSP_SERVER, NTLMSSP_NEGOTIATE, ntlmssp_server_negotiate},
+ {NTLMSSP_CLIENT, NTLMSSP_CHALLENGE, ntlmssp_client_challenge},
+ {NTLMSSP_SERVER, NTLMSSP_AUTH, ntlmssp_server_auth},
+ {NTLMSSP_CLIENT, NTLMSSP_UNKNOWN, NULL},
+ {NTLMSSP_SERVER, NTLMSSP_UNKNOWN, NULL}
+};
+
+
/**
* Print out the NTLMSSP flags for debugging
* @param neg_flags The flags from the packet
@@ -71,7 +100,7 @@ void debug_ntlmssp_flags(uint32 neg_flags)
*
*/
-static const uint8 *get_challenge(struct ntlmssp_state *ntlmssp_state)
+static const uint8 *get_challenge(const struct ntlmssp_state *ntlmssp_state)
{
static uchar chal[8];
generate_random_buffer(chal, sizeof(chal), False);
@@ -80,6 +109,188 @@ static const uint8 *get_challenge(struct ntlmssp_state *ntlmssp_state)
}
/**
+ * Default 'we can set the challenge to anything we like' implementation
+ *
+ */
+
+static BOOL may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
+{
+ return True;
+}
+
+/**
+ * Default 'we can set the challenge to anything we like' implementation
+ *
+ * Does not actually do anything, as the value is always in the structure anyway.
+ *
+ */
+
+static NTSTATUS set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
+{
+ SMB_ASSERT(challenge->length == 8);
+ return NT_STATUS_OK;
+}
+
+/**
+ * Set a username on an NTLMSSP context - ensures it is talloc()ed
+ *
+ */
+
+NTSTATUS ntlmssp_set_username(NTLMSSP_STATE *ntlmssp_state, const char *user)
+{
+ ntlmssp_state->user = talloc_strdup(ntlmssp_state->mem_ctx, user);
+ if (!ntlmssp_state->user) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ return NT_STATUS_OK;
+}
+
+/**
+ * Set a password on an NTLMSSP context - ensures it is talloc()ed
+ *
+ */
+NTSTATUS ntlmssp_set_password(NTLMSSP_STATE *ntlmssp_state, const char *password)
+{
+ if (!password) {
+ ntlmssp_state->password = NULL;
+ } else {
+ ntlmssp_state->password = talloc_strdup(ntlmssp_state->mem_ctx, password);
+ if (!ntlmssp_state->password) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+/**
+ * Set a domain on an NTLMSSP context - ensures it is talloc()ed
+ *
+ */
+NTSTATUS ntlmssp_set_domain(NTLMSSP_STATE *ntlmssp_state, const char *domain)
+{
+ ntlmssp_state->domain = talloc_strdup(ntlmssp_state->mem_ctx, domain);
+ if (!ntlmssp_state->domain) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ return NT_STATUS_OK;
+}
+
+/**
+ * Set a workstation on an NTLMSSP context - ensures it is talloc()ed
+ *
+ */
+NTSTATUS ntlmssp_set_workstation(NTLMSSP_STATE *ntlmssp_state, const char *workstation)
+{
+ ntlmssp_state->workstation = talloc_strdup(ntlmssp_state->mem_ctx, workstation);
+ if (!ntlmssp_state->domain) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ return NT_STATUS_OK;
+}
+
+/**
+ * Store a DATA_BLOB containing an NTLMSSP response, for use later.
+ * This copies the data blob
+ */
+
+NTSTATUS ntlmssp_store_response(NTLMSSP_STATE *ntlmssp_state,
+ DATA_BLOB response)
+{
+ ntlmssp_state->stored_response = data_blob_talloc(ntlmssp_state->mem_ctx,
+ response.data, response.length);
+ return NT_STATUS_OK;
+}
+
+/**
+ * Next state function for the NTLMSSP state machine
+ *
+ * @param ntlmssp_state NTLMSSP State
+ * @param in The packet in from the NTLMSSP partner, as a DATA_BLOB
+ * @param out The reply, as an allocated DATA_BLOB, caller to free.
+ * @return Errors, NT_STATUS_MORE_PROCESSING_REQUIRED or NT_STATUS_OK.
+ */
+
+NTSTATUS ntlmssp_update(NTLMSSP_STATE *ntlmssp_state,
+ const DATA_BLOB in, DATA_BLOB *out)
+{
+ DATA_BLOB input;
+ uint32 ntlmssp_command;
+ int i;
+
+ *out = data_blob(NULL, 0);
+
+ if (!in.length && ntlmssp_state->stored_response.length) {
+ input = ntlmssp_state->stored_response;
+
+ /* we only want to read the stored response once - overwrite it */
+ ntlmssp_state->stored_response = data_blob(NULL, 0);
+ } else {
+ input = in;
+ }
+
+ if (!input.length) {
+ switch (ntlmssp_state->role) {
+ case NTLMSSP_CLIENT:
+ ntlmssp_command = NTLMSSP_INITIAL;
+ break;
+ case NTLMSSP_SERVER:
+ /* 'datagram' mode - no neg packet */
+ ntlmssp_command = NTLMSSP_NEGOTIATE;
+ break;
+ }
+ } else {
+ if (!msrpc_parse(&input, "Cd",
+ "NTLMSSP",
+ &ntlmssp_command)) {
+ DEBUG(1, ("Failed to parse NTLMSSP packet, could not extract NTLMSSP command\n"));
+ dump_data(2, (const char *)input.data, input.length);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ if (ntlmssp_command != ntlmssp_state->expected_state) {
+ DEBUG(1, ("got NTLMSSP command %u, expected %u\n", ntlmssp_command, ntlmssp_state->expected_state));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ for (i=0; ntlmssp_callbacks[i].fn; i++) {
+ if (ntlmssp_callbacks[i].role == ntlmssp_state->role
+ && ntlmssp_callbacks[i].ntlmssp_command == ntlmssp_command) {
+ return ntlmssp_callbacks[i].fn(ntlmssp_state, input, out);
+ }
+ }
+
+ DEBUG(1, ("failed to find NTLMSSP callback for NTLMSSP mode %u, command %u\n",
+ ntlmssp_state->role, ntlmssp_command));
+
+ return NT_STATUS_INVALID_PARAMETER;
+}
+
+/**
+ * End an NTLMSSP state machine
+ *
+ * @param ntlmssp_state NTLMSSP State, free()ed by this function
+ */
+
+void ntlmssp_end(NTLMSSP_STATE **ntlmssp_state)
+{
+ TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx;
+
+ (*ntlmssp_state)->ref_count--;
+
+ if ((*ntlmssp_state)->ref_count == 0) {
+ data_blob_free(&(*ntlmssp_state)->chal);
+ data_blob_free(&(*ntlmssp_state)->lm_resp);
+ data_blob_free(&(*ntlmssp_state)->nt_resp);
+
+ talloc_destroy(mem_ctx);
+ }
+
+ *ntlmssp_state = NULL;
+ return;
+}
+
+/**
* Determine correct target name flags for reply, given server role
* and negotiated flags
*
@@ -107,6 +318,45 @@ static const char *ntlmssp_target_name(struct ntlmssp_state *ntlmssp_state,
}
}
+static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
+ uint32 neg_flags, BOOL allow_lm) {
+ if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) {
+ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_OEM;
+ ntlmssp_state->unicode = True;
+ } else {
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_UNICODE;
+ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
+ ntlmssp_state->unicode = False;
+ }
+
+ if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY && allow_lm) {
+ /* other end forcing us to use LM */
+ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
+ ntlmssp_state->use_ntlmv2 = False;
+ } else {
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
+ }
+
+ if (!(neg_flags & NTLMSSP_NEGOTIATE_NTLM2)) {
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
+ }
+
+ if (!(neg_flags & NTLMSSP_NEGOTIATE_128)) {
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128;
+ }
+
+ if (!(neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) {
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_KEY_EXCH;
+ }
+
+ if ((neg_flags & NTLMSSP_REQUEST_TARGET)) {
+ ntlmssp_state->neg_flags |= NTLMSSP_REQUEST_TARGET;
+ }
+
+}
+
+
/**
* Next state function for the Negotiate packet
*
@@ -150,31 +400,33 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
debug_ntlmssp_flags(neg_flags);
}
- cryptkey = ntlmssp_state->get_challenge(ntlmssp_state);
+ ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, lp_lanman_auth());
- data_blob_free(&ntlmssp_state->chal);
- ntlmssp_state->chal = data_blob(cryptkey, 8);
+ /* Ask our caller what challenge they would like in the packet */
+ cryptkey = ntlmssp_state->get_challenge(ntlmssp_state);
- /* Give them the challenge. For now, ignore neg_flags and just
- return the flags we want. Obviously this is not correct */
-
- chal_flags =
- NTLMSSP_NEGOTIATE_128 |
- NTLMSSP_NEGOTIATE_NTLM;
-
- if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) {
- chal_flags |= NTLMSSP_NEGOTIATE_UNICODE;
- ntlmssp_state->unicode = True;
- } else {
- chal_flags |= NTLMSSP_NEGOTIATE_OEM;
+ /* Check if we may set the challenge */
+ if (!ntlmssp_state->may_set_challenge(ntlmssp_state)) {
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
}
+ /* The flags we send back are not just the negotiated flags,
+ * they are also 'what is in this packet'. Therfore, we
+ * operate on 'chal_flags' from here on
+ */
+
+ chal_flags = ntlmssp_state->neg_flags;
+
+ /* get the right name to fill in as 'target' */
target_name = ntlmssp_target_name(ntlmssp_state,
neg_flags, &chal_flags);
-
- if (target_name == NULL)
+ if (target_name == NULL)
return NT_STATUS_INVALID_PARAMETER;
+ ntlmssp_state->chal = data_blob_talloc(ntlmssp_state->mem_ctx, cryptkey, 8);
+ ntlmssp_state->internal_chal = data_blob_talloc(ntlmssp_state->mem_ctx, cryptkey, 8);
+
+
/* This should be a 'netbios domain -> DNS domain' mapping */
dnsdomname[0] = '\0';
get_mydomname(dnsdomname);
@@ -184,6 +436,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
get_myfullname(dnsname);
strlower_m(dnsname);
+ /* This creates the 'blob' of names that appears at the end of the packet */
if (chal_flags & NTLMSSP_CHAL_TARGET_INFO)
{
const char *target_name_dns = "";
@@ -194,16 +447,17 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
}
msrpc_gen(&struct_blob, "aaaaa",
- ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_DOMAIN, target_name,
- ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_SERVER, ntlmssp_state->get_global_myname(),
- ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_DOMAIN_DNS, target_name_dns,
- ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_SERVER_DNS, dnsdomname,
- ntlmssp_state->unicode, 0, "");
+ NTLMSSP_NAME_TYPE_DOMAIN, target_name,
+ NTLMSSP_NAME_TYPE_SERVER, ntlmssp_state->get_global_myname(),
+ NTLMSSP_NAME_TYPE_DOMAIN_DNS, dnsdomname,
+ NTLMSSP_NAME_TYPE_SERVER_DNS, dnsname,
+ 0, "");
} else {
struct_blob = data_blob(NULL, 0);
}
{
+ /* Marshel the packet in the right format, be it unicode or ASCII */
const char *gen_string;
if (ntlmssp_state->unicode) {
gen_string = "CdUdbddB";
@@ -240,13 +494,27 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
const DATA_BLOB request, DATA_BLOB *reply)
{
- DATA_BLOB sess_key;
- uint32 ntlmssp_command, neg_flags;
+ DATA_BLOB encrypted_session_key = data_blob(NULL, 0);
+ DATA_BLOB nt_session_key = data_blob(NULL, 0);
+ DATA_BLOB lm_session_key = data_blob(NULL, 0);
+ DATA_BLOB session_key = data_blob(NULL, 0);
+ uint32 ntlmssp_command, auth_flags;
NTSTATUS nt_status;
+ /* used by NTLM2 */
+ BOOL doing_ntlm2 = False;
+
+ uchar session_nonce[16];
+ uchar session_nonce_hash[16];
+
const char *parse_string;
+ char *domain = NULL;
+ char *user = NULL;
+ char *workstation = NULL;
/* parse the NTLMSSP packet */
+ *reply = data_blob(NULL, 0);
+
#if 0
file_save("ntlmssp_auth.dat", request.data, request.length);
#endif
@@ -260,9 +528,9 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
data_blob_free(&ntlmssp_state->lm_resp);
data_blob_free(&ntlmssp_state->nt_resp);
- SAFE_FREE(ntlmssp_state->user);
- SAFE_FREE(ntlmssp_state->domain);
- SAFE_FREE(ntlmssp_state->workstation);
+ ntlmssp_state->user = NULL;
+ ntlmssp_state->domain = NULL;
+ ntlmssp_state->workstation = NULL;
/* now the NTLMSSP encoded auth hashes */
if (!msrpc_parse(&request, parse_string,
@@ -270,18 +538,73 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
&ntlmssp_command,
&ntlmssp_state->lm_resp,
&ntlmssp_state->nt_resp,
- &ntlmssp_state->domain,
- &ntlmssp_state->user,
- &ntlmssp_state->workstation,
- &sess_key,
- &neg_flags)) {
+ &domain,
+ &user,
+ &workstation,
+ &encrypted_session_key,
+ &auth_flags)) {
DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n"));
dump_data(2, (const char *)request.data, request.length);
- return NT_STATUS_INVALID_PARAMETER;
+ SAFE_FREE(domain);
+ SAFE_FREE(user);
+ SAFE_FREE(workstation);
+ data_blob_free(&encrypted_session_key);
+ auth_flags = 0;
+
+ /* Try again with a shorter string (Win9X truncates this packet) */
+ if (ntlmssp_state->unicode) {
+ parse_string = "CdBBUUU";
+ } else {
+ parse_string = "CdBBAAA";
+ }
+
+ /* now the NTLMSSP encoded auth hashes */
+ if (!msrpc_parse(&request, parse_string,
+ "NTLMSSP",
+ &ntlmssp_command,
+ &ntlmssp_state->lm_resp,
+ &ntlmssp_state->nt_resp,
+ &domain,
+ &user,
+ &workstation)) {
+ DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n"));
+ dump_data(2, (const char *)request.data, request.length);
+ SAFE_FREE(domain);
+ SAFE_FREE(user);
+ SAFE_FREE(workstation);
+
+ return NT_STATUS_INVALID_PARAMETER;
+ }
}
- data_blob_free(&sess_key);
-
+ if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
+ SAFE_FREE(domain);
+ SAFE_FREE(user);
+ SAFE_FREE(workstation);
+ data_blob_free(&encrypted_session_key);
+ return nt_status;
+ }
+
+ if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
+ SAFE_FREE(domain);
+ SAFE_FREE(user);
+ SAFE_FREE(workstation);
+ data_blob_free(&encrypted_session_key);
+ return nt_status;
+ }
+
+ if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_workstation(ntlmssp_state, workstation))) {
+ SAFE_FREE(domain);
+ SAFE_FREE(user);
+ SAFE_FREE(workstation);
+ data_blob_free(&encrypted_session_key);
+ return nt_status;
+ }
+
+ SAFE_FREE(domain);
+ SAFE_FREE(user);
+ SAFE_FREE(workstation);
+
DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n",
ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, (unsigned long)ntlmssp_state->lm_resp.length, (unsigned long)ntlmssp_state->nt_resp.length));
@@ -290,9 +613,98 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
file_save("lmhash1.dat", &ntlmssp_state->lm_resp.data, &ntlmssp_state->lm_resp.length);
#endif
- nt_status = ntlmssp_state->check_password(ntlmssp_state);
+ /* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a
+ client challenge
- *reply = data_blob(NULL, 0);
+ However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful.
+ */
+ if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
+ if (ntlmssp_state->nt_resp.length == 24 && ntlmssp_state->lm_resp.length == 24) {
+ struct MD5Context md5_session_nonce_ctx;
+ SMB_ASSERT(ntlmssp_state->internal_chal.data && ntlmssp_state->internal_chal.length == 8);
+
+ doing_ntlm2 = True;
+
+ memcpy(session_nonce, ntlmssp_state->internal_chal.data, 8);
+ memcpy(&session_nonce[8], ntlmssp_state->lm_resp.data, 8);
+
+ MD5Init(&md5_session_nonce_ctx);
+ MD5Update(&md5_session_nonce_ctx, session_nonce, 16);
+ MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
+
+ ntlmssp_state->chal = data_blob_talloc(ntlmssp_state->mem_ctx, session_nonce_hash, 8);
+
+ /* LM response is no longer useful */
+ data_blob_free(&ntlmssp_state->lm_resp);
+
+ /* We changed the effective challenge - set it */
+ if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->set_challenge(ntlmssp_state, &ntlmssp_state->chal))) {
+ data_blob_free(&encrypted_session_key);
+ return nt_status;
+ }
+ }
+ }
+
+ /* Finally, actually ask if the password is OK */
+ if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state, &nt_session_key, &lm_session_key))) {
+ data_blob_free(&encrypted_session_key);
+ return nt_status;
+ }
+
+ dump_data_pw("NT session key:\n", nt_session_key.data, nt_session_key.length);
+ dump_data_pw("LM first-8:\n", lm_session_key.data, lm_session_key.length);
+
+ /* Handle the different session key derivation for NTLM2 */
+ if (doing_ntlm2) {
+ if (nt_session_key.data && nt_session_key.length == 16) {
+ session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
+ hmac_md5(nt_session_key.data, session_nonce,
+ sizeof(session_nonce), session_key.data);
+ dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
+
+ }
+ } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {
+ if (lm_session_key.data && lm_session_key.length >= 8 &&
+ ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) {
+ session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
+ SMBsesskeygen_lmv1(lm_session_key.data, ntlmssp_state->lm_resp.data,
+ session_key.data);
+ dump_data_pw("LM session key:\n", session_key.data, session_key.length);
+ }
+ } else if (nt_session_key.data) {
+ session_key = nt_session_key;
+ dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
+ }
+
+ /* With KEY_EXCH, the client supplies the proposed session key,
+ but encrypts it with the long-term key */
+ if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
+ if (!encrypted_session_key.data || encrypted_session_key.length != 16) {
+ data_blob_free(&encrypted_session_key);
+ DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n",
+ encrypted_session_key.length));
+ return NT_STATUS_INVALID_PARAMETER;
+ } else if (!session_key.data || session_key.length != 16) {
+ DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n",
+ session_key.length));
+ } else {
+ dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
+ SamOEMhash(encrypted_session_key.data,
+ session_key.data,
+ encrypted_session_key.length);
+ ntlmssp_state->session_key = data_blob_talloc(ntlmssp_state->mem_ctx,
+ encrypted_session_key.data,
+ encrypted_session_key.length);
+ dump_data_pw("KEY_EXCH session key:\n", session_key.data, session_key.length);
+ }
+ } else {
+ ntlmssp_state->session_key = session_key;
+ }
+
+ data_blob_free(&encrypted_session_key);
+
+ /* allow arbitarily many authentications */
+ ntlmssp_state->expected_state = NTLMSSP_AUTH;
return nt_status;
}
@@ -316,8 +728,12 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state)
return NT_STATUS_NO_MEMORY;
}
+ (*ntlmssp_state)->role = NTLMSSP_SERVER;
+
(*ntlmssp_state)->mem_ctx = mem_ctx;
(*ntlmssp_state)->get_challenge = get_challenge;
+ (*ntlmssp_state)->set_challenge = set_challenge;
+ (*ntlmssp_state)->may_set_challenge = may_set_challenge;
(*ntlmssp_state)->get_global_myname = global_myname;
(*ntlmssp_state)->get_domain = lp_workgroup;
@@ -325,73 +741,18 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state)
(*ntlmssp_state)->expected_state = NTLMSSP_NEGOTIATE;
- return NT_STATUS_OK;
-}
-
-/**
- * End an NTLMSSP state machine
- *
- * @param ntlmssp_state NTLMSSP State, free()ed by this function
- */
-
-NTSTATUS ntlmssp_server_end(NTLMSSP_STATE **ntlmssp_state)
-{
- TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx;
-
- data_blob_free(&(*ntlmssp_state)->chal);
- data_blob_free(&(*ntlmssp_state)->lm_resp);
- data_blob_free(&(*ntlmssp_state)->nt_resp);
+ (*ntlmssp_state)->ref_count = 1;
- SAFE_FREE((*ntlmssp_state)->user);
- SAFE_FREE((*ntlmssp_state)->domain);
- SAFE_FREE((*ntlmssp_state)->workstation);
+ (*ntlmssp_state)->neg_flags =
+ NTLMSSP_NEGOTIATE_128 |
+ NTLMSSP_NEGOTIATE_NTLM |
+ NTLMSSP_NEGOTIATE_NTLM2 |
+ NTLMSSP_NEGOTIATE_KEY_EXCH |
+ NTLMSSP_NEGOTIATE_SIGN;
- talloc_destroy(mem_ctx);
- *ntlmssp_state = NULL;
return NT_STATUS_OK;
}
-/**
- * Next state function for the NTLMSSP state machine
- *
- * @param ntlmssp_state NTLMSSP State
- * @param request The request, as a DATA_BLOB
- * @param request The reply, as an allocated DATA_BLOB, caller to free.
- * @return Errors, NT_STATUS_MORE_PROCESSING_REQUIRED or NT_STATUS_OK.
- */
-
-NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state,
- const DATA_BLOB request, DATA_BLOB *reply)
-{
- uint32 ntlmssp_command;
- *reply = data_blob(NULL, 0);
-
- if (request.length) {
- if (!msrpc_parse(&request, "Cd",
- "NTLMSSP",
- &ntlmssp_command)) {
- return NT_STATUS_INVALID_PARAMETER;
- }
- } else {
- /* 'datagram' mode - no neg packet */
- ntlmssp_command = NTLMSSP_NEGOTIATE;
- }
-
- if (ntlmssp_command != ntlmssp_state->expected_state) {
- DEBUG(1, ("got NTLMSSP command %u, expected %u\n", ntlmssp_command, ntlmssp_state->expected_state));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (ntlmssp_command == NTLMSSP_NEGOTIATE) {
- return ntlmssp_server_negotiate(ntlmssp_state, request, reply);
- } else if (ntlmssp_command == NTLMSSP_AUTH) {
- return ntlmssp_server_auth(ntlmssp_state, request, reply);
- } else {
- DEBUG(1, ("unknown NTLMSSP command %u, expected %u\n", ntlmssp_command, ntlmssp_state->expected_state));
- return NT_STATUS_INVALID_PARAMETER;
- }
-}
-
/*********************************************************************
Client side NTLMSSP
*********************************************************************/
@@ -405,19 +766,19 @@ NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state,
* @return Errors or NT_STATUS_OK.
*/
-static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_state,
+static NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state,
DATA_BLOB reply, DATA_BLOB *next_request)
{
if (ntlmssp_state->unicode) {
ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
+ } else {
+ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
}
if (ntlmssp_state->use_ntlmv2) {
ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
}
- ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
-
/* generate the ntlmssp negotiate packet */
msrpc_gen(next_request, "CddAA",
"NTLMSSP",
@@ -426,6 +787,8 @@ static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_stat
ntlmssp_state->get_domain(),
ntlmssp_state->get_global_myname());
+ ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
+
return NT_STATUS_MORE_PROCESSING_REQUIRED;
}
@@ -438,7 +801,7 @@ static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_stat
* @return Errors or NT_STATUS_OK.
*/
-static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_state,
+static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
const DATA_BLOB reply, DATA_BLOB *next_request)
{
uint32 chal_flags, ntlmssp_command, unkn1, unkn2;
@@ -452,6 +815,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
DATA_BLOB nt_response = data_blob(NULL, 0);
DATA_BLOB session_key = data_blob(NULL, 0);
DATA_BLOB encrypted_session_key = data_blob(NULL, 0);
+ NTSTATUS nt_status;
if (!msrpc_parse(&reply, "CdBd",
"NTLMSSP",
@@ -469,17 +833,16 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
DEBUG(3, ("Got challenge flags:\n"));
debug_ntlmssp_flags(chal_flags);
- if (chal_flags & NTLMSSP_NEGOTIATE_UNICODE) {
+ ntlmssp_handle_neg_flags(ntlmssp_state, chal_flags, lp_client_lanman_auth());
+
+ if (ntlmssp_state->unicode) {
if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) {
chal_parse_string = "CdUdbddB";
} else {
chal_parse_string = "CdUdbdd";
}
auth_gen_string = "CdBBUUUBd";
- ntlmssp_state->unicode = True;
- ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
- ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_OEM;
- } else if (chal_flags & NTLMSSP_NEGOTIATE_OEM) {
+ } else {
if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) {
chal_parse_string = "CdAdbddB";
} else {
@@ -487,32 +850,6 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
}
auth_gen_string = "CdBBAAABd";
-
- ntlmssp_state->unicode = False;
- ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_UNICODE;
- ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
- } else {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (chal_flags & NTLMSSP_NEGOTIATE_LM_KEY && lp_client_lanman_auth()) {
- /* server forcing us to use LM */
- ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
- ntlmssp_state->use_ntlmv2 = False;
- } else {
- ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
- }
-
- if (!(chal_flags & NTLMSSP_NEGOTIATE_NTLM2)) {
- ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
- }
-
- if (!(chal_flags & NTLMSSP_NEGOTIATE_128)) {
- ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128;
- }
-
- if (!(chal_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) {
- ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_KEY_EXCH;
}
DEBUG(3, ("NTLMSSP: Set final flags:\n"));
@@ -546,6 +883,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
if (!struct_blob.length) {
/* be lazy, match win2k - we can't do NTLMv2 without it */
+ DEBUG(1, ("Server did not provide 'target information', required for NTLMv2\n"));
return NT_STATUS_INVALID_PARAMETER;
}
@@ -569,7 +907,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
uchar nt_session_key[16];
E_md4hash(ntlmssp_state->password, nt_hash);
- lm_response = data_blob(NULL, 24);
+ lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
generate_random_buffer(lm_response.data, 8, False);
memset(lm_response.data+8, 0, 16);
@@ -580,16 +918,21 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
MD5Update(&md5_session_nonce_ctx, challenge_blob.data, 8);
MD5Update(&md5_session_nonce_ctx, lm_response.data, 8);
MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
+
+ DEBUG(5, ("NTLMSSP challenge set by NTLM2\n"));
+ DEBUG(5, ("challenge is: \n"));
+ dump_data(5, session_nonce_hash, 8);
- nt_response = data_blob(NULL, 24);
+ nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
SMBNTencrypt(ntlmssp_state->password,
session_nonce_hash,
nt_response.data);
- session_key = data_blob(NULL, 16);
+ session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
SMBsesskeygen_ntv1(nt_hash, NULL, nt_session_key);
hmac_md5(nt_session_key, session_nonce, sizeof(session_nonce), session_key.data);
+ dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
} else {
@@ -600,22 +943,24 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
/* lanman auth is insecure, it may be disabled */
if (lp_client_lanman_auth()) {
- lm_response = data_blob(NULL, 24);
+ lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
SMBencrypt(ntlmssp_state->password,challenge_blob.data,
lm_response.data);
- }
+ }
- nt_response = data_blob(NULL, 24);
+ nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
SMBNTencrypt(ntlmssp_state->password,challenge_blob.data,
nt_response.data);
- session_key = data_blob(NULL, 16);
+ session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
&& lp_client_lanman_auth()) {
SMBsesskeygen_lmv1(lm_hash, lm_response.data,
session_key.data);
+ dump_data_pw("LM session key\n", session_key.data, session_key.length);
} else {
SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
+ dump_data_pw("NT session key:\n", session_key.data, session_key.length);
}
}
data_blob_free(&struct_blob);
@@ -627,9 +972,12 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
generate_random_buffer(client_session_key, sizeof(client_session_key), False);
encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key));
+ dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length);
+
SamOEMhash(encrypted_session_key.data, session_key.data, encrypted_session_key.length);
data_blob_free(&session_key);
- session_key = data_blob(client_session_key, sizeof(client_session_key));
+ session_key = data_blob_talloc(ntlmssp_state->mem_ctx, client_session_key, sizeof(client_session_key));
+ dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
}
/* this generates the actual auth packet */
@@ -644,28 +992,29 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
encrypted_session_key.data, encrypted_session_key.length,
ntlmssp_state->neg_flags)) {
- data_blob_free(&lm_response);
- data_blob_free(&nt_response);
- data_blob_free(&session_key);
return NT_STATUS_NO_MEMORY;
}
data_blob_free(&encrypted_session_key);
data_blob_free(&ntlmssp_state->chal);
- data_blob_free(&ntlmssp_state->lm_resp);
- data_blob_free(&ntlmssp_state->nt_resp);
- data_blob_free(&ntlmssp_state->session_key);
ntlmssp_state->chal = challenge_blob;
ntlmssp_state->lm_resp = lm_response;
ntlmssp_state->nt_resp = nt_response;
ntlmssp_state->session_key = session_key;
+ ntlmssp_state->expected_state = NTLMSSP_UNKNOWN;
+
+ if (!NT_STATUS_IS_OK(nt_status = ntlmssp_sign_init(ntlmssp_state))) {
+ DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n", nt_errstr(nt_status)));
+ return nt_status;
+ }
+
return NT_STATUS_MORE_PROCESSING_REQUIRED;
}
-NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state)
+NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state)
{
TALLOC_CTX *mem_ctx;
@@ -678,6 +1027,8 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state)
return NT_STATUS_NO_MEMORY;
}
+ (*ntlmssp_state)->role = NTLMSSP_CLIENT;
+
(*ntlmssp_state)->mem_ctx = mem_ctx;
(*ntlmssp_state)->get_global_myname = global_myname;
@@ -687,6 +1038,10 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state)
(*ntlmssp_state)->use_ntlmv2 = lp_client_ntlmv2_auth();
+ (*ntlmssp_state)->expected_state = NTLMSSP_INITIAL;
+
+ (*ntlmssp_state)->ref_count = 1;
+
(*ntlmssp_state)->neg_flags =
NTLMSSP_NEGOTIATE_128 |
NTLMSSP_NEGOTIATE_NTLM |
@@ -700,101 +1055,6 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state)
NTLMSSP_NEGOTIATE_SIGN |
NTLMSSP_REQUEST_TARGET;
- (*ntlmssp_state)->ref_count = 1;
-
- return NT_STATUS_OK;
-}
-
-NTSTATUS ntlmssp_client_end(NTLMSSP_CLIENT_STATE **ntlmssp_state)
-{
- TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx;
-
- (*ntlmssp_state)->ref_count--;
-
- if ((*ntlmssp_state)->ref_count == 0) {
- data_blob_free(&(*ntlmssp_state)->chal);
- data_blob_free(&(*ntlmssp_state)->lm_resp);
- data_blob_free(&(*ntlmssp_state)->nt_resp);
- data_blob_free(&(*ntlmssp_state)->session_key);
- data_blob_free(&(*ntlmssp_state)->stored_response);
- talloc_destroy(mem_ctx);
- }
-
- *ntlmssp_state = NULL;
return NT_STATUS_OK;
}
-NTSTATUS ntlmssp_client_update(NTLMSSP_CLIENT_STATE *ntlmssp_state,
- DATA_BLOB reply, DATA_BLOB *next_request)
-{
- NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
- uint32 ntlmssp_command;
- *next_request = data_blob(NULL, 0);
-
- if (!reply.length) {
- /* If there is a cached reply, use it - otherwise this is the first packet */
- if (!ntlmssp_state->stored_response.length) {
- return ntlmssp_client_initial(ntlmssp_state, reply, next_request);
- }
-
- reply = ntlmssp_state->stored_response;
- }
-
- if (!msrpc_parse(&reply, "Cd",
- "NTLMSSP",
- &ntlmssp_command)) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (ntlmssp_command == NTLMSSP_CHALLENGE) {
- nt_status = ntlmssp_client_challenge(ntlmssp_state, reply, next_request);
- }
- if (ntlmssp_state->stored_response.length) {
- data_blob_free(&ntlmssp_state->stored_response);
- }
- return nt_status;
-}
-
-NTSTATUS ntlmssp_set_username(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *user)
-{
- ntlmssp_state->user = talloc_strdup(ntlmssp_state->mem_ctx, user);
- if (!ntlmssp_state->user) {
- return NT_STATUS_NO_MEMORY;
- }
- return NT_STATUS_OK;
-}
-
-NTSTATUS ntlmssp_set_password(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *password)
-{
- if (!password) {
- ntlmssp_state->password = NULL;
- } else {
- ntlmssp_state->password = talloc_strdup(ntlmssp_state->mem_ctx, password);
- if (!ntlmssp_state->password) {
- return NT_STATUS_NO_MEMORY;
- }
- }
- return NT_STATUS_OK;
-}
-
-NTSTATUS ntlmssp_set_domain(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *domain)
-{
- ntlmssp_state->domain = talloc_strdup(ntlmssp_state->mem_ctx, domain);
- if (!ntlmssp_state->domain) {
- return NT_STATUS_NO_MEMORY;
- }
- return NT_STATUS_OK;
-}
-
-/**
- * Store a DATA_BLOB containing an NTLMSSP response, for use later.
- * This 'keeps' the data blob - the caller must *not* free it.
- */
-
-NTSTATUS ntlmssp_client_store_response(NTLMSSP_CLIENT_STATE *ntlmssp_state,
- DATA_BLOB response)
-{
- data_blob_free(&ntlmssp_state->stored_response);
- ntlmssp_state->stored_response = response;
- return NT_STATUS_OK;
-}
diff --git a/source/libsmb/ntlmssp_parse.c b/source/libsmb/ntlmssp_parse.c
index b136dacf5a2..3444db03068 100644
--- a/source/libsmb/ntlmssp_parse.c
+++ b/source/libsmb/ntlmssp_parse.c
@@ -31,7 +31,7 @@
format specifiers are:
U = unicode string (input is unix string)
- a = address (input is BOOL unicode, char *unix_string)
+ a = address (input is char *unix_string)
(1 byte type, 1 byte length, unicode/ASCII string, all inline)
A = ASCII string (input is unix string)
B = data blob (pointer + length)
@@ -49,7 +49,6 @@ BOOL msrpc_gen(DATA_BLOB *blob,
uint8 *b;
int head_size=0, data_size=0;
int head_ofs, data_ofs;
- BOOL unicode;
/* first scan the format to work out the header and body size */
va_start(ap, format);
@@ -66,14 +65,9 @@ BOOL msrpc_gen(DATA_BLOB *blob,
data_size += str_ascii_charnum(s);
break;
case 'a':
- unicode = va_arg(ap, BOOL);
n = va_arg(ap, int);
s = va_arg(ap, char *);
- if (unicode) {
- data_size += (str_charnum(s) * 2) + 4;
- } else {
- data_size += (str_ascii_charnum(s)) + 4;
- }
+ data_size += (str_charnum(s) * 2) + 4;
break;
case 'B':
b = va_arg(ap, uint8 *);
@@ -124,27 +118,16 @@ BOOL msrpc_gen(DATA_BLOB *blob,
data_ofs += n;
break;
case 'a':
- unicode = va_arg(ap, BOOL);
n = va_arg(ap, int);
SSVAL(blob->data, data_ofs, n); data_ofs += 2;
s = va_arg(ap, char *);
- if (unicode) {
- n = str_charnum(s);
- SSVAL(blob->data, data_ofs, n*2); data_ofs += 2;
- if (0 < n) {
- push_string(NULL, blob->data+data_ofs, s, n*2,
- STR_UNICODE|STR_NOALIGN);
- }
- data_ofs += n*2;
- } else {
- n = str_ascii_charnum(s);
- SSVAL(blob->data, data_ofs, n); data_ofs += 2;
- if (0 < n) {
- push_string(NULL, blob->data+data_ofs, s, n,
- STR_ASCII|STR_NOALIGN);
- }
- data_ofs += n;
+ n = str_charnum(s);
+ SSVAL(blob->data, data_ofs, n*2); data_ofs += 2;
+ if (0 < n) {
+ push_string(NULL, blob->data+data_ofs, s, n*2,
+ STR_UNICODE|STR_NOALIGN);
}
+ data_ofs += n*2;
break;
case 'B':
diff --git a/source/libsmb/ntlmssp_sign.c b/source/libsmb/ntlmssp_sign.c
index 153c234d1f8..ea1a7037c9c 100644
--- a/source/libsmb/ntlmssp_sign.c
+++ b/source/libsmb/ntlmssp_sign.c
@@ -102,7 +102,7 @@ enum ntlmssp_direction {
NTLMSSP_RECEIVE
};
-static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_CLIENT_STATE *ntlmssp_state,
+static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state,
const uchar *data, size_t length,
enum ntlmssp_direction direction,
DATA_BLOB *sig)
@@ -113,7 +113,7 @@ static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_CLIENT_STATE *ntlmssp_stat
uchar digest[16];
SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);
- hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->cli_sign_const), 16, &ctx);
+ hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx);
hmac_md5_update((const unsigned char *)seq_num, 4, &ctx);
hmac_md5_update(data, length, &ctx);
hmac_md5_final(digest, &ctx);
@@ -124,10 +124,10 @@ static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_CLIENT_STATE *ntlmssp_stat
}
switch (direction) {
case NTLMSSP_SEND:
- NTLMSSPcalc_ap(ntlmssp_state->cli_sign_hash, sig->data+4, sig->length-4);
+ NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash, sig->data+4, sig->length-4);
break;
case NTLMSSP_RECEIVE:
- NTLMSSPcalc_ap(ntlmssp_state->srv_sign_hash, sig->data+4, sig->length-4);
+ NTLMSSPcalc_ap(ntlmssp_state->recv_sign_hash, sig->data+4, sig->length-4);
break;
}
} else {
@@ -144,9 +144,9 @@ static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_CLIENT_STATE *ntlmssp_stat
return NT_STATUS_OK;
}
-NTSTATUS ntlmssp_client_sign_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state,
- const uchar *data, size_t length,
- DATA_BLOB *sig)
+NTSTATUS ntlmssp_sign_packet(NTLMSSP_STATE *ntlmssp_state,
+ const uchar *data, size_t length,
+ DATA_BLOB *sig)
{
NTSTATUS nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data, length, NTLMSSP_SEND, sig);
@@ -161,9 +161,9 @@ NTSTATUS ntlmssp_client_sign_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state,
*
*/
-NTSTATUS ntlmssp_client_check_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state,
- const uchar *data, size_t length,
- const DATA_BLOB *sig)
+NTSTATUS ntlmssp_check_packet(NTLMSSP_STATE *ntlmssp_state,
+ const uchar *data, size_t length,
+ const DATA_BLOB *sig)
{
DATA_BLOB local_sig;
NTSTATUS nt_status;
@@ -204,11 +204,11 @@ NTSTATUS ntlmssp_client_check_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state,
*
*/
-NTSTATUS ntlmssp_client_seal_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state,
- uchar *data, size_t length,
- DATA_BLOB *sig)
+NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state,
+ uchar *data, size_t length,
+ DATA_BLOB *sig)
{
- DEBUG(10,("ntlmssp_client_seal_data: seal\n"));
+ DEBUG(10,("ntlmssp_seal_data: seal\n"));
dump_data_pw("ntlmssp clear data\n", data, length);
if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
HMACMD5Context ctx;
@@ -216,7 +216,7 @@ NTSTATUS ntlmssp_client_seal_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state,
uchar digest[16];
SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);
- hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->cli_sign_const), 16, &ctx);
+ hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx);
hmac_md5_update((const unsigned char *)seq_num, 4, &ctx);
hmac_md5_update(data, length, &ctx);
hmac_md5_final(digest, &ctx);
@@ -227,13 +227,13 @@ NTSTATUS ntlmssp_client_seal_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state,
}
dump_data_pw("ntlmssp client sealing hash:\n",
- ntlmssp_state->cli_seal_hash,
- sizeof(ntlmssp_state->cli_seal_hash));
- NTLMSSPcalc_ap(ntlmssp_state->cli_seal_hash, data, length);
+ ntlmssp_state->send_seal_hash,
+ sizeof(ntlmssp_state->send_seal_hash));
+ NTLMSSPcalc_ap(ntlmssp_state->send_seal_hash, data, length);
dump_data_pw("ntlmssp client signing hash:\n",
- ntlmssp_state->cli_sign_hash,
- sizeof(ntlmssp_state->cli_sign_hash));
- NTLMSSPcalc_ap(ntlmssp_state->cli_sign_hash, sig->data+4, sig->length-4);
+ ntlmssp_state->send_sign_hash,
+ sizeof(ntlmssp_state->send_sign_hash));
+ NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash, sig->data+4, sig->length-4);
} else {
uint32 crc;
crc = crc32_calc_buffer((const char *)data, length);
@@ -266,14 +266,14 @@ NTSTATUS ntlmssp_client_seal_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state,
*
*/
-NTSTATUS ntlmssp_client_unseal_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state,
+NTSTATUS ntlmssp_unseal_packet(NTLMSSP_STATE *ntlmssp_state,
uchar *data, size_t length,
DATA_BLOB *sig)
{
- DEBUG(10,("ntlmssp_client_unseal_data: seal\n"));
+ DEBUG(10,("ntlmssp__unseal_data: seal\n"));
dump_data_pw("ntlmssp sealed data\n", data, length);
if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
- NTLMSSPcalc_ap(ntlmssp_state->srv_seal_hash, data, length);
+ NTLMSSPcalc_ap(ntlmssp_state->recv_seal_hash, data, length);
} else {
dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
sizeof(ntlmssp_state->ntlmssp_hash));
@@ -281,13 +281,13 @@ NTSTATUS ntlmssp_client_unseal_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state,
}
dump_data_pw("ntlmssp clear data\n", data, length);
- return ntlmssp_client_check_packet(ntlmssp_state, data, length, sig);
+ return ntlmssp_check_packet(ntlmssp_state, data, length, sig);
}
/**
Initialise the state for NTLMSSP signing.
*/
-NTSTATUS ntlmssp_client_sign_init(NTLMSSP_CLIENT_STATE *ntlmssp_state)
+NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state)
{
unsigned char p24[24];
ZERO_STRUCT(p24);
@@ -297,34 +297,54 @@ NTSTATUS ntlmssp_client_sign_init(NTLMSSP_CLIENT_STATE *ntlmssp_state)
if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2)
{
+ const char *send_sign_const;
+ const char *send_seal_const;
+ const char *recv_sign_const;
+ const char *recv_seal_const;
+
+ switch (ntlmssp_state->role) {
+ case NTLMSSP_CLIENT:
+ send_sign_const = CLI_SIGN;
+ send_seal_const = CLI_SEAL;
+ recv_sign_const = SRV_SIGN;
+ recv_seal_const = SRV_SEAL;
+ break;
+ case NTLMSSP_SERVER:
+ send_sign_const = SRV_SIGN;
+ send_seal_const = SRV_SEAL;
+ recv_sign_const = CLI_SIGN;
+ recv_seal_const = CLI_SEAL;
+ break;
+ }
+
+ calc_ntlmv2_hash(ntlmssp_state->send_sign_hash,
+ ntlmssp_state->send_sign_const,
+ ntlmssp_state->session_key, send_sign_const);
+ dump_data_pw("NTLMSSP send sign hash:\n",
+ ntlmssp_state->send_sign_hash,
+ sizeof(ntlmssp_state->send_sign_hash));
+
+ calc_ntlmv2_hash(ntlmssp_state->send_seal_hash,
+ ntlmssp_state->send_seal_const,
+ ntlmssp_state->session_key, send_seal_const);
+ dump_data_pw("NTLMSSP send sesl hash:\n",
+ ntlmssp_state->send_seal_hash,
+ sizeof(ntlmssp_state->send_seal_hash));
+
+ calc_ntlmv2_hash(ntlmssp_state->recv_sign_hash,
+ ntlmssp_state->recv_sign_const,
+ ntlmssp_state->session_key, send_sign_const);
+ dump_data_pw("NTLMSSP receive sign hash:\n",
+ ntlmssp_state->recv_sign_hash,
+ sizeof(ntlmssp_state->recv_sign_hash));
+
+ calc_ntlmv2_hash(ntlmssp_state->recv_seal_hash,
+ ntlmssp_state->recv_seal_const,
+ ntlmssp_state->session_key, send_seal_const);
+ dump_data_pw("NTLMSSP receive seal hash:\n",
+ ntlmssp_state->recv_sign_hash,
+ sizeof(ntlmssp_state->recv_sign_hash));
- calc_ntlmv2_hash(ntlmssp_state->cli_sign_hash,
- ntlmssp_state->cli_sign_const,
- ntlmssp_state->session_key, CLI_SIGN);
- dump_data_pw("NTLMSSP client sign hash:\n",
- ntlmssp_state->cli_sign_hash,
- sizeof(ntlmssp_state->cli_sign_hash));
-
- calc_ntlmv2_hash(ntlmssp_state->cli_seal_hash,
- ntlmssp_state->cli_seal_const,
- ntlmssp_state->session_key, CLI_SEAL);
- dump_data_pw("NTLMSSP client sesl hash:\n",
- ntlmssp_state->cli_seal_hash,
- sizeof(ntlmssp_state->cli_seal_hash));
-
- calc_ntlmv2_hash(ntlmssp_state->srv_sign_hash,
- ntlmssp_state->srv_sign_const,
- ntlmssp_state->session_key, SRV_SIGN);
- dump_data_pw("NTLMSSP server sign hash:\n",
- ntlmssp_state->srv_sign_hash,
- sizeof(ntlmssp_state->srv_sign_hash));
-
- calc_ntlmv2_hash(ntlmssp_state->srv_seal_hash,
- ntlmssp_state->srv_seal_const,
- ntlmssp_state->session_key, SRV_SEAL);
- dump_data_pw("NTLMSSP server seal hash:\n",
- ntlmssp_state->cli_sign_hash,
- sizeof(ntlmssp_state->cli_sign_hash));
}
else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {
if (!ntlmssp_state->session_key.data || ntlmssp_state->session_key.length < 8) {
diff --git a/source/libsmb/smb_signing.c b/source/libsmb/smb_signing.c
index 91509f0fb81..6b2abb9ccc8 100644
--- a/source/libsmb/smb_signing.c
+++ b/source/libsmb/smb_signing.c
@@ -370,7 +370,7 @@ We were expecting seq %u\n", reply_seq_number, saved_seq ));
#endif /* JRATEST */
} else {
- DEBUG(10, ("client_check_incoming_message:: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
+ DEBUG(10, ("client_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
dump_data(10, (const char *)server_sent_mac, 8);
}
return signing_good(inbuf, si, good, saved_seq);
@@ -405,11 +405,11 @@ static void simple_free_signing_context(struct smb_sign_info *si)
SMB signing - Simple implementation - setup the MAC key.
************************************************************/
-BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[16], const DATA_BLOB response)
+BOOL cli_simple_set_signing(struct cli_state *cli, const DATA_BLOB user_session_key, const DATA_BLOB response)
{
struct smb_basic_signing_context *data;
- if (!user_session_key)
+ if (!user_session_key.length)
return False;
if (!cli_set_smb_signing_common(cli)) {
@@ -425,21 +425,23 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[
cli->sign_info.signing_context = data;
- data->mac_key = data_blob(NULL, response.length + 16);
+ data->mac_key = data_blob(NULL, response.length + user_session_key.length);
- memcpy(&data->mac_key.data[0], user_session_key, 16);
+ memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
DEBUG(10, ("cli_simple_set_signing: user_session_key\n"));
- dump_data(10, (const char *)user_session_key, 16);
+ dump_data(10, (const char *)user_session_key.data, user_session_key.length);
if (response.length) {
- memcpy(&data->mac_key.data[16],response.data, response.length);
+ memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
DEBUG(10, ("cli_simple_set_signing: response_data\n"));
dump_data(10, (const char *)response.data, response.length);
} else {
DEBUG(10, ("cli_simple_set_signing: NULL response_data\n"));
}
+ dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
+
/* Initialise the sequence number */
data->send_seq_num = 0;
@@ -455,9 +457,12 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[
/***********************************************************
Tell client code we are in a multiple trans reply state.
+ We call this after the last outgoing trans2 packet (which
+ has incremented the sequence numbers), so we must save the
+ current mid and sequence number -2.
************************************************************/
-void cli_signing_trans_start(struct cli_state *cli)
+void cli_signing_trans_start(struct cli_state *cli, uint16 mid)
{
struct smb_basic_signing_context *data = cli->sign_info.signing_context;
@@ -467,9 +472,9 @@ void cli_signing_trans_start(struct cli_state *cli)
data->trans_info = smb_xmalloc(sizeof(struct trans_info_context));
ZERO_STRUCTP(data->trans_info);
- data->trans_info->send_seq_num = data->send_seq_num;
- data->trans_info->mid = SVAL(cli->outbuf,smb_mid);
- data->trans_info->reply_seq_num = data->send_seq_num+1;
+ data->trans_info->send_seq_num = data->send_seq_num-2;
+ data->trans_info->mid = mid;
+ data->trans_info->reply_seq_num = data->send_seq_num-1;
DEBUG(10,("cli_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
data->send_seq_num = %u\n",
@@ -490,10 +495,15 @@ void cli_signing_trans_stop(struct cli_state *cli)
if (!cli->sign_info.doing_signing || !data)
return;
+ DEBUG(10,("cli_signing_trans_stop: freeing mid = %u, reply_seq_num = %u, send_seq_num = %u \
+data->send_seq_num = %u\n",
+ (unsigned int)data->trans_info->mid,
+ (unsigned int)data->trans_info->reply_seq_num,
+ (unsigned int)data->trans_info->send_seq_num,
+ (unsigned int)data->send_seq_num ));
+
SAFE_FREE(data->trans_info);
data->trans_info = NULL;
-
- data->send_seq_num += 2;
}
/***********************************************************
@@ -741,7 +751,26 @@ We were expecting seq %u\n", reply_seq_number, saved_seq ));
DEBUG(10, ("srv_check_incoming_message: seq %u: (current is %u) got good SMB signature of\n", (unsigned int)reply_seq_number, (unsigned int)data->send_seq_num));
dump_data(10, (const char *)server_sent_mac, 8);
}
- return signing_good(inbuf, si, good, saved_seq);
+
+ if (!signing_good(inbuf, si, good, saved_seq)) {
+ if (!si->mandatory_signing && (data->send_seq_num < 3)){
+ /* Non-mandatory signing - just turn off if this is the first bad packet.. */
+ DEBUG(5, ("srv_check_incoming_message: signing negotiated but not required and client \
+isn't sending correct signatures. Turning off.\n"));
+ si->negotiated_smb_signing = False;
+ si->allow_smb_signing = False;
+ si->doing_signing = False;
+ free_signing_context(si);
+ return True;
+ } else {
+ /* Mandatory signing or bad packet after signing started - fail and disconnect. */
+ if (saved_seq)
+ DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u\n", (unsigned int)saved_seq));
+ return False;
+ }
+ } else {
+ return True;
+ }
}
/***********************************************************
@@ -928,11 +957,11 @@ data->send_seq_num = %u\n",
Turn on signing from this packet onwards.
************************************************************/
-void srv_set_signing(const uchar user_session_key[16], const DATA_BLOB response)
+void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response)
{
struct smb_basic_signing_context *data;
- if (!user_session_key)
+ if (!user_session_key.length)
return;
if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) {
@@ -957,11 +986,17 @@ void srv_set_signing(const uchar user_session_key[16], const DATA_BLOB response)
srv_sign_info.signing_context = data;
- data->mac_key = data_blob(NULL, response.length + 16);
+ data->mac_key = data_blob(NULL, response.length + user_session_key.length);
- memcpy(&data->mac_key.data[0], user_session_key, 16);
+ memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
if (response.length)
- memcpy(&data->mac_key.data[16],response.data, response.length);
+ memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
+
+ dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
+
+ DEBUG(3,("srv_set_signing: turning on SMB signing: signing negotiated = %s, mandatory_signing = %s.\n",
+ BOOLSTR(srv_sign_info.negotiated_smb_signing),
+ BOOLSTR(srv_sign_info.mandatory_signing) ));
/* Initialise the sequence number */
data->send_seq_num = 0;
diff --git a/source/libsmb/smbdes.c b/source/libsmb/smbdes.c
index cde77f94a36..ae946b4a660 100644
--- a/source/libsmb/smbdes.c
+++ b/source/libsmb/smbdes.c
@@ -397,6 +397,46 @@ void SamOEMhash( unsigned char *data, const unsigned char *key, int val)
}
}
+void SamOEMhashBlob( unsigned char *data, int len, DATA_BLOB *key)
+{
+ unsigned char s_box[256];
+ unsigned char index_i = 0;
+ unsigned char index_j = 0;
+ unsigned char j = 0;
+ int ind;
+
+ for (ind = 0; ind < 256; ind++)
+ {
+ s_box[ind] = (unsigned char)ind;
+ }
+
+ for( ind = 0; ind < 256; ind++)
+ {
+ unsigned char tc;
+
+ j += (s_box[ind] + key->data[ind%key->length]);
+
+ tc = s_box[ind];
+ s_box[ind] = s_box[j];
+ s_box[j] = tc;
+ }
+ for( ind = 0; ind < len; ind++)
+ {
+ unsigned char tc;
+ unsigned char t;
+
+ index_i++;
+ index_j += s_box[index_i];
+
+ tc = s_box[index_i];
+ s_box[index_i] = s_box[index_j];
+ s_box[index_j] = tc;
+
+ t = s_box[index_i] + s_box[index_j];
+ data[ind] = data[ind] ^ s_box[t];
+ }
+}
+
/* Decode a sam password hash into a password. The password hash is the
same method used to store passwords in the NT registry. The DES key
used is based on the RID of the user. */
diff --git a/source/libsmb/smbencrypt.c b/source/libsmb/smbencrypt.c
index ec31bb5dbaa..2d02a233943 100644
--- a/source/libsmb/smbencrypt.c
+++ b/source/libsmb/smbencrypt.c
@@ -331,9 +331,9 @@ DATA_BLOB NTLMv2_generate_names_blob(const char *hostname,
DATA_BLOB names_blob = data_blob(NULL, 0);
msrpc_gen(&names_blob, "aaa",
- True, NTLMSSP_NAME_TYPE_DOMAIN, domain,
- True, NTLMSSP_NAME_TYPE_SERVER, hostname,
- True, 0, "");
+ NTLMSSP_NAME_TYPE_DOMAIN, domain,
+ NTLMSSP_NAME_TYPE_SERVER, hostname,
+ 0, "");
return names_blob;
}
diff --git a/source/libsmb/trusts_util.c b/source/libsmb/trusts_util.c
index c18641bc845..2c6eb1b55a8 100644
--- a/source/libsmb/trusts_util.c
+++ b/source/libsmb/trusts_util.c
@@ -181,6 +181,7 @@ BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
done:
/* cleanup */
if (cli) {
+ DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
cli_nt_session_close( cli );
cli_shutdown( cli );
}
diff --git a/source/nsswitch/wbinfo.c b/source/nsswitch/wbinfo.c
index 04233bb85cb..1256ec3a3bc 100644
--- a/source/nsswitch/wbinfo.c
+++ b/source/nsswitch/wbinfo.c
@@ -136,6 +136,37 @@ static BOOL wbinfo_get_usergroups(char *user)
return True;
}
+
+/* List group SIDs a user SID is a member of */
+static BOOL wbinfo_get_usersids(char *user_sid)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+ int i;
+ const char *s;
+
+ ZERO_STRUCT(response);
+
+ /* Send request */
+ fstrcpy(request.data.sid, user_sid);
+
+ result = winbindd_request(WINBINDD_GETUSERSIDS, &request, &response);
+
+ if (result != NSS_STATUS_SUCCESS)
+ return False;
+
+ s = response.extra_data;
+ for (i = 0; i < response.data.num_entries; i++) {
+ d_printf("%s\n", s);
+ s += strlen(s) + 1;
+ }
+
+ SAFE_FREE(response.extra_data);
+
+ return True;
+}
+
/* Convert NetBIOS name to IP */
static BOOL wbinfo_wins_byname(char *name)
@@ -884,7 +915,8 @@ enum {
OPT_SET_AUTH_USER = 1000,
OPT_GET_AUTH_USER,
OPT_DOMAIN_NAME,
- OPT_SEQUENCE
+ OPT_SEQUENCE,
+ OPT_USERSIDS
};
int main(int argc, char **argv)
@@ -923,6 +955,7 @@ int main(int argc, char **argv)
{ "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" },
{ "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" },
{ "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" },
+ { "user-sids", 0, POPT_ARG_STRING, &string_arg, OPT_USERSIDS, "Get user group sids for user SID", "SID" },
{ "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a', "authenticate user", "user%password" },
{ "set-auth-user", 0, POPT_ARG_STRING, &string_arg, OPT_SET_AUTH_USER, "Store user and password used by winbindd (root only)", "user%password" },
{ "get-auth-user", 0, POPT_ARG_NONE, NULL, OPT_GET_AUTH_USER, "Retrieve user and password used by winbindd (root only)", NULL },
@@ -1055,6 +1088,13 @@ int main(int argc, char **argv)
goto done;
}
break;
+ case OPT_USERSIDS:
+ if (!wbinfo_get_usersids(string_arg)) {
+ d_printf("Could not get group SIDs for user SID %s\n",
+ string_arg);
+ goto done;
+ }
+ break;
case 'a': {
BOOL got_error = False;
diff --git a/source/nsswitch/winbind_nss_freebsd.c b/source/nsswitch/winbind_nss_freebsd.c
new file mode 100644
index 00000000000..b73a4ce44f8
--- /dev/null
+++ b/source/nsswitch/winbind_nss_freebsd.c
@@ -0,0 +1,81 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ AIX loadable authentication module, providing identification
+ routines against Samba winbind/Windows NT Domain
+
+ Copyright (C) Aaron Collins 2003
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "winbind_client.h"
+
+/* Make sure that the module gets registered needed by freebsd 5.1 */
+
+extern enum nss_status _nss_winbind_getgrent_r(struct group *, char *, size_t,
+ int *);
+extern enum nss_status _nss_winbind_getgrnam_r(const char *, struct group *,
+ char *, size_t, int *);
+extern enum nss_status _nss_winbind_getgrgid_r(gid_t gid, struct group *, char *,
+ size_t, int *);
+extern enum nss_status _nss_winbind_setgrent(void);
+extern enum nss_status _nss_winbind_endgrent(void);
+
+extern enum nss_status _nss_winbind_getpwent_r(struct passwd *, char *, size_t,
+ int *);
+extern enum nss_status _nss_winbind_getpwnam_r(const char *, struct passwd *,
+ char *, size_t, int *);
+extern enum nss_status _nss_winbind_getpwuid_r(gid_t gid, struct passwd *, char *,
+ size_t, int *);
+extern enum nss_status _nss_winbind_setpwent(void);
+extern enum nss_status _nss_winbind_endpwent(void);
+
+NSS_METHOD_PROTOTYPE(__nss_compat_getgrnam_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_getgrgid_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_getgrent_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_setgrent);
+NSS_METHOD_PROTOTYPE(__nss_compat_endgrent);
+
+NSS_METHOD_PROTOTYPE(__nss_compat_getpwnam_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_getpwuid_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_getpwent_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_setpwent);
+NSS_METHOD_PROTOTYPE(__nss_compat_endpwent);
+
+static ns_mtab methods[] = {
+{ NSDB_GROUP, "getgrnam_r", __nss_compat_getgrnam_r, _nss_winbind_getgrnam_r },
+{ NSDB_GROUP, "getgrgid_r", __nss_compat_getgrgid_r, _nss_winbind_getgrgid_r },
+{ NSDB_GROUP, "getgrent_r", __nss_compat_getgrent_r, _nss_winbind_getgrent_r },
+{ NSDB_GROUP, "endgrent", __nss_compat_setgrent, _nss_winbind_setgrent },
+{ NSDB_GROUP, "setgrent", __nss_compat_endgrent, _nss_winbind_endgrent },
+
+{ NSDB_PASSWD, "getpwnam_r", __nss_compat_getpwnam_r, _nss_winbind_getpwnam_r },
+{ NSDB_PASSWD, "getpwuid_r", __nss_compat_getpwuid_r, _nss_winbind_getpwuid_r },
+{ NSDB_PASSWD, "getpwent_r", __nss_compat_getpwent_r, _nss_winbind_getpwent_r },
+{ NSDB_PASSWD, "endpwent", __nss_compat_setpwent, _nss_winbind_setpwent },
+{ NSDB_PASSWD, "setpwent", __nss_compat_endpwent, _nss_winbind_endpwent },
+
+};
+
+ns_mtab *
+nss_module_register(const char *source, unsigned int *mtabsize,
+ nss_module_unregister_fn *unreg)
+{
+ *mtabsize = sizeof(methods)/sizeof(methods[0]);
+ *unreg = NULL;
+ return (methods);
+}
diff --git a/source/nsswitch/winbind_nss_linux.c b/source/nsswitch/winbind_nss_linux.c
index 125bc8ccdaf..ac4a861ff1b 100644
--- a/source/nsswitch/winbind_nss_linux.c
+++ b/source/nsswitch/winbind_nss_linux.c
@@ -860,3 +860,152 @@ _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start,
done:
return ret;
}
+
+
+/* return a list of group SIDs for a user SID */
+NSS_STATUS
+_nss_winbind_getusersids(const char *user_sid, char **group_sids,
+ int *num_groups,
+ char *buffer, size_t buf_size, int *errnop)
+{
+ NSS_STATUS ret;
+ struct winbindd_request request;
+ struct winbindd_response response;
+
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: getusersids %s\n", getpid(), user_sid);
+#endif
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ strncpy(request.data.sid, user_sid,sizeof(request.data.sid) - 1);
+ request.data.sid[sizeof(request.data.sid) - 1] = '\0';
+
+ ret = winbindd_request(WINBINDD_GETUSERSIDS, &request, &response);
+
+ if (ret != NSS_STATUS_SUCCESS) {
+ goto done;
+ }
+
+ if (buf_size < response.length - sizeof(response)) {
+ ret = NSS_STATUS_TRYAGAIN;
+ errno = *errnop = ERANGE;
+ goto done;
+ }
+
+ *num_groups = response.data.num_entries;
+ *group_sids = buffer;
+ memcpy(buffer, response.extra_data, response.length - sizeof(response));
+ errno = *errnop = 0;
+
+ done:
+ free_response(&response);
+ return ret;
+}
+
+
+/* map a user or group name to a SID string */
+NSS_STATUS
+_nss_winbind_nametosid(const char *name, char **sid, char *buffer,
+ size_t buflen, int *errnop)
+{
+ NSS_STATUS ret;
+ struct winbindd_response response;
+ struct winbindd_request request;
+
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: nametosid %s\n", getpid(), name);
+#endif
+
+ ZERO_STRUCT(response);
+ ZERO_STRUCT(request);
+
+ strncpy(request.data.name.name, name,
+ sizeof(request.data.name.name) - 1);
+ request.data.name.name[sizeof(request.data.name.name) - 1] = '\0';
+
+ ret = winbindd_request(WINBINDD_LOOKUPNAME, &request, &response);
+ if (ret != NSS_STATUS_SUCCESS) {
+ *errnop = errno = EINVAL;
+ goto failed;
+ }
+
+ if (buflen < strlen(response.data.sid.sid)+1) {
+ ret = NSS_STATUS_TRYAGAIN;
+ *errnop = errno = ERANGE;
+ goto failed;
+ }
+
+ *errnop = errno = 0;
+ *sid = buffer;
+ strcpy(*sid, response.data.sid.sid);
+
+failed:
+ free_response(&response);
+ return ret;
+}
+
+/* map a sid string to a user or group name */
+NSS_STATUS
+_nss_winbind_sidtoname(const char *sid, char **name, char *buffer,
+ size_t buflen, int *errnop)
+{
+ NSS_STATUS ret;
+ struct winbindd_response response;
+ struct winbindd_request request;
+ static char sep_char;
+ unsigned needed;
+
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: sidtoname %s\n", getpid(), sid);
+#endif
+
+ /* we need to fetch the separator first time through */
+ if (!sep_char) {
+ ZERO_STRUCT(response);
+ ZERO_STRUCT(request);
+
+ ret = winbindd_request(WINBINDD_INFO, &request, &response);
+ if (ret != NSS_STATUS_SUCCESS) {
+ *errnop = errno = EINVAL;
+ goto failed;
+ }
+
+ sep_char = response.data.info.winbind_separator;
+ free_response(&response);
+ }
+
+
+ strncpy(request.data.sid, sid,
+ sizeof(request.data.sid) - 1);
+ request.data.sid[sizeof(request.data.sid) - 1] = '\0';
+
+ ret = winbindd_request(WINBINDD_LOOKUPSID, &request, &response);
+ if (ret != NSS_STATUS_SUCCESS) {
+ *errnop = errno = EINVAL;
+ goto failed;
+ }
+
+ needed =
+ strlen(response.data.name.dom_name) +
+ strlen(response.data.name.name) + 2;
+
+ if (buflen < needed) {
+ ret = NSS_STATUS_TRYAGAIN;
+ *errnop = errno = ERANGE;
+ goto failed;
+ }
+
+ snprintf(buffer, needed, "%s%c%s",
+ response.data.name.dom_name,
+ sep_char,
+ response.data.name.name);
+
+ *name = buffer;
+ *errnop = errno = 0;
+
+failed:
+ free_response(&response);
+ return ret;
+}
diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c
index d8e233a3a8c..74df934ca2e 100644
--- a/source/nsswitch/winbindd.c
+++ b/source/nsswitch/winbindd.c
@@ -221,6 +221,7 @@ static struct dispatch_table dispatch_table[] = {
{ WINBINDD_GETPWENT, winbindd_getpwent, "GETPWENT" },
{ WINBINDD_GETGROUPS, winbindd_getgroups, "GETGROUPS" },
+ { WINBINDD_GETUSERSIDS, winbindd_getusersids, "GETUSERSIDS" },
/* Group functions */
@@ -722,6 +723,7 @@ static void process_loop(void)
&& *(uint32 *) &state->request != sizeof(state->request)) {
DEBUG(0,("process_loop: Invalid request size from pid %lu: %d bytes sent, should be %ld\n",
(unsigned long)state->request.pid, *(uint32 *) &state->request, (unsigned long)sizeof(state->request)));
+ DEBUGADD(0, ("This usually means that you are running old wbinfo, pam_winbind or libnss_winbind clients\n"));
remove_client(state);
break;
diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c
index 4bf5a304590..ac9cd8f3329 100644
--- a/source/nsswitch/winbindd_cm.c
+++ b/source/nsswitch/winbindd_cm.c
@@ -179,10 +179,9 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
result = NT_STATUS_OK;
- if (!cli_session_setup_spnego(new_conn->cli, machine_krb5_principal,
+ if (!NT_STATUS_IS_OK(result = cli_session_setup_spnego(new_conn->cli, machine_krb5_principal,
machine_password,
- domain)) {
- result = cli_nt_error(new_conn->cli);
+ domain))) {
DEBUG(4,("failed kerberos session setup with %s\n", nt_errstr(result)));
if (NT_STATUS_IS_OK(result))
result = NT_STATUS_UNSUCCESSFUL;
diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c
index d951b3433e5..180a3db8e2e 100644
--- a/source/nsswitch/winbindd_group.c
+++ b/source/nsswitch/winbindd_group.c
@@ -692,8 +692,8 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
goto tryagain;
}
- DEBUG(10, ("got gid %lu for group %x\n", (unsigned long)group_gid,
- name_list[ent->sam_entry_index].rid));
+ DEBUG(10, ("got gid %lu for group %lu\n", (unsigned long)group_gid,
+ (unsigned long)name_list[ent->sam_entry_index].rid));
/* Fill in group entry */
@@ -1082,3 +1082,88 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
return result;
}
+
+
+/* Get user supplementary sids. This is equivalent to the
+ winbindd_getgroups() function but it involves a SID->SIDs mapping
+ rather than a NAME->SID->SIDS->GIDS mapping, which means we avoid
+ idmap. This call is designed to be used with applications that need
+ to do ACL evaluation themselves. Note that the cached info3 data is
+ not used
+
+ this function assumes that the SID that comes in is a user SID. If
+ you pass in another type of SID then you may get unpredictable
+ results.
+*/
+enum winbindd_result winbindd_getusersids(struct winbindd_cli_state *state)
+{
+ DOM_SID user_sid;
+ NTSTATUS status;
+ DOM_SID **user_grpsids;
+ struct winbindd_domain *domain;
+ enum winbindd_result result = WINBINDD_ERROR;
+ unsigned int i;
+ TALLOC_CTX *mem_ctx;
+ char *ret;
+ uint32 num_groups;
+ unsigned ofs, ret_size = 0;
+
+ /* Ensure null termination */
+ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
+
+ if (!string_to_sid(&user_sid, state->request.data.sid)) {
+ DEBUG(1, ("Could not get convert sid %s from string\n", state->request.data.sid));
+ return WINBINDD_ERROR;
+ }
+
+ if (!(mem_ctx = talloc_init("winbindd_getusersids(%s)",
+ state->request.data.username))) {
+ return WINBINDD_ERROR;
+ }
+
+ /* Get info for the domain */
+ if ((domain = find_domain_from_sid(&user_sid)) == NULL) {
+ DEBUG(0,("could not find domain entry for sid %s\n",
+ sid_string_static(&user_sid)));
+ goto done;
+ }
+
+ status = domain->methods->lookup_usergroups(domain, mem_ctx,
+ &user_sid, &num_groups,
+ &user_grpsids);
+ if (!NT_STATUS_IS_OK(status))
+ goto done;
+
+ if (num_groups == 0) {
+ goto no_groups;
+ }
+
+ /* work out the response size */
+ for (i = 0; i < num_groups; i++) {
+ const char *s = sid_string_static(user_grpsids[i]);
+ ret_size += strlen(s) + 1;
+ }
+
+ /* build the reply */
+ ret = malloc(ret_size);
+ if (!ret) goto done;
+ ofs = 0;
+ for (i = 0; i < num_groups; i++) {
+ const char *s = sid_string_static(user_grpsids[i]);
+ safe_strcpy(ret + ofs, s, ret_size - ofs);
+ ofs += strlen(ret+ofs) + 1;
+ }
+
+no_groups:
+ /* Send data back to client */
+ state->response.data.num_entries = num_groups;
+ state->response.extra_data = ret;
+ state->response.length += ret_size;
+ result = WINBINDD_OK;
+
+ done:
+ talloc_destroy(mem_ctx);
+
+ return result;
+}
+
diff --git a/source/nsswitch/winbindd_nss.h b/source/nsswitch/winbindd_nss.h
index 41fecd2816c..76243c57ef3 100644
--- a/source/nsswitch/winbindd_nss.h
+++ b/source/nsswitch/winbindd_nss.h
@@ -118,6 +118,9 @@ enum winbindd_cmd {
/* find the location of our privileged pipe */
WINBINDD_PRIV_PIPE_DIR,
+ /* return a list of group sids for a user sid */
+ WINBINDD_GETUSERSIDS,
+
WINBINDD_NUM_CMDS
};
diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c
index d43dca29c54..6e386760b42 100644
--- a/source/nsswitch/winbindd_pam.c
+++ b/source/nsswitch/winbindd_pam.c
@@ -225,9 +225,15 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
DATA_BLOB lm_resp, nt_resp;
if (!state->privileged) {
- DEBUG(2, ("winbindd_pam_auth_crap: non-privileged access denied!\n"));
+ char *error_string = NULL;
+ DEBUG(2, ("winbindd_pam_auth_crap: non-privileged access denied. !\n"));
+ DEBUGADD(2, ("winbindd_pam_auth_crap: Ensure permissions on %s are set correctly.\n",
+ get_winbind_priv_pipe_dir()));
/* send a better message than ACCESS_DENIED */
- push_utf8_fstring(state->response.data.auth.error_string, "winbind client not authorized to use winbindd_pam_auth_crap");
+ asprintf(&error_string, "winbind client not authorized to use winbindd_pam_auth_crap. Ensure permissions on %s are set correctly.",
+ get_winbind_priv_pipe_dir());
+ push_utf8_fstring(state->response.data.auth.error_string, error_string);
+ SAFE_FREE(error_string);
result = NT_STATUS_ACCESS_DENIED;
goto done;
}
@@ -378,6 +384,8 @@ done:
state->response.data.auth.nt_status = NT_STATUS_V(result);
push_utf8_fstring(state->response.data.auth.nt_status_string, nt_errstr(result));
+
+ /* we might have given a more useful error above */
if (!*state->response.data.auth.error_string)
push_utf8_fstring(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
state->response.data.auth.pam_error = nt_status_to_pam(result);
diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c
index c6711a9ccfa..e05d46a936e 100644
--- a/source/nsswitch/winbindd_rpc.c
+++ b/source/nsswitch/winbindd_rpc.c
@@ -42,6 +42,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
BOOL got_dom_pol = False;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
unsigned int i, start_idx, retry;
+ uint32 loop_count;
DEBUG(3,("rpc: query_user_list\n"));
@@ -68,25 +69,36 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
got_dom_pol = True;
i = start_idx = 0;
+ loop_count = 0;
+
do {
TALLOC_CTX *ctx2;
- char **dom_users;
- uint32 num_dom_users, *dom_rids, j, size = 0xffff;
- uint16 acb_mask = ACB_NORMAL;
-
+ uint32 num_dom_users, j;
+ uint32 max_entries, max_size;
+ SAM_DISPINFO_CTR ctr;
+ SAM_DISPINFO_1 info1;
+
+ ZERO_STRUCT( ctr );
+ ZERO_STRUCT( info1 );
+ ctr.sam.info1 = &info1;
+
if (!(ctx2 = talloc_init("winbindd enum_users"))) {
result = NT_STATUS_NO_MEMORY;
goto done;
}
- result = cli_samr_enum_dom_users(
- hnd->cli, ctx2, &dom_pol, &start_idx, acb_mask,
- size, &dom_users, &dom_rids, &num_dom_users);
+ /* this next bit is copied from net_user_list_internal() */
+
+ get_query_dispinfo_params( loop_count, &max_entries, &max_size );
+
+ result = cli_samr_query_dispinfo(hnd->cli, mem_ctx, &dom_pol,
+ &start_idx, 1, &num_dom_users, max_entries, max_size, &ctr);
+
+ loop_count++;
*num_entries += num_dom_users;
- *info = talloc_realloc(
- mem_ctx, *info,
+ *info = talloc_realloc( mem_ctx, *info,
(*num_entries) * sizeof(WINBIND_USERINFO));
if (!(*info)) {
@@ -96,10 +108,16 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
}
for (j = 0; j < num_dom_users; i++, j++) {
- (*info)[i].acct_name =
- talloc_strdup(mem_ctx, dom_users[j]);
- (*info)[i].full_name = talloc_strdup(mem_ctx, "");
- (*info)[i].user_sid = rid_to_talloced_sid(domain, mem_ctx, dom_rids[j]);
+ fstring username, fullname;
+ uint32 rid = ctr.sam.info1->sam[j].rid_user;
+
+ unistr2_to_ascii( username, &(&ctr.sam.info1->str[j])->uni_acct_name, sizeof(username)-1);
+ unistr2_to_ascii( fullname, &(&ctr.sam.info1->str[j])->uni_full_name, sizeof(fullname)-1);
+
+ (*info)[i].acct_name = talloc_strdup(mem_ctx, username );
+ (*info)[i].full_name = talloc_strdup(mem_ctx, fullname );
+ (*info)[i].user_sid = rid_to_talloced_sid(domain, mem_ctx, rid );
+
/* For the moment we set the primary group for
every user to be the Domain Users group.
There are serious problems with determining
@@ -107,10 +125,9 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
This should really be made into a 'winbind
force group' smb.conf parameter or
something like that. */
- (*info)[i].group_sid
- = rid_to_talloced_sid(domain,
- mem_ctx,
- DOMAIN_GROUP_RID_USERS);
+
+ (*info)[i].group_sid = rid_to_talloced_sid(domain,
+ mem_ctx, DOMAIN_GROUP_RID_USERS);
}
talloc_destroy(ctx2);
diff --git a/source/nsswitch/winbindd_sid.c b/source/nsswitch/winbindd_sid.c
index 6400a23b7bf..7c4c8d804a8 100644
--- a/source/nsswitch/winbindd_sid.c
+++ b/source/nsswitch/winbindd_sid.c
@@ -84,6 +84,7 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state)
char *name_domain, *name_user;
DOM_SID sid;
struct winbindd_domain *domain;
+ char *p;
/* Ensure null termination */
state->request.data.sid[sizeof(state->request.data.name.dom_name)-1]='\0';
@@ -91,13 +92,19 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state)
/* Ensure null termination */
state->request.data.sid[sizeof(state->request.data.name.name)-1]='\0';
- DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
- state->request.data.name.dom_name,
- lp_winbind_separator(),
- state->request.data.name.name));
+ /* cope with the name being a fully qualified name */
+ p = strstr(state->request.data.name.name, lp_winbind_separator());
+ if (p) {
+ *p = 0;
+ name_domain = state->request.data.name.name;
+ name_user = p+1;
+ } else {
+ name_domain = state->request.data.name.dom_name;
+ name_user = state->request.data.name.name;
+ }
- name_domain = state->request.data.name.dom_name;
- name_user = state->request.data.name.name;
+ DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
+ name_domain, lp_winbind_separator(), name_user));
if ((domain = find_domain_from_name(name_domain)) == NULL) {
DEBUG(0, ("could not find domain entry for domain %s\n",
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index e1308da3aa6..f54c97fc1bb 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -262,6 +262,7 @@ typedef struct
BOOL bPamPasswordChange;
BOOL bUnixPasswdSync;
BOOL bPasswdChatDebug;
+ int iPasswdChatTimeout;
BOOL bTimestampLogs;
BOOL bNTSmbSupport;
BOOL bNTPipeSupport;
@@ -280,7 +281,6 @@ typedef struct
BOOL bDebugPid;
BOOL bDebugUid;
BOOL bHostMSDfs;
- BOOL bHideLocalUsers;
BOOL bUnicode;
BOOL bUseMmap;
BOOL bHostnameLookups;
@@ -565,9 +565,6 @@ static BOOL handle_netbios_aliases( const char *pszParmValue, char **ptr );
static BOOL handle_netbios_scope( const char *pszParmValue, char **ptr );
static BOOL handle_charset( const char *pszParmValue, char **ptr );
-static BOOL handle_ldap_suffix ( const char *pszParmValue, char **ptr );
-static BOOL handle_ldap_sub_suffix ( const char *pszParmValue, char **ptr );
-
static BOOL handle_acl_compatibility(const char *pszParmValue, char **ptr);
static void set_server_role(void);
@@ -749,6 +746,12 @@ static const struct enum_list enum_map_to_guest[] = {
* Any parameter that does NOT have FLAG_ADVANCED will not disply at all
* Set FLAG_SHARE and FLAG_PRINT to specifically display parameters in
* respective views.
+ *
+ * NOTE2: Handling of duplicated (synonym) paramters:
+ * Only the first occurance of a parameter should be enabled by FLAG_BASIC
+ * and/or FLAG_ADVANCED. All duplicates following the first mention should be
+ * set to FLAG_HIDE. ie: Make you must place the parameter that has the preferred
+ * name first, and all synonyms must follow it with the FLAG_HIDE attribute.
*/
static struct parm_struct parm_table[] = {
@@ -801,6 +804,7 @@ static struct parm_struct parm_table[] = {
{"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL, NULL, FLAG_ADVANCED},
{"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED},
{"passwd chat debug", P_BOOL, P_GLOBAL, &Globals.bPasswdChatDebug, NULL, NULL, FLAG_ADVANCED},
+ {"passwd chat timeout", P_INTEGER, P_GLOBAL, &Globals.iPasswdChatTimeout, NULL, NULL, FLAG_ADVANCED},
{"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL, NULL, FLAG_ADVANCED},
{"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED},
{"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, FLAG_ADVANCED},
@@ -1064,11 +1068,11 @@ static struct parm_struct parm_table[] = {
{"ldap server", P_STRING, P_GLOBAL, &Globals.szLdapServer, NULL, NULL, FLAG_ADVANCED},
{"ldap port", P_INTEGER, P_GLOBAL, &Globals.ldap_port, NULL, NULL, FLAG_ADVANCED},
#endif
- {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, handle_ldap_suffix, NULL, FLAG_ADVANCED},
- {"ldap machine suffix", P_STRING, P_GLOBAL, &Globals.szLdapMachineSuffix, handle_ldap_sub_suffix, NULL, FLAG_ADVANCED},
- {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, handle_ldap_sub_suffix, NULL, FLAG_ADVANCED},
- {"ldap group suffix", P_STRING, P_GLOBAL, &Globals.szLdapGroupSuffix, handle_ldap_sub_suffix, NULL, FLAG_ADVANCED},
- {"ldap idmap suffix", P_STRING, P_GLOBAL, &Globals.szLdapIdmapSuffix, handle_ldap_sub_suffix, NULL, FLAG_ADVANCED},
+ {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, NULL, NULL, FLAG_ADVANCED},
+ {"ldap machine suffix", P_STRING, P_GLOBAL, &Globals.szLdapMachineSuffix, NULL, NULL, FLAG_ADVANCED},
+ {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, NULL, NULL, FLAG_ADVANCED},
+ {"ldap group suffix", P_STRING, P_GLOBAL, &Globals.szLdapGroupSuffix, NULL, NULL, FLAG_ADVANCED},
+ {"ldap idmap suffix", P_STRING, P_GLOBAL, &Globals.szLdapIdmapSuffix, NULL, NULL, FLAG_ADVANCED},
{"ldap filter", P_STRING, P_GLOBAL, &Globals.szLdapFilter, NULL, NULL, FLAG_ADVANCED},
{"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, FLAG_ADVANCED},
{"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, FLAG_ADVANCED},
@@ -1133,7 +1137,6 @@ static struct parm_struct parm_table[] = {
{"fake directory create times", P_BOOL, P_LOCAL, &sDefault.bFakeDirCreateTimes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED},
- {"hide local users", P_BOOL, P_GLOBAL, &Globals.bHideLocalUsers, NULL, NULL, FLAG_ADVANCED},
{N_("VFS module options"), P_SEP, P_SEPARATOR},
@@ -1150,9 +1153,9 @@ static struct parm_struct parm_table[] = {
{"enable rid algorithm", P_BOOL, P_GLOBAL, &Globals.bEnableRidAlgorithm, NULL, NULL, FLAG_DEPRECATED},
{"idmap backend", P_STRING, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED},
{"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED},
- {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED},
+ {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_HIDE},
{"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED},
- {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED},
+ {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_HIDE},
{"template primary group", P_STRING, P_GLOBAL, &Globals.szTemplatePrimaryGroup, NULL, NULL, FLAG_ADVANCED},
{"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED},
{"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED},
@@ -1417,6 +1420,7 @@ static void init_globals(void)
Globals.bUnixPasswdSync = False;
Globals.bPamPasswordChange = False;
Globals.bPasswdChatDebug = False;
+ Globals.iPasswdChatTimeout = 2; /* 2 second default. */
Globals.bUnicode = True; /* Do unicode on the wire by default */
Globals.bNTPipeSupport = True; /* Do NT pipes by default. */
Globals.bNTStatusSupport = True; /* Use NT status by default. */
@@ -1689,10 +1693,6 @@ FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer)
FN_GLOBAL_INTEGER(lp_ldap_port, &Globals.ldap_port)
#endif
FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
-FN_GLOBAL_STRING(lp_ldap_machine_suffix, &Globals.szLdapMachineSuffix)
-FN_GLOBAL_STRING(lp_ldap_user_suffix, &Globals.szLdapUserSuffix)
-FN_GLOBAL_STRING(lp_ldap_idmap_suffix, &Globals.szLdapIdmapSuffix)
-FN_GLOBAL_STRING(lp_ldap_group_suffix, &Globals.szLdapGroupSuffix)
FN_GLOBAL_STRING(lp_ldap_filter, &Globals.szLdapFilter)
FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
@@ -1734,6 +1734,7 @@ FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
FN_GLOBAL_BOOL(lp_pam_password_change, &Globals.bPamPasswordChange)
FN_GLOBAL_BOOL(lp_unix_password_sync, &Globals.bUnixPasswdSync)
FN_GLOBAL_BOOL(lp_passwd_chat_debug, &Globals.bPasswdChatDebug)
+FN_GLOBAL_INTEGER(lp_passwd_chat_timeout, &Globals.iPasswdChatTimeout)
FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
FN_GLOBAL_BOOL(lp_nt_pipe_support, &Globals.bNTPipeSupport)
FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
@@ -1894,7 +1895,6 @@ FN_LOCAL_INTEGER(lp_write_cache_size, iWriteCacheSize)
FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
FN_LOCAL_CHAR(lp_magicchar, magic_char)
FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
-FN_GLOBAL_BOOL(lp_hide_local_users, &Globals.bHideLocalUsers)
FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
@@ -2992,56 +2992,56 @@ static BOOL handle_debug_list( const char *pszParmValueIn, char **ptr )
}
/***************************************************************************
- Handle setting ldap suffix and determines whether ldap machine suffix needs
- to be set as well.
-
- Set all of the sub suffix strings to be the 'ldap suffix' by default
+ Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
***************************************************************************/
-static BOOL handle_ldap_suffix( const char *pszParmValue, char **ptr )
+static char* append_ldap_suffix( const char *str )
{
- pstring suffix;
-
- pstrcpy(suffix, pszParmValue);
+ char *suffix_string;
- /* set defaults for the the sub-suffixes */
-
- if (! *Globals.szLdapMachineSuffix )
- string_set(&Globals.szLdapMachineSuffix, suffix);
- if (! *Globals.szLdapUserSuffix )
- string_set(&Globals.szLdapUserSuffix, suffix);
- if (! *Globals.szLdapGroupSuffix )
- string_set(&Globals.szLdapGroupSuffix, suffix);
- if (! *Globals.szLdapIdmapSuffix )
- string_set(&Globals.szLdapIdmapSuffix, suffix);
-
- string_set(ptr, suffix);
- return True;
+
+ if (!lp_talloc)
+ lp_talloc = talloc_init("lp_talloc");
+
+ suffix_string = talloc_asprintf( lp_talloc, "%s,%s", str, Globals.szLdapSuffix );
+ if ( !suffix_string ) {
+ DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
+ return NULL;
+ }
+
+ return suffix_string;
}
-/***************************************************************************
- Handle the ldap sub suffix option.
- Always append the 'ldap suffix' if it is set
-***************************************************************************/
+char *lp_ldap_machine_suffix(void)
+{
+ if (Globals.szLdapMachineSuffix[0])
+ return append_ldap_suffix(Globals.szLdapMachineSuffix);
+
+ return lp_string(Globals.szLdapSuffix);
+}
-static BOOL handle_ldap_sub_suffix( const char *pszParmValue, char **ptr)
+char *lp_ldap_user_suffix(void)
{
- pstring suffix;
-
- pstrcpy(suffix, pszParmValue);
+ if (Globals.szLdapUserSuffix[0])
+ return append_ldap_suffix(Globals.szLdapUserSuffix);
- if (! *Globals.szLdapSuffix ) {
- string_set( ptr, suffix );
- return True;
- }
- else {
- if ( *pszParmValue )
- pstrcat(suffix, ",");
- pstrcat(suffix, Globals.szLdapSuffix);
- }
-
- string_set( ptr, suffix );
- return True;
+ return lp_string(Globals.szLdapSuffix);
+}
+
+char *lp_ldap_group_suffix(void)
+{
+ if (Globals.szLdapGroupSuffix[0])
+ return append_ldap_suffix(Globals.szLdapGroupSuffix);
+
+ return lp_string(Globals.szLdapSuffix);
+}
+
+char *lp_ldap_idmap_suffix(void)
+{
+ if (Globals.szLdapIdmapSuffix[0])
+ return append_ldap_suffix(Globals.szLdapIdmapSuffix);
+
+ return lp_string(Globals.szLdapSuffix);
}
/***************************************************************************
@@ -3311,9 +3311,13 @@ static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
if ((char ***)ptr && *(char ***)ptr) {
char **list = *(char ***)ptr;
- for (; *list; list++)
- fprintf(f, "%s%s", *list,
- ((*(list+1))?", ":""));
+ for (; *list; list++) {
+ /* surround strings with whitespace in single quotes */
+ if ( strchr_m( *list, ' ' ) )
+ fprintf(f, "\'%s\'%s", *list, ((*(list+1))?", ":""));
+ else
+ fprintf(f, "%s%s", *list, ((*(list+1))?", ":""));
+ }
}
break;
diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c
index 9d8f600eeac..6246cdaee13 100644
--- a/source/passdb/passdb.c
+++ b/source/passdb/passdb.c
@@ -416,6 +416,7 @@ NTSTATUS pdb_set_sam_sids(SAM_ACCOUNT *account_data, const struct passwd *pwd)
{
const char *guest_account = lp_guestaccount();
GROUP_MAP map;
+ BOOL ret;
if (!account_data || !pwd) {
return NT_STATUS_INVALID_PARAMETER;
@@ -445,7 +446,11 @@ NTSTATUS pdb_set_sam_sids(SAM_ACCOUNT *account_data, const struct passwd *pwd)
}
/* call the mapping code here */
- if(pdb_getgrgid(&map, pwd->pw_gid)) {
+ become_root();
+ ret = pdb_getgrgid(&map, pwd->pw_gid);
+ unbecome_root();
+
+ if( ret ) {
if (!pdb_set_group_sid(account_data, &map.sid, PDB_SET)){
DEBUG(0,("Can't set Group SID!\n"));
return NT_STATUS_INVALID_PARAMETER;
@@ -725,14 +730,6 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use
return True;
}
- /*
- * Don't try to convert the rid to a name if
- * running in appliance mode
- */
-
- if (lp_hide_local_users())
- return False;
-
if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
return False;
}
@@ -852,18 +849,14 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi
return True;
}
- /*
- * Don't lookup local unix users if running in appliance mode
- */
- if (lp_hide_local_users())
- return False;
-
(void)map_username(user);
if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
return False;
}
+ /* BEGIN ROOT BLOCK */
+
become_root();
if (pdb_getsampwnam(sam_account, user)) {
unbecome_root();
@@ -873,7 +866,6 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi
pdb_free_sam(&sam_account);
return True;
}
- unbecome_root();
pdb_free_sam(&sam_account);
@@ -889,8 +881,10 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi
} else {
/* it's not a mapped group */
grp = getgrnam(user);
- if(!grp)
+ if(!grp) {
+ unbecome_root(); /* ---> exit form block */
return False;
+ }
/*
*check if it's mapped, if it is reply it doesn't exist
@@ -905,12 +899,15 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi
*/
if (pdb_getgrgid(&map, grp->gr_gid)){
+ unbecome_root(); /* ---> exit form block */
return False;
}
sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid));
*psid_name_use = SID_NAME_ALIAS;
}
+ unbecome_root();
+ /* END ROOT BLOCK */
sid_copy( psid, &local_sid);
diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c
index 023e9f3fe0b..4d7c7791bd6 100644
--- a/source/passdb/pdb_ldap.c
+++ b/source/passdb/pdb_ldap.c
@@ -415,8 +415,8 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
logon_script,
profile_path,
acct_desc,
- munged_dial,
workstations;
+ char munged_dial[2048];
uint32 user_rid;
uint8 smblmpwd[LM_HASH_LEN],
smbntpwd[NT_HASH_LEN];
@@ -660,6 +660,13 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
pdb_set_workstations(sampass, workstations, PDB_SET);
}
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_MUNGED_DIAL), munged_dial)) {
+ /* leave as default */;
+ } else {
+ pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
+ }
+
/* FIXME: hours stuff should be cleaner */
logon_divs = 168;
@@ -703,7 +710,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
pdb_set_hours_len(sampass, hours_len, PDB_SET);
pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
- pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
+/* pdb_set_munged_dial(sampass, munged_dial, PDB_SET); */
/* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
@@ -851,7 +858,12 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS),
pdb_get_workstations(sampass));
-
+
+ if (need_update(sampass, PDB_MUNGEDDIAL))
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
+ get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_MUNGED_DIAL),
+ pdb_get_munged_dial(sampass));
+
if (need_update(sampass, PDB_SMBHOME))
smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH),
diff --git a/source/passdb/util_sam_sid.c b/source/passdb/util_sam_sid.c
index 6a7675a12aa..6e9ccecc9e8 100644
--- a/source/passdb/util_sam_sid.c
+++ b/source/passdb/util_sam_sid.c
@@ -76,6 +76,8 @@ static const known_sid_users builtin_groups[] = {
{ BUILTIN_ALIAS_RID_SYSTEM_OPS, SID_NAME_ALIAS, "Server Operators" },
{ BUILTIN_ALIAS_RID_PRINT_OPS, SID_NAME_ALIAS, "Print Operators" },
{ BUILTIN_ALIAS_RID_BACKUP_OPS, SID_NAME_ALIAS, "Backup Operators" },
+ { BUILTIN_ALIAS_RID_REPLICATOR, SID_NAME_ALIAS, "Replicator" },
+ { BUILTIN_ALIAS_RID_RAS_SERVERS, SID_NAME_ALIAS, "RAS Servers" },
{ 0, (enum SID_NAME_USE)0, NULL}};
/**************************************************************************
@@ -290,7 +292,7 @@ BOOL map_name_to_wellknown_sid(DOM_SID *sid, enum SID_NAME_USE *use, const char
continue;
for (j=0; users[j].known_user_name != NULL; j++) {
- if (strequal(users[j].known_user_name, name) == 0) {
+ if ( strequal(users[j].known_user_name, name) ) {
sid_copy(sid, sid_name_map[i].sid);
sid_append_rid(sid, users[j].rid);
*use = users[j].sid_name_use;
diff --git a/source/printing/print_cups.c b/source/printing/print_cups.c
index 34eee7d97f7..f0096a17c2c 100644
--- a/source/printing/print_cups.c
+++ b/source/printing/print_cups.c
@@ -681,7 +681,8 @@ cups_job_submit(int snum, struct printjob *pjob)
*response; /* IPP Response */
cups_lang_t *language; /* Default language */
char uri[HTTP_MAX_URI]; /* printer-uri attribute */
-
+ char *clientname; /* hostname of client for job-originating-host attribute */
+ pstring new_jobname;
DEBUG(5,("cups_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
@@ -735,12 +736,20 @@ cups_job_submit(int snum, struct printjob *pjob)
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
NULL, pjob->user);
+ clientname = client_name();
+ if (strcmp(clientname, "UNKNOWN") == 0) {
+ clientname = client_addr();
+ }
+
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
"job-originating-host-name", NULL,
- get_remote_machine_name());
+ clientname);
+
+ pstr_sprintf(new_jobname,"%s%.8u %s", PRINT_SPOOL_PREFIX,
+ (unsigned int)pjob->smbjob, pjob->jobname);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
- pjob->jobname);
+ new_jobname);
/*
* Do the request and get back a response...
diff --git a/source/printing/printing.c b/source/printing/printing.c
index ad17213c2d6..bdcd9504505 100644
--- a/source/printing/printing.c
+++ b/source/printing/printing.c
@@ -613,12 +613,14 @@ static void print_unix_job(int snum, print_queue_struct *q, uint32 jobid)
pj.status = q->status;
pj.size = q->size;
pj.spooled = True;
- pj.smbjob = (old_pj != NULL ? True : False);
fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
- if (jobid < UNIX_JOB_START)
+ if (jobid < UNIX_JOB_START) {
+ pj.smbjob = (old_pj != NULL ? True : False);
fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
- else
+ } else {
+ pj.smbjob = False;
fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
+ }
fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
fstrcpy(pj.queuename, old_pj ? old_pj->queuename : lp_const_servicename(snum));
@@ -2063,6 +2065,8 @@ BOOL print_job_end(int snum, uint32 jobid, BOOL normal_close)
return True;
}
+ pjob->smbjob = jobid;
+
ret = (*(current_printif->job_submit))(snum, pjob);
if (ret)
diff --git a/source/rpc_client/cli_netlogon.c b/source/rpc_client/cli_netlogon.c
index 97bc4c65b76..70ac4603034 100644
--- a/source/rpc_client/cli_netlogon.c
+++ b/source/rpc_client/cli_netlogon.c
@@ -654,11 +654,17 @@ NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli, TALLOC_CTX *mem_c
ZERO_STRUCT(netlogon_sess_key);
memcpy(netlogon_sess_key, cli->sess_key, 8);
- if (memcmp(zeros, info3->user_sess_key, 16) != 0)
+ if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
SamOEMhash(info3->user_sess_key, netlogon_sess_key, 16);
-
- if (memcmp(zeros, info3->padding, 16) != 0)
+ } else {
+ memset(info3->user_sess_key, '\0', 16);
+ }
+
+ if (memcmp(zeros, info3->padding, 16) != 0) {
SamOEMhash(info3->padding, netlogon_sess_key, 16);
+ } else {
+ memset(info3->padding, '\0', 16);
+ }
/* Return results */
diff --git a/source/rpc_client/cli_pipe.c b/source/rpc_client/cli_pipe.c
index 9ce10202dbe..49abf787eed 100644
--- a/source/rpc_client/cli_pipe.c
+++ b/source/rpc_client/cli_pipe.c
@@ -264,13 +264,16 @@ static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata,
later use */
DATA_BLOB ntlmssp_verf = data_blob(NULL, auth_len);
-
+ BOOL store_ok;
+
/* save the reply away, for use a little later */
prs_copy_data_out((char *)ntlmssp_verf.data, &auth_verf, auth_len);
+ store_ok = (NT_STATUS_IS_OK(ntlmssp_store_response(cli->ntlmssp_pipe_state,
+ ntlmssp_verf)));
- return (NT_STATUS_IS_OK(ntlmssp_client_store_response(cli->ntlmssp_pipe_state,
- ntlmssp_verf)));
+ data_blob_free(&ntlmssp_verf);
+ return store_ok;
}
else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
/* nothing to do here - we don't seem to be able to
@@ -307,12 +310,12 @@ static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata,
DEBUG(1, ("Can't unseal - data_len < 0!!\n"));
return False;
}
- nt_status = ntlmssp_client_unseal_packet(cli->ntlmssp_pipe_state,
+ nt_status = ntlmssp_unseal_packet(cli->ntlmssp_pipe_state,
(unsigned char *)reply_data, data_len,
&sig);
}
else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
- nt_status = ntlmssp_client_check_packet(cli->ntlmssp_pipe_state,
+ nt_status = ntlmssp_check_packet(cli->ntlmssp_pipe_state,
(const unsigned char *)reply_data, data_len,
&sig);
}
@@ -674,9 +677,9 @@ static NTSTATUS create_rpc_bind_req(struct cli_state *cli, prs_struct *rpc_out,
DATA_BLOB request;
DEBUG(5, ("Processing NTLMSSP Negotiate\n"));
- nt_status = ntlmssp_client_update(cli->ntlmssp_pipe_state,
- null_blob,
- &request);
+ nt_status = ntlmssp_update(cli->ntlmssp_pipe_state,
+ null_blob,
+ &request);
if (!NT_STATUS_EQUAL(nt_status,
NT_STATUS_MORE_PROCESSING_REQUIRED)) {
@@ -777,9 +780,9 @@ static NTSTATUS create_rpc_bind_resp(struct cli_state *cli,
/* The response is picked up from the internal cache,
where it was placed by the rpc_auth_pipe() code */
- nt_status = ntlmssp_client_update(cli->ntlmssp_pipe_state,
- ntlmssp_null_response,
- &ntlmssp_reply);
+ nt_status = ntlmssp_update(cli->ntlmssp_pipe_state,
+ ntlmssp_null_response,
+ &ntlmssp_reply);
if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
return nt_status;
@@ -819,14 +822,6 @@ static NTSTATUS create_rpc_bind_resp(struct cli_state *cli,
return NT_STATUS_NO_MEMORY;
}
- if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
- nt_status = ntlmssp_client_sign_init(cli->ntlmssp_pipe_state);
-
- if (!NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
- }
- }
-
data_blob_free(&ntlmssp_reply);
return NT_STATUS_OK;
}
@@ -994,7 +989,7 @@ BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num,
*/
if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) {
- nt_status = ntlmssp_client_seal_packet(cli->ntlmssp_pipe_state,
+ nt_status = ntlmssp_seal_packet(cli->ntlmssp_pipe_state,
(unsigned char*)prs_data_p(&sec_blob),
data_and_padding_size,
&sign_blob);
@@ -1005,7 +1000,7 @@ BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num,
}
else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
- nt_status = ntlmssp_client_sign_packet(cli->ntlmssp_pipe_state,
+ nt_status = ntlmssp_sign_packet(cli->ntlmssp_pipe_state,
(unsigned char*)prs_data_p(&sec_blob),
data_and_padding_size, &sign_blob);
if (!NT_STATUS_IS_OK(nt_status)) {
@@ -1231,7 +1226,8 @@ static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFAC
if ( hdr_ba->addr.len <= 0)
return False;
- if ( !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].server_pipe ))
+ if ( !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].client_pipe) &&
+ !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].server_pipe) )
{
DEBUG(4,("bind_rpc_pipe: pipe_name %s != expected pipe %s. oh well!\n",
pipe_names[i].server_pipe ,hdr_ba->addr.str));
@@ -1332,6 +1328,10 @@ static BOOL rpc_pipe_bind(struct cli_state *cli, int pipe_idx, const char *my_na
if (!NT_STATUS_IS_OK(nt_status))
return False;
+ /* Currently the NTLMSSP code does not implement NTLM2 correctly for signing or sealing */
+
+ cli->ntlmssp_pipe_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
+
nt_status = ntlmssp_set_username(cli->ntlmssp_pipe_state,
cli->user_name);
if (!NT_STATUS_IS_OK(nt_status))
diff --git a/source/rpc_client/cli_samr.c b/source/rpc_client/cli_samr.c
index e5e67f39dc9..0eebcd0a6f5 100644
--- a/source/rpc_client/cli_samr.c
+++ b/source/rpc_client/cli_samr.c
@@ -1341,7 +1341,7 @@ NTSTATUS cli_samr_create_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx,
NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *user_pol, uint16 switch_value,
- uchar sess_key[16], SAM_USERINFO_CTR *ctr)
+ DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr)
{
prs_struct qbuf, rbuf;
SAMR_Q_SET_USERINFO q;
@@ -1353,6 +1353,11 @@ NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
ZERO_STRUCT(q);
ZERO_STRUCT(r);
+ if (!sess_key->length) {
+ DEBUG(1, ("No user session key\n"));
+ return NT_STATUS_NO_USER_SESSION_KEY;
+ }
+
/* Initialise parse structures */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
@@ -1393,7 +1398,7 @@ NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *user_pol, uint16 switch_value,
- uchar sess_key[16], SAM_USERINFO_CTR *ctr)
+ DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr)
{
prs_struct qbuf, rbuf;
SAMR_Q_SET_USERINFO2 q;
@@ -1402,6 +1407,11 @@ NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
DEBUG(10,("cli_samr_set_userinfo2\n"));
+ if (!sess_key->length) {
+ DEBUG(1, ("No user session key\n"));
+ return NT_STATUS_NO_USER_SESSION_KEY;
+ }
+
ZERO_STRUCT(q);
ZERO_STRUCT(r);
diff --git a/source/rpc_parse/parse_misc.c b/source/rpc_parse/parse_misc.c
index 203122e73c0..afdf0fc4c9b 100644
--- a/source/rpc_parse/parse_misc.c
+++ b/source/rpc_parse/parse_misc.c
@@ -1015,7 +1015,11 @@ void init_unistr2_from_datablob(UNISTR2 *str, DATA_BLOB *blob)
str->uni_str_len = blob->length / sizeof(uint16);
str->uni_max_len = str->uni_str_len;
str->offset = 0;
- str->buffer = (uint16 *) memdup(blob->data, blob->length);
+ if (blob->length) {
+ str->buffer = (uint16 *) memdup(blob->data, blob->length);
+ } else {
+ str->buffer = NULL;
+ }
if ((str->buffer == NULL) && (blob->length > 0)) {
smb_panic("init_unistr2_from_datablob: malloc fail\n");
}
diff --git a/source/rpc_parse/parse_net.c b/source/rpc_parse/parse_net.c
index 3b096e088ab..ad0a91e7ea5 100644
--- a/source/rpc_parse/parse_net.c
+++ b/source/rpc_parse/parse_net.c
@@ -1265,7 +1265,8 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
uint16 logon_count, uint16 bad_pw_count,
uint32 num_groups, const DOM_GID *gids,
- uint32 user_flgs, uchar sess_key[16],
+ uint32 user_flgs, uchar nt_session_key[16],
+ uchar lm_session_key[16],
const char *logon_srv, const char *logon_dom,
const DOM_SID *dom_sid, const char *other_sids)
{
@@ -1307,8 +1308,8 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
usr->buffer_groups = 1; /* indicates fill in groups, below, even if there are none */
usr->user_flgs = user_flgs;
- if (sess_key != NULL)
- memcpy(usr->user_sess_key, sess_key, sizeof(usr->user_sess_key));
+ if (nt_session_key != NULL)
+ memcpy(usr->user_sess_key, nt_session_key, sizeof(usr->user_sess_key));
else
memset((char *)usr->user_sess_key, '\0', sizeof(usr->user_sess_key));
@@ -1316,6 +1317,10 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
memset((char *)usr->padding, '\0', sizeof(usr->padding));
+ if (lm_session_key != NULL)
+ memcpy(usr->padding, lm_session_key, sizeof(usr->user_sess_key));
+
+
num_other_sids = init_dom_sid2s(ctx, other_sids, &usr->other_sids);
usr->num_other_sids = num_other_sids;
diff --git a/source/rpc_parse/parse_samr.c b/source/rpc_parse/parse_samr.c
index 73107f8f61e..607c9ecf640 100644
--- a/source/rpc_parse/parse_samr.c
+++ b/source/rpc_parse/parse_samr.c
@@ -181,9 +181,9 @@ BOOL samr_io_r_lookup_domain(const char *desc, SAMR_R_LOOKUP_DOMAIN * r_u,
reads or writes a structure.
********************************************************************/
-void init_samr_q_remove_user_foreign_domain(SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN * q_u, POLICY_HND *dom_pol, DOM_SID *sid)
+void init_samr_q_remove_sid_foreign_domain(SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN * q_u, POLICY_HND *dom_pol, DOM_SID *sid)
{
- DEBUG(5, ("samr_init_samr_q_remove_user_foreign_domain\n"));
+ DEBUG(5, ("samr_init_samr_q_remove_sid_foreign_domain\n"));
q_u->dom_pol = *dom_pol;
init_dom_sid2(&q_u->sid, sid);
@@ -193,13 +193,13 @@ void init_samr_q_remove_user_foreign_domain(SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN *
reads or writes a structure.
********************************************************************/
-BOOL samr_io_q_remove_user_foreign_domain(const char *desc, SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN * q_u,
+BOOL samr_io_q_remove_sid_foreign_domain(const char *desc, SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN * q_u,
prs_struct *ps, int depth)
{
if (q_u == NULL)
return False;
- prs_debug(ps, depth, desc, "samr_io_q_remove_user_foreign_domain");
+ prs_debug(ps, depth, desc, "samr_io_q_remove_sid_foreign_domain");
depth++;
if(!prs_align(ps))
@@ -221,13 +221,13 @@ BOOL samr_io_q_remove_user_foreign_domain(const char *desc, SAMR_Q_REMOVE_USER_F
reads or writes a structure.
********************************************************************/
-BOOL samr_io_r_remove_user_foreign_domain(const char *desc, SAMR_R_REMOVE_USER_FOREIGN_DOMAIN * r_u,
+BOOL samr_io_r_remove_sid_foreign_domain(const char *desc, SAMR_R_REMOVE_SID_FOREIGN_DOMAIN * r_u,
prs_struct *ps, int depth)
{
if (r_u == NULL)
return False;
- prs_debug(ps, depth, desc, "samr_io_r_remove_user_foreign_domain");
+ prs_debug(ps, depth, desc, "samr_io_r_remove_sid_foreign_domain");
depth++;
if(!prs_align(ps))
@@ -5938,7 +5938,7 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
const char* description = pdb_get_acct_desc(pw);
const char* workstations = pdb_get_workstations(pw);
const char* munged_dial = pdb_get_munged_dial(pw);
- DATA_BLOB blob = base64_decode_data_blob(munged_dial);
+ DATA_BLOB munged_dial_blob;
uint32 user_rid;
const DOM_SID *user_sid;
@@ -5946,6 +5946,12 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
uint32 group_rid;
const DOM_SID *group_sid;
+ if (munged_dial) {
+ munged_dial_blob = base64_decode_data_blob(munged_dial);
+ } else {
+ munged_dial_blob = data_blob(NULL, 0);
+ }
+
/* Create NTTIME structs */
unix_to_nt_time (&logon_time, pdb_get_logon_time(pw));
unix_to_nt_time (&logoff_time, pdb_get_logoff_time(pw));
@@ -5975,7 +5981,7 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
user_name,
sid_to_string(user_sid_string, user_sid),
sid_to_string(domain_sid_string, domain_sid)));
- data_blob_free(&blob);
+ data_blob_free(&munged_dial_blob);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -5989,7 +5995,7 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
user_name,
sid_to_string(group_sid_string, group_sid),
sid_to_string(domain_sid_string, domain_sid)));
- data_blob_free(&blob);
+ data_blob_free(&munged_dial_blob);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -6049,9 +6055,9 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
init_unistr2(&usr->uni_unknown_str, NULL, UNI_STR_TERMINATE);
init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str);
- init_unistr2_from_datablob(&usr->uni_munged_dial, &blob);
+ init_unistr2_from_datablob(&usr->uni_munged_dial, &munged_dial_blob);
init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
- data_blob_free(&blob);
+ data_blob_free(&munged_dial_blob);
usr->unknown_6 = pdb_get_unknown_6(pw);
usr->padding4 = 0;
@@ -6296,8 +6302,8 @@ NTSTATUS make_samr_userinfo_ctr_usr21(TALLOC_CTX *ctx, SAM_USERINFO_CTR * ctr,
inits a SAM_USERINFO_CTR structure.
********************************************************************/
-void init_samr_userinfo_ctr(SAM_USERINFO_CTR * ctr, uchar * sess_key,
- uint16 switch_value, void *info)
+static void init_samr_userinfo_ctr(SAM_USERINFO_CTR * ctr, DATA_BLOB *sess_key,
+ uint16 switch_value, void *info)
{
DEBUG(5, ("init_samr_userinfo_ctr\n"));
@@ -6306,13 +6312,13 @@ void init_samr_userinfo_ctr(SAM_USERINFO_CTR * ctr, uchar * sess_key,
switch (switch_value) {
case 0x18:
- SamOEMhash(ctr->info.id24->pass, sess_key, 516);
- dump_data(100, (char *)sess_key, 16);
+ SamOEMhashBlob(ctr->info.id24->pass, 516, sess_key);
+ dump_data(100, (char *)sess_key->data, sess_key->length);
dump_data(100, (char *)ctr->info.id24->pass, 516);
break;
case 0x17:
- SamOEMhash(ctr->info.id23->pass, sess_key, 516);
- dump_data(100, (char *)sess_key, 16);
+ SamOEMhashBlob(ctr->info.id23->pass, 516, sess_key);
+ dump_data(100, (char *)sess_key->data, sess_key->length);
dump_data(100, (char *)ctr->info.id23->pass, 516);
break;
default:
@@ -6497,7 +6503,7 @@ inits a SAMR_Q_SET_USERINFO structure.
********************************************************************/
void init_samr_q_set_userinfo(SAMR_Q_SET_USERINFO * q_u,
- POLICY_HND *hnd, unsigned char sess_key[16],
+ POLICY_HND *hnd, DATA_BLOB *sess_key,
uint16 switch_value, void *info)
{
DEBUG(5, ("init_samr_q_set_userinfo\n"));
@@ -6571,7 +6577,7 @@ inits a SAMR_Q_SET_USERINFO2 structure.
********************************************************************/
void init_samr_q_set_userinfo2(SAMR_Q_SET_USERINFO2 * q_u,
- POLICY_HND *hnd, unsigned char sess_key[16],
+ POLICY_HND *hnd, DATA_BLOB *sess_key,
uint16 switch_value, SAM_USERINFO_CTR * ctr)
{
DEBUG(5, ("init_samr_q_set_userinfo2\n"));
@@ -6585,9 +6591,9 @@ void init_samr_q_set_userinfo2(SAMR_Q_SET_USERINFO2 * q_u,
switch (switch_value) {
case 0x12:
- SamOEMhash(ctr->info.id12->lm_pwd, sess_key, 16);
- SamOEMhash(ctr->info.id12->nt_pwd, sess_key, 16);
- dump_data(100, (char *)sess_key, 16);
+ SamOEMhashBlob(ctr->info.id12->lm_pwd, 16, sess_key);
+ SamOEMhashBlob(ctr->info.id12->nt_pwd, 16, sess_key);
+ dump_data(100, (char *)sess_key->data, sess_key->length);
dump_data(100, (char *)ctr->info.id12->lm_pwd, 16);
dump_data(100, (char *)ctr->info.id12->nt_pwd, 16);
break;
diff --git a/source/rpc_server/srv_dfs_nt.c b/source/rpc_server/srv_dfs_nt.c
index ac3ed9c3947..f324fd126ed 100644
--- a/source/rpc_server/srv_dfs_nt.c
+++ b/source/rpc_server/srv_dfs_nt.c
@@ -369,6 +369,7 @@ WERROR _dfs_get_info(pipes_struct *p, DFS_Q_DFS_GET_INFO *q_u,
{
UNISTR2* uni_path = &q_u->uni_path;
uint32 level = q_u->level;
+ int consumedcnt = sizeof(pstring);
pstring path;
struct junction_map jn;
@@ -377,7 +378,7 @@ WERROR _dfs_get_info(pipes_struct *p, DFS_Q_DFS_GET_INFO *q_u,
return WERR_DFS_NO_SUCH_SERVER;
/* The following call can change the cwd. */
- if(!get_referred_path(path, &jn, NULL, NULL)) {
+ if(!get_referred_path(path, &jn, &consumedcnt, NULL) || consumedcnt < strlen(path)) {
vfs_ChDir(p->conn,p->conn->connectpath);
return WERR_DFS_NO_SUCH_VOL;
}
diff --git a/source/rpc_server/srv_lsa_nt.c b/source/rpc_server/srv_lsa_nt.c
index 0a8ad404cb3..e545d8c2673 100644
--- a/source/rpc_server/srv_lsa_nt.c
+++ b/source/rpc_server/srv_lsa_nt.c
@@ -845,6 +845,7 @@ NTSTATUS _lsa_enum_accounts(pipes_struct *p, LSA_Q_ENUM_ACCOUNTS *q_u, LSA_R_ENU
int num_entries=0;
LSA_SID_ENUM *sids=&r_u->sids;
int i=0,j=0;
+ BOOL ret;
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
return NT_STATUS_INVALID_HANDLE;
@@ -858,8 +859,14 @@ NTSTATUS _lsa_enum_accounts(pipes_struct *p, LSA_Q_ENUM_ACCOUNTS *q_u, LSA_R_ENU
return NT_STATUS_ACCESS_DENIED;
/* get the list of mapped groups (domain, local, builtin) */
- if(!pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, ENUM_ONLY_MAPPED))
+ become_root();
+ ret = pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, ENUM_ONLY_MAPPED);
+ unbecome_root();
+ if( !ret ) {
+ DEBUG(3,("_lsa_enum_accounts: enumeration of groups failed!\n"));
return NT_STATUS_OK;
+ }
+
if (q_u->enum_context >= num_entries)
return NT_STATUS_NO_MORE_ENTRIES;
diff --git a/source/rpc_server/srv_netlog_nt.c b/source/rpc_server/srv_netlog_nt.c
index e6d005b1575..e8bc6345dee 100644
--- a/source/rpc_server/srv_netlog_nt.c
+++ b/source/rpc_server/srv_netlog_nt.c
@@ -683,7 +683,8 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
pstring my_name;
fstring user_sid_string;
fstring group_sid_string;
- uchar user_sess_key[16];
+ uchar nt_session_key[16];
+ uchar lm_session_key[16];
uchar netlogon_sess_key[16];
sampw = server_info->sam_account;
@@ -718,10 +719,18 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
ZERO_STRUCT(netlogon_sess_key);
memcpy(netlogon_sess_key, p->dc.sess_key, 8);
- memcpy(user_sess_key, server_info->session_key, sizeof(user_sess_key));
- SamOEMhash(user_sess_key, netlogon_sess_key, 16);
+ if (server_info->nt_session_key.length) {
+ memcpy(nt_session_key, server_info->nt_session_key.data,
+ MIN(sizeof(nt_session_key), server_info->nt_session_key.length));
+ SamOEMhash(nt_session_key, netlogon_sess_key, 16);
+ }
+ if (server_info->lm_session_key.length) {
+ memcpy(lm_session_key, server_info->lm_session_key.data,
+ MIN(sizeof(lm_session_key), server_info->lm_session_key.length));
+ SamOEMhash(lm_session_key, netlogon_sess_key, 16);
+ }
ZERO_STRUCT(netlogon_sess_key);
-
+
init_net_user_info3(p->mem_ctx, usr_info,
user_rid,
group_rid,
@@ -743,14 +752,16 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
num_gids, /* uint32 num_groups */
gids , /* DOM_GID *gids */
0x20 , /* uint32 user_flgs (?) */
- user_sess_key,
+ server_info->nt_session_key.length ? nt_session_key : NULL,
+ server_info->lm_session_key.length ? lm_session_key : NULL,
my_name , /* char *logon_srv */
pdb_get_domain(sampw),
&domain_sid, /* DOM_SID *dom_sid */
/* Should be users domain sid, not servers - for trusted domains */
NULL); /* char *other_sids */
- ZERO_STRUCT(user_sess_key);
+ ZERO_STRUCT(nt_session_key);
+ ZERO_STRUCT(lm_session_key);
}
free_server_info(&server_info);
return status;
diff --git a/source/rpc_server/srv_pipe.c b/source/rpc_server/srv_pipe.c
index 96261c665f7..fa24efe589b 100644
--- a/source/rpc_server/srv_pipe.c
+++ b/source/rpc_server/srv_pipe.c
@@ -420,9 +420,15 @@ failed authentication on named pipe %s.\n", domain, user_name, wks, p->name ));
* Set up the sign/seal data.
*/
- {
+ if (server_info->lm_session_key.length != 16) {
+ DEBUG(1,("api_pipe_ntlmssp_verify: User [%s]\\[%s] from machine %s \
+succeeded authentication on named pipe %s, but session key was of incorrect length [%u].\n",
+ domain, user_name, wks, p->name, server_info->lm_session_key.length));
+ free_server_info(&server_info);
+ return False;
+ } else {
uchar p24[24];
- NTLMSSPOWFencrypt(server_info->first_8_lm_hash, lm_owf, p24);
+ NTLMSSPOWFencrypt(server_info->lm_session_key.data, lm_owf, p24);
{
unsigned char j = 0;
int ind;
@@ -468,7 +474,7 @@ failed authentication on named pipe %s.\n", domain, user_name, wks, p->name ));
* Store the UNIX credential data (uid/gid pair) in the pipe structure.
*/
- memcpy(p->session_key, server_info->session_key, sizeof(p->session_key));
+ p->session_key = data_blob(server_info->lm_session_key.data, server_info->lm_session_key.length);
p->pipe_user.uid = server_info->uid;
p->pipe_user.gid = server_info->gid;
diff --git a/source/rpc_server/srv_pipe_hnd.c b/source/rpc_server/srv_pipe_hnd.c
index 57e45d477fe..514c22d471e 100644
--- a/source/rpc_server/srv_pipe_hnd.c
+++ b/source/rpc_server/srv_pipe_hnd.c
@@ -342,7 +342,7 @@ static void *make_internal_rpc_pipe_p(char *pipe_name,
/* Store the session key and NT_TOKEN */
if (vuser) {
- memcpy(p->session_key, vuser->session_key, sizeof(p->session_key));
+ p->session_key = data_blob(vuser->session_key.data, vuser->session_key.length);
p->pipe_user.nt_user_token = dup_nt_token(vuser->nt_user_token);
}
@@ -772,6 +772,7 @@ static ssize_t process_complete_pdu(pipes_struct *p)
static ssize_t process_incoming_data(pipes_struct *p, char *data, size_t n)
{
size_t data_to_copy = MIN(n, MAX_PDU_FRAG_LEN - p->in_data.pdu_received_len);
+ size_t old_pdu_received_len = p->in_data.pdu_received_len;
DEBUG(10,("process_incoming_data: Start: pdu_received_len = %u, pdu_needed_len = %u, incoming data = %u\n",
(unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len,
@@ -831,10 +832,11 @@ incoming data size = %u\n", (unsigned int)p->in_data.pdu_received_len, (unsigned
/*
* Do we have a complete PDU ?
+ * (return the nym of bytes handled in the call)
*/
if(p->in_data.pdu_received_len == p->in_data.pdu_needed_len)
- return process_complete_pdu(p);
+ return process_complete_pdu(p) - old_pdu_received_len;
DEBUG(10,("process_incoming_data: not a complete PDU yet. pdu_received_len = %u, pdu_needed_len = %u\n",
(unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len ));
diff --git a/source/rpc_server/srv_samr.c b/source/rpc_server/srv_samr.c
index a0f62c20fca..971f5ed40ce 100644
--- a/source/rpc_server/srv_samr.c
+++ b/source/rpc_server/srv_samr.c
@@ -1343,13 +1343,13 @@ static BOOL api_samr_open_group(pipes_struct *p)
}
/*******************************************************************
- api_samr_remove_user_foreign_domain
+ api_samr_remove_sid_foreign_domain
********************************************************************/
-static BOOL api_samr_remove_user_foreign_domain(pipes_struct *p)
+static BOOL api_samr_remove_sid_foreign_domain(pipes_struct *p)
{
- SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN q_u;
- SAMR_R_REMOVE_USER_FOREIGN_DOMAIN r_u;
+ SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN q_u;
+ SAMR_R_REMOVE_SID_FOREIGN_DOMAIN r_u;
prs_struct *data = &p->in_data.data;
prs_struct *rdata = &p->out_data.rdata;
@@ -1357,15 +1357,15 @@ static BOOL api_samr_remove_user_foreign_domain(pipes_struct *p)
ZERO_STRUCT(q_u);
ZERO_STRUCT(r_u);
- if (!samr_io_q_remove_user_foreign_domain("", &q_u, data, 0)) {
- DEBUG(0,("api_samr_remove_user_foreign_domain: unable to unmarshall SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN.\n"));
+ if (!samr_io_q_remove_sid_foreign_domain("", &q_u, data, 0)) {
+ DEBUG(0,("api_samr_remove_sid_foreign_domain: unable to unmarshall SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN.\n"));
return False;
}
- r_u.status = _samr_remove_user_foreign_domain(p, &q_u, &r_u);
+ r_u.status = _samr_remove_sid_foreign_domain(p, &q_u, &r_u);
- if (!samr_io_r_remove_user_foreign_domain("", &r_u, rdata, 0)) {
- DEBUG(0,("api_samr_remove_user_foreign_domain: unable to marshall SAMR_R_REMOVE_USER_FOREIGN_DOMAIN.\n"));
+ if (!samr_io_r_remove_sid_foreign_domain("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_samr_remove_sid_foreign_domain: unable to marshall SAMR_R_REMOVE_SID_FOREIGN_DOMAIN.\n"));
return False;
}
@@ -1483,7 +1483,7 @@ static struct api_struct api_samr_cmds [] =
{"SAMR_OPEN_ALIAS" , SAMR_OPEN_ALIAS , api_samr_open_alias },
{"SAMR_OPEN_GROUP" , SAMR_OPEN_GROUP , api_samr_open_group },
{"SAMR_OPEN_DOMAIN" , SAMR_OPEN_DOMAIN , api_samr_open_domain },
- {"SAMR_REMOVE_USER_FOREIGN_DOMAIN" , SAMR_REMOVE_USER_FOREIGN_DOMAIN , api_samr_remove_user_foreign_domain },
+ {"SAMR_REMOVE_SID_FOREIGN_DOMAIN" , SAMR_REMOVE_SID_FOREIGN_DOMAIN , api_samr_remove_sid_foreign_domain },
{"SAMR_LOOKUP_DOMAIN" , SAMR_LOOKUP_DOMAIN , api_samr_lookup_domain },
{"SAMR_QUERY_SEC_OBJECT" , SAMR_QUERY_SEC_OBJECT , api_samr_query_sec_obj },
diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c
index b3e6478c880..7f57a9fc9d4 100644
--- a/source/rpc_server/srv_samr_nt.c
+++ b/source/rpc_server/srv_samr_nt.c
@@ -292,6 +292,7 @@ static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid)
uint32 group_entries = 0;
uint32 i;
TALLOC_CTX *mem_ctx = info->mem_ctx;
+ BOOL ret;
DEBUG(10,("load_group_domain_entries\n"));
@@ -303,13 +304,14 @@ static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid)
become_root();
-
- if (!pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED)) {
+ ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED);
+ unbecome_root();
+
+ if ( !ret ) {
DEBUG(1, ("load_group_domain_entries: pdb_enum_group_mapping() failed!\n"));
return NT_STATUS_NO_MEMORY;
}
- unbecome_root();
info->disp_info.num_group_account=group_entries;
@@ -875,140 +877,11 @@ static void make_group_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNIST
/*******************************************************************
Get the group entries - similar to get_sampwd_entries().
- ********************************************************************/
-
-static NTSTATUS get_group_alias_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM_SID *sid, uint32 start_idx,
- uint32 *p_num_entries, uint32 max_entries)
-{
- fstring sid_str;
- uint32 num_entries = 0;
- int i;
- GROUP_MAP smap;
- GROUP_MAP *map = NULL;
-
- sid_to_string(sid_str, sid);
- DEBUG(5, ("get_group_alias_entries: enumerating aliases on SID: %s\n", sid_str));
-
- *p_num_entries = 0;
-
- /* well-known aliases */
- if (sid_equal(sid, &global_sid_Builtin) && !lp_hide_local_users()) {
-
- become_root();
- pdb_enum_group_mapping(SID_NAME_WKN_GRP, &map, (int *)&num_entries, ENUM_ONLY_MAPPED);
- unbecome_root();
-
- if (num_entries != 0) {
- *d_grp=(DOMAIN_GRP *)talloc_zero(ctx, num_entries*sizeof(DOMAIN_GRP));
- if (*d_grp==NULL)
- return NT_STATUS_NO_MEMORY;
-
- for(i=0; i<num_entries && i<max_entries; i++) {
- fstrcpy((*d_grp)[i].name, map[i+start_idx].nt_name);
- sid_split_rid(&map[i+start_idx].sid, &(*d_grp)[i].rid);
-
- }
- }
- SAFE_FREE(map);
-
- } else if (sid_equal(sid, get_global_sam_sid()) && !lp_hide_local_users()) {
- struct sys_grent *glist;
- struct sys_grent *grp;
- gid_t winbind_gid_low, winbind_gid_high;
- BOOL winbind_groups_exist = lp_idmap_gid(&winbind_gid_low, &winbind_gid_high);
- BOOL ret;
-
- /* local aliases */
- /* we return the UNIX groups here. This seems to be the right */
- /* thing to do, since NT member servers return their local */
- /* groups in the same situation. */
-
- /* use getgrent_list() to retrieve the list of groups to avoid
- * problems with getgrent possible infinite loop by internal
- * libc grent structures overwrites by called functions */
- grp = glist = getgrent_list();
- if (grp == NULL)
- return NT_STATUS_NO_MEMORY;
-
- for (; (num_entries < max_entries) && (grp != NULL); grp = grp->next) {
- uint32 trid;
-
- become_root();
- ret = pdb_getgrgid(&smap, grp->gr_gid);
- unbecome_root();
- if( !ret )
- continue;
-
- if (smap.sid_name_use!=SID_NAME_ALIAS) {
- continue;
- }
-
- sid_split_rid(&smap.sid, &trid);
-
- if (!sid_equal(sid, &smap.sid))
- continue;
-
- /* Don't return winbind groups as they are not local! */
- if (winbind_groups_exist && (grp->gr_gid >= winbind_gid_low)&&(grp->gr_gid <= winbind_gid_high)) {
- DEBUG(10,("get_group_alias_entries: not returing %s, not local.\n", smap.nt_name ));
- continue;
- }
-
- /* Don't return user private groups... */
-
- if (Get_Pwnam(smap.nt_name) != 0) {
- DEBUG(10,("get_group_alias_entries: not returing %s, clashes with user.\n", smap.nt_name ));
- continue;
- }
-
- for( i = 0; i < num_entries; i++)
- if ( (*d_grp)[i].rid == trid )
- break;
-
- if ( i < num_entries ) {
- continue; /* rid was there, dup! */
- }
-
- /* JRA - added this for large group db enumeration... */
-
- if (start_idx > 0) {
- /* skip the requested number of entries.
- not very efficient, but hey...
- */
- start_idx--;
- continue;
- }
-
- *d_grp=talloc_realloc(ctx,*d_grp, (num_entries+1)*sizeof(DOMAIN_GRP));
- if (*d_grp==NULL) {
- grent_free(glist);
- return NT_STATUS_NO_MEMORY;
- }
-
- fstrcpy((*d_grp)[num_entries].name, smap.nt_name);
- (*d_grp)[num_entries].rid = trid;
- num_entries++;
- DEBUG(10,("get_group_alias_entries: added entry %d, rid:%d\n", num_entries, trid));
- }
-
- grent_free(glist);
- }
-
- *p_num_entries = num_entries;
-
- DEBUG(10,("get_group_alias_entries: returning %d entries\n", *p_num_entries));
-
- if (num_entries >= max_entries)
- return STATUS_MORE_ENTRIES;
- return NT_STATUS_OK;
-}
-
-/*******************************************************************
- Get the group entries - similar to get_sampwd_entries().
- ********************************************************************/
+ ******************************************************************/
-static NTSTATUS get_group_domain_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM_SID *sid, uint32 start_idx,
- uint32 *p_num_entries, uint32 max_entries)
+static NTSTATUS get_group_entries( enum SID_NAME_USE type, TALLOC_CTX *ctx,
+ DOMAIN_GRP **d_grp, DOM_SID *sid, uint32 start_idx,
+ uint32 *p_num_entries, uint32 max_entries )
{
GROUP_MAP *map=NULL;
int i;
@@ -1021,7 +894,7 @@ static NTSTATUS get_group_domain_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DO
needed for some passdb backends to enumerate groups */
become_root();
- pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED);
+ pdb_enum_group_mapping(type, &map, (int *)&group_entries, ENUM_ONLY_MAPPED);
unbecome_root();
num_entries=group_entries-start_idx;
@@ -1042,13 +915,51 @@ static NTSTATUS get_group_domain_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DO
fstrcpy((*d_grp)[i].name, map[i+start_idx].nt_name);
fstrcpy((*d_grp)[i].comment, map[i+start_idx].comment);
sid_split_rid(&map[i+start_idx].sid, &(*d_grp)[i].rid);
- (*d_grp)[i].attr=SID_NAME_DOM_GRP;
+ (*d_grp)[i].attr=type;
}
SAFE_FREE(map);
*p_num_entries = num_entries;
+ DEBUG(10,("get_group_entries: returning %d entries\n", *p_num_entries));
+
+ return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ Wrapper for enuemrating domain groups
+ ******************************************************************/
+
+static NTSTATUS get_group_domain_entries( TALLOC_CTX *ctx, DOMAIN_GRP **d_grp,
+ DOM_SID *sid, uint32 start_idx,
+ uint32 *p_num_entries, uint32 max_entries )
+{
+ return get_group_entries( SID_NAME_DOM_GRP, ctx, d_grp, sid, start_idx,
+ p_num_entries, max_entries );
+}
+
+/*******************************************************************
+ Wrapper for enumerating local groups
+ ******************************************************************/
+
+static NTSTATUS get_group_alias_entries( TALLOC_CTX *ctx, DOMAIN_GRP **d_grp,
+ DOM_SID *sid, uint32 start_idx,
+ uint32 *p_num_entries, uint32 max_entries)
+{
+ if ( sid_equal(sid, &global_sid_Builtin) ) {
+ return get_group_entries( SID_NAME_WKN_GRP, ctx, d_grp,
+ sid, start_idx, p_num_entries, max_entries );
+ }
+ else if ( sid_equal(sid, get_global_sam_sid()) ) {
+ return get_group_entries( SID_NAME_ALIAS, ctx, d_grp,
+ sid, start_idx, p_num_entries, max_entries );
+ }
+
+ /* can't do anything with this SID */
+
+ *p_num_entries = 0;
+
return NT_STATUS_OK;
}
@@ -1473,8 +1384,6 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO
DEBUG(5,("_samr_lookup_names: looking name on SID %s\n", sid_to_string(sid_str, &pol_sid)));
- become_root(); /* local_lookup_name can require root privs */
-
for (i = 0; i < num_rids; i++) {
fstring name;
DOM_SID sid;
@@ -1510,8 +1419,6 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO
}
}
- unbecome_root();
-
init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, (uint32 *)type, r_u->status);
DEBUG(5,("_samr_lookup_names: %d\n", __LINE__));
@@ -2223,6 +2130,12 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
return nt_status;
}
+ if (!acb_info) {
+ /* Match Win2k, and return NT_STATUS_INVALID_PARAMETER if
+ this parameter is zero (ie, no user type specified) */
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
/* find the account: tell the caller if it exists.
lkclXXXX i have *no* idea if this is a problem or not
or even if you are supposed to construct a different
@@ -3044,7 +2957,10 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
break;
case 24:
- SamOEMhash(ctr->info.id24->pass, p->session_key, 516);
+ if (!p->session_key.length) {
+ return NT_STATUS_NO_USER_SESSION_KEY;
+ }
+ SamOEMhashBlob(ctr->info.id24->pass, 516, &p->session_key);
dump_data(100, (char *)ctr->info.id24->pass, 516);
@@ -3062,7 +2978,10 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
* info level and W2K SP2 drops down to level 23... JRA.
*/
- SamOEMhash(ctr->info.id25->pass, p->session_key, 532);
+ if (!p->session_key.length) {
+ return NT_STATUS_NO_USER_SESSION_KEY;
+ }
+ SamOEMhashBlob(ctr->info.id25->pass, 532, &p->session_key);
dump_data(100, (char *)ctr->info.id25->pass, 532);
@@ -3073,7 +2992,10 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
return NT_STATUS_INVALID_INFO_CLASS;
case 23:
- SamOEMhash(ctr->info.id23->pass, p->session_key, 516);
+ if (!p->session_key.length) {
+ return NT_STATUS_NO_USER_SESSION_KEY;
+ }
+ SamOEMhashBlob(ctr->info.id23->pass, 516, &p->session_key);
dump_data(100, (char *)ctr->info.id23->pass, 516);
@@ -4330,75 +4252,114 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G
}
/*********************************************************************
- _samr_remove_user_foreign_domain
+ _samr_remove_sid_foreign_domain
*********************************************************************/
-NTSTATUS _samr_remove_user_foreign_domain(pipes_struct *p,
- SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN *q_u,
- SAMR_R_REMOVE_USER_FOREIGN_DOMAIN *r_u)
+NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p,
+ SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN *q_u,
+ SAMR_R_REMOVE_SID_FOREIGN_DOMAIN *r_u)
{
- DOM_SID user_sid, dom_sid;
+ DOM_SID delete_sid, alias_sid;
SAM_ACCOUNT *sam_pass=NULL;
uint32 acc_granted;
+ GROUP_MAP map;
+ BOOL is_user = False;
+ NTSTATUS result;
+ enum SID_NAME_USE type = SID_NAME_UNKNOWN;
- sid_copy( &user_sid, &q_u->sid.sid );
+ sid_copy( &delete_sid, &q_u->sid.sid );
- DEBUG(5,("_samr_remove_user_foreign_domain: removing user [%s]\n",
- sid_string_static(&user_sid)));
+ DEBUG(5,("_samr_remove_sid_foreign_domain: removing SID [%s]\n",
+ sid_string_static(&delete_sid)));
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &alias_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
+
+ result = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS,
+ "_samr_remove_sid_foreign_domain");
- if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted,
- STD_RIGHT_DELETE_ACCESS, "_samr_remove_user_foreign_domain")))
- {
- return r_u->status;
- }
+ if (!NT_STATUS_IS_OK(result))
+ return result;
+
+ DEBUG(8, ("_samr_remove_sid_foreign_domain:sid is %s\n",
+ sid_string_static(&alias_sid)));
- if ( !sid_check_is_in_our_domain(&user_sid) ) {
- DEBUG(5,("_samr_remove_user_foreign_domain: user not is our domain!\n"));
- return NT_STATUS_NO_SUCH_USER;
+ /* make sure we can handle this */
+
+ if ( sid_check_is_domain(&alias_sid) )
+ type = SID_NAME_DOM_GRP;
+ else if ( sid_check_is_builtin(&alias_sid) )
+ type = SID_NAME_ALIAS;
+
+ if ( type == SID_NAME_UNKNOWN ) {
+ DEBUG(10, ("_samr_remove_sid_foreign_domain: can't operate on what we don't own!\n"));
+ return NT_STATUS_OK;
}
/* check if the user exists before trying to delete */
pdb_init_sam(&sam_pass);
- if ( !pdb_getsampwsid(sam_pass, &user_sid) ) {
+ if ( pdb_getsampwsid(sam_pass, &delete_sid) ) {
+ is_user = True;
+ } else {
+ /* maybe it is a group */
+ if( !pdb_getgrsid(&map, delete_sid) ) {
+ DEBUG(3,("_samr_remove_sid_foreign_domain: %s is not a user or a group!\n",
+ sid_string_static(&delete_sid)));
+ result = NT_STATUS_INVALID_SID;
+ goto done;
+ }
+ }
- DEBUG(5,("_samr_remove_user_foreign_domain:User %s doesn't exist.\n",
- sid_string_static(&user_sid)));
-
- pdb_free_sam(&sam_pass);
+ /* we can only delete a user from a group since we don't have
+ nested groups anyways. So in the latter case, just say OK */
+
+ if ( is_user ) {
+ GROUP_MAP *mappings = NULL;
+ uint32 num_groups, i;
+ struct group *grp2;
- return NT_STATUS_NO_SUCH_USER;
- }
+ if ( pdb_enum_group_mapping(type, &mappings, &num_groups, False) && num_groups>0 ) {
+
+ /* interate over the groups */
+ for ( i=0; i<num_groups; i++ ) {
- /*
- * delete the unix side
- *
- * note: we don't check if the delete really happened
- * as the script is not necessary present
- * and maybe the sysadmin doesn't want to delete the unix side
- */
-
- smb_delete_user(pdb_get_username(sam_pass));
+ grp2 = getgrgid(mappings[i].gid);
- /* and delete the samba side */
-
- if ( !pdb_delete_sam_account(sam_pass) ) {
-
- DEBUG(5,("_samr_delete_dom_user:Failed to delete entry for user %s.\n", pdb_get_username(sam_pass)));
- pdb_free_sam(&sam_pass);
-
- return NT_STATUS_CANNOT_DELETE;
+ if ( !grp2 ) {
+ DEBUG(0,("_samr_remove_sid_foreign_domain: group mapping without UNIX group!\n"));
+ continue;
+ }
+
+ if ( !user_in_unix_group_list(pdb_get_username(sam_pass), grp2->gr_name) )
+ continue;
+
+ smb_delete_user_group(grp2->gr_name, pdb_get_username(sam_pass));
+
+ if ( user_in_unix_group_list(pdb_get_username(sam_pass), grp2->gr_name) ) {
+ /* should we fail here ? */
+ DEBUG(0,("_samr_remove_sid_foreign_domain: Delete user [%s] from group [%s] failed!\n",
+ pdb_get_username(sam_pass), grp2->gr_name ));
+ continue;
+ }
+
+ DEBUG(10,("_samr_remove_sid_foreign_domain: Removed user [%s] from group [%s]!\n",
+ pdb_get_username(sam_pass), grp2->gr_name ));
+ }
+
+ SAFE_FREE(mappings);
+ }
}
+ result = NT_STATUS_OK;
+done:
+
pdb_free_sam(&sam_pass);
- return NT_STATUS_OK;
+ return result;
}
/*******************************************************************
diff --git a/source/rpc_server/srv_srvsvc_nt.c b/source/rpc_server/srv_srvsvc_nt.c
index 4d1cf9bddcb..40d3a43bef9 100644
--- a/source/rpc_server/srv_srvsvc_nt.c
+++ b/source/rpc_server/srv_srvsvc_nt.c
@@ -487,10 +487,9 @@ static void init_srv_share_info_1501(pipes_struct *p, SRV_SHARE_INFO_1501 *sh150
static BOOL is_hidden_share(int snum)
{
- pstring net_name;
+ const char *net_name = lp_servicename(snum);
- pstrcpy(net_name, lp_servicename(snum));
- return (net_name[strlen(net_name)] == '$') ? True : False;
+ return (net_name[strlen(net_name) - 1] == '$') ? True : False;
}
/*******************************************************************
diff --git a/source/rpc_server/srv_util.c b/source/rpc_server/srv_util.c
index 632d381503e..c2395e6faec 100644
--- a/source/rpc_server/srv_util.c
+++ b/source/rpc_server/srv_util.c
@@ -281,6 +281,7 @@ BOOL get_domain_user_groups(TALLOC_CTX *ctx, int *numgroups, DOM_GID **pgids, SA
fstring user_name;
uint32 grid;
uint32 tmp_rid;
+ BOOL ret;
*numgroups= 0;
@@ -290,15 +291,21 @@ BOOL get_domain_user_groups(TALLOC_CTX *ctx, int *numgroups, DOM_GID **pgids, SA
DEBUG(10,("get_domain_user_groups: searching domain groups [%s] is a member of\n", user_name));
/* we must wrap this is become/unbecome root for ldap backends */
+
become_root();
-
/* first get the list of the domain groups */
- if (!pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, &num_entries, ENUM_ONLY_MAPPED))
+ ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, &num_entries, ENUM_ONLY_MAPPED);
+
+ unbecome_root();
+
+ /* end wrapper for group enumeration */
+
+
+ if ( !ret )
return False;
+
DEBUG(10,("get_domain_user_groups: there are %d mapped groups\n", num_entries));
- unbecome_root();
- /* end wrapper for group enumeration */
/*
* alloc memory. In the worse case, we alloc memory for nothing.
@@ -375,7 +382,7 @@ BOOL get_domain_user_groups(TALLOC_CTX *ctx, int *numgroups, DOM_GID **pgids, SA
done:
*pgids=gids;
*numgroups=cur_gid;
- safe_free(map);
+ SAFE_FREE(map);
return True;
}
diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c
index d99570ff7c0..5caf78e41a6 100644
--- a/source/smbd/chgpasswd.c
+++ b/source/smbd/chgpasswd.c
@@ -245,7 +245,8 @@ static int expect(int master, char *issue, char *expected)
if (strequal(expected, "."))
return True;
- timeout = 2000;
+ /* Initial timeout. */
+ timeout = lp_passwd_chat_timeout() * 1000;
nread = 0;
buffer[nread] = 0;
@@ -261,8 +262,10 @@ static int expect(int master, char *issue, char *expected)
pstrcpy( str, buffer);
trim_char( str, ' ', ' ');
- if ((match = (unix_wild_match(expected, str) == 0)))
- timeout = 200;
+ if ((match = (unix_wild_match(expected, str) == 0))) {
+ /* Now data has started to return, lower timeout. */
+ timeout = lp_passwd_chat_timeout() * 100;
+ }
}
}
diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c
index f88964123e1..fb72a2eafc8 100644
--- a/source/smbd/dosmode.c
+++ b/source/smbd/dosmode.c
@@ -183,6 +183,7 @@ uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf)
/*******************************************************************
chmod a file - but preserve some bits
********************************************************************/
+
int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_STAT *st)
{
SMB_STRUCT_STAT st1;
@@ -197,6 +198,8 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST
return(-1);
}
+ get_acl_group_bits(conn, fname, &st->st_mode);
+
if (S_ISDIR(st->st_mode))
dosmode |= aDIR;
else
diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c
index 86d982b0227..dd92cc4e4d5 100644
--- a/source/smbd/ipc.c
+++ b/source/smbd/ipc.c
@@ -445,6 +445,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
of the parameter/data bytes */
outsize = set_message(outbuf,0,0,True);
show_msg(outbuf);
+ srv_signing_trans_stop();
if (!send_smb(smbd_server_fd(),outbuf))
exit_server("reply_trans: send_smb failed.");
}
@@ -456,6 +457,13 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
+ /*
+ * The sequence number for the trans reply is always
+ * based on the last secondary received.
+ */
+
+ srv_signing_trans_start(SVAL(inbuf,smb_mid));
+
if ((ret && (CVAL(inbuf, smb_com) != SMBtranss)) || !ret) {
if(ret) {
DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
diff --git a/source/smbd/lanman.c b/source/smbd/lanman.c
index 3ea6ab483be..c53889a7a47 100644
--- a/source/smbd/lanman.c
+++ b/source/smbd/lanman.c
@@ -1635,6 +1635,7 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c
char *str1 = param+2;
char *str2 = skip_string(str1,1);
char *p = skip_string(str2,1);
+ BOOL ret;
GROUP_MAP *group_list;
int num_entries;
@@ -1653,8 +1654,12 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c
return False;
/* get list of domain groups SID_DOMAIN_GRP=2 */
- if(!pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False)) {
- DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
+ become_root();
+ ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False);
+ unbecome_root();
+
+ if( !ret ) {
+ DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
return False;
}
diff --git a/source/smbd/mangle_hash.c b/source/smbd/mangle_hash.c
index ac2d7681e8e..16722ae6e9d 100644
--- a/source/smbd/mangle_hash.c
+++ b/source/smbd/mangle_hash.c
@@ -139,7 +139,7 @@ extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */
/* -------------------------------------------------------------------- */
-static NTSTATUS has_valid_chars(const smb_ucs2_t *s, BOOL allow_wildcards)
+static NTSTATUS has_valid_83_chars(const smb_ucs2_t *s, BOOL allow_wildcards)
{
if (!s || !*s)
return NT_STATUS_INVALID_PARAMETER;
@@ -176,7 +176,7 @@ static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **pr
if ((p = strrchr_w(*prefix, UCS2_CHAR('.')))) {
ext_len = strlen_w(p+1);
if ((ext_len > 0) && (ext_len < 4) && (p != *prefix) &&
- (NT_STATUS_IS_OK(has_valid_chars(p+1,allow_wildcards)))) /* check extension */ {
+ (NT_STATUS_IS_OK(has_valid_83_chars(p+1,allow_wildcards)))) /* check extension */ {
*p = 0;
*extension = strdup_w(p+1);
if (!*extension) {
@@ -200,7 +200,7 @@ static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **pr
* ************************************************************************** **
*/
-static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards)
+static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards, BOOL only_8_3)
{
smb_ucs2_t *str, *p;
NTSTATUS ret = NT_STATUS_OK;
@@ -216,9 +216,11 @@ static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards)
if (*fname == UCS2_CHAR('.'))
return NT_STATUS_UNSUCCESSFUL;
- ret = has_valid_chars(fname, allow_wildcards);
- if (!NT_STATUS_IS_OK(ret))
- return ret;
+ if (only_8_3) {
+ ret = has_valid_83_chars(fname, allow_wildcards);
+ if (!NT_STATUS_IS_OK(ret))
+ return ret;
+ }
str = strdup_w(fname);
p = strchr_w(str, UCS2_CHAR('.'));
@@ -286,7 +288,7 @@ static NTSTATUS is_8_3_w(const smb_ucs2_t *fname, BOOL allow_wildcards)
if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0)
return NT_STATUS_OK;
- if (!NT_STATUS_IS_OK(is_valid_name(fname, allow_wildcards)))
+ if (!NT_STATUS_IS_OK(is_valid_name(fname, allow_wildcards, True)))
goto done;
if (!NT_STATUS_IS_OK(mangle_get_prefix(fname, &pref, &ext, allow_wildcards)))
@@ -737,7 +739,7 @@ static void name_map(char *OutName, BOOL need83, BOOL cache83)
return;
}
- if( !need83 && !NT_STATUS_IS_OK(is_valid_name(OutName_ucs2, False)))
+ if( !need83 && !NT_STATUS_IS_OK(is_valid_name(OutName_ucs2, False, False)))
need83 = True;
/* check if it's already in 8.3 format */
diff --git a/source/smbd/mangle_hash2.c b/source/smbd/mangle_hash2.c
index 7e7bc8c68cf..8dfa84d0548 100644
--- a/source/smbd/mangle_hash2.c
+++ b/source/smbd/mangle_hash2.c
@@ -325,7 +325,7 @@ static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards)
prefix_len = PTR_DIFF(dot_p, name);
suffix_len = len - (prefix_len+1);
- if (prefix_len > 8 || suffix_len > 3) {
+ if (prefix_len > 8 || suffix_len > 3 || suffix_len == 0) {
return False;
}
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index 80297daaef3..767df0b7251 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -2488,6 +2488,7 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
/* We need to send an interim response then receive the rest
of the parameter/data bytes */
outsize = set_message(outbuf,0,0,True);
+ srv_signing_trans_stop();
if (!send_smb(smbd_server_fd(),outbuf))
exit_server("reply_nttrans: send_smb failed.");
@@ -2498,6 +2499,13 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
+ /*
+ * The sequence number for the trans reply is always
+ * based on the last secondary received.
+ */
+
+ srv_signing_trans_start(SVAL(inbuf,smb_mid));
+
if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) {
outsize = set_message(outbuf,0,0,True);
if(ret) {
diff --git a/source/smbd/open.c b/source/smbd/open.c
index ef7ace862ae..3807c18e784 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -30,7 +30,7 @@ extern BOOL global_client_failed_oplock_break;
fd support routines - attempt to do a dos_open.
****************************************************************************/
-static int fd_open(struct connection_struct *conn, char *fname,
+static int fd_open(struct connection_struct *conn, const char *fname,
int flags, mode_t mode)
{
int fd;
@@ -41,13 +41,6 @@ static int fd_open(struct connection_struct *conn, char *fname,
fd = SMB_VFS_OPEN(conn,fname,flags,mode);
- /* Fix for files ending in '.' */
- if((fd == -1) && (errno == ENOENT) &&
- (strchr_m(fname,'.')==NULL)) {
- pstrcat(fname,".");
- fd = SMB_VFS_OPEN(conn,fname,flags,mode);
- }
-
DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname,
flags, (int)mode, fd, (fd == -1) ? strerror(errno) : "" ));
@@ -70,7 +63,7 @@ int fd_close(struct connection_struct *conn, files_struct *fsp)
Check a filename for the pipe string.
****************************************************************************/
-static void check_for_pipe(char *fname)
+static void check_for_pipe(const char *fname)
{
/* special case of pipe opens */
char s[10];
@@ -89,10 +82,9 @@ static void check_for_pipe(char *fname)
****************************************************************************/
static BOOL open_file(files_struct *fsp,connection_struct *conn,
- const char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access)
+ const char *fname,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access)
{
extern struct current_user current_user;
- pstring fname;
int accmode = (flags & O_ACCMODE);
int local_flags = flags;
@@ -100,8 +92,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn,
fsp->oplock_type = NO_OPLOCK;
errno = EPERM;
- pstrcpy(fname,fname1);
-
/* Check permissions */
/*
diff --git a/source/smbd/password.c b/source/smbd/password.c
index 958ed663e67..494d9ecd439 100644
--- a/source/smbd/password.c
+++ b/source/smbd/password.c
@@ -77,6 +77,8 @@ void invalidate_vuid(uint16 vuid)
free_server_info(&vuser->server_info);
+ data_blob_free(&vuser->session_key);
+
DLIST_REMOVE(validated_users, vuser);
/* clear the vuid from the 'cache' on each connection, and
@@ -109,25 +111,36 @@ void invalidate_all_vuids(void)
* @param server_info The token returned from the authentication process.
* (now 'owned' by register_vuid)
*
+ * @param session_key The User session key for the login session (now also 'owned' by register_vuid)
+ *
+ * @param respose_blob The NT challenge-response, if available. (May be freed after this call)
+ *
+ * @param smb_name The untranslated name of the user
+ *
* @return Newly allocated vuid, biased by an offset. (This allows us to
* tell random client vuid's (normally zero) from valid vuids.)
*
*/
-int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB response_blob, const char *smb_name)
+int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, DATA_BLOB response_blob, const char *smb_name)
{
user_struct *vuser = NULL;
/* Ensure no vuid gets registered in share level security. */
- if(lp_security() == SEC_SHARE)
+ if(lp_security() == SEC_SHARE) {
+ data_blob_free(&session_key);
return UID_FIELD_INVALID;
+ }
/* Limit allowed vuids to 16bits - VUID_OFFSET. */
- if (num_validated_vuids >= 0xFFFF-VUID_OFFSET)
+ if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) {
+ data_blob_free(&session_key);
return UID_FIELD_INVALID;
+ }
if((vuser = (user_struct *)malloc( sizeof(user_struct) )) == NULL) {
DEBUG(0,("Failed to malloc users struct!\n"));
+ data_blob_free(&session_key);
return UID_FIELD_INVALID;
}
@@ -156,6 +169,7 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB response_blob
if (vuser->n_groups) {
if (!(vuser->groups = memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) {
DEBUG(0,("register_vuid: failed to memdup vuser->groups\n"));
+ data_blob_free(&session_key);
free(vuser);
free_server_info(&server_info);
return UID_FIELD_INVALID;
@@ -197,7 +211,7 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB response_blob
}
}
- memcpy(vuser->session_key, server_info->session_key, sizeof(vuser->session_key));
+ vuser->session_key = session_key;
DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n",
(unsigned int)vuser->uid,
@@ -211,6 +225,7 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB response_blob
} else {
DEBUG(1, ("server_info does not contain a user_token - cannot continue\n"));
free_server_info(&server_info);
+ data_blob_free(&session_key);
SAFE_FREE(vuser->homedir);
SAFE_FREE(vuser->unix_homedir);
SAFE_FREE(vuser->logon_script);
diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c
index aa1d25c483a..8033c694f5d 100644
--- a/source/smbd/posix_acls.c
+++ b/source/smbd/posix_acls.c
@@ -3178,6 +3178,48 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
}
/****************************************************************************
+ Get the actual group bits stored on a file with an ACL. Has no effect if
+ the file has no ACL. Needed in dosmode code where the stat() will return
+ the mask bits, not the real group bits, for a file with an ACL.
+****************************************************************************/
+
+int get_acl_group_bits( connection_struct *conn, char *fname, mode_t *mode )
+{
+ int entry_id = SMB_ACL_FIRST_ENTRY;
+ SMB_ACL_ENTRY_T entry;
+ SMB_ACL_T posix_acl;
+
+ posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
+ if (posix_acl == (SMB_ACL_T)NULL)
+ return -1;
+
+ while (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
+ SMB_ACL_TAG_T tagtype;
+ SMB_ACL_PERMSET_T permset;
+
+ /* get_next... */
+ if (entry_id == SMB_ACL_FIRST_ENTRY)
+ entry_id = SMB_ACL_NEXT_ENTRY;
+
+ if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) ==-1)
+ return -1;
+
+ if (tagtype == SMB_ACL_GROUP_OBJ) {
+ if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
+ return -1;
+ } else {
+ *mode &= ~(S_IRGRP|S_IWGRP|S_IXGRP);
+ *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRGRP : 0);
+ *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWGRP : 0);
+ *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXGRP : 0);
+ return 0;;
+ }
+ }
+ }
+ return -1;
+}
+
+/****************************************************************************
Do a chmod by setting the ACL USER_OBJ, GROUP_OBJ and OTHER bits in an ACL
and set the mask to rwx. Needed to preserve complex ACLs set by NT.
****************************************************************************/
diff --git a/source/smbd/process.c b/source/smbd/process.c
index 8a90a15d297..5206dc70f80 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -924,11 +924,17 @@ const char *smb_fn_name(int type)
return(smb_messages[type].name);
}
-
/****************************************************************************
- Helper function for contruct_reply.
+ Helper functions for contruct_reply.
****************************************************************************/
+static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_EXTENDED_SECURITY|FLAGS2_32_BIT_ERROR_CODES;
+
+void remove_from_common_flags2(uint32 v)
+{
+ common_flags2 &= ~v;
+}
+
void construct_reply_common(char *inbuf,char *outbuf)
{
memset(outbuf,'\0',smb_size);
@@ -941,9 +947,8 @@ void construct_reply_common(char *inbuf,char *outbuf)
SCVAL(outbuf,smb_reh,0);
SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
SSVAL(outbuf,smb_flg2,
- (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
- FLAGS2_LONG_PATH_COMPONENTS |
- FLAGS2_32_BIT_ERROR_CODES | FLAGS2_EXTENDED_SECURITY);
+ (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
+ common_flags2);
SSVAL(outbuf,smb_err,SMB_SUCCESS);
SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
diff --git a/source/smbd/quotas.c b/source/smbd/quotas.c
index 91c952aa902..46f688a2194 100644
--- a/source/smbd/quotas.c
+++ b/source/smbd/quotas.c
@@ -94,23 +94,30 @@ typedef struct _LINUX_SMB_DISK_QUOTA {
static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp)
{
- int ret = -1;
+ int ret = -1;
#ifdef HAVE_LINUX_XQM_H
- struct fs_disk_quota D;
- ZERO_STRUCT(D);
-
- if ((ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D)))
- return ret;
-
- dp->bsize = (SMB_BIG_UINT)512;
- dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
- dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;
- dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;
- dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
- dp->curinodes = (SMB_BIG_UINT)D.d_icount;
- dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
+ struct fs_disk_quota D;
+
+ ZERO_STRUCT(D);
+
+ ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
+
+ /* As XFS has group quotas, if getting the user quota fails, try getting the group instead. */
+ if (ret) {
+ ret = quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), path, getegid(), (caddr_t)&D);
+ if (ret)
+ return ret;
+ }
+
+ dp->bsize = (SMB_BIG_UINT)512;
+ dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
+ dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;
+ dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;
+ dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
+ dp->curinodes = (SMB_BIG_UINT)D.d_icount;
+ dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
#endif
- return ret;
+ return ret;
}
/****************************************************************************
@@ -119,7 +126,7 @@ static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QU
static int get_smb_linux_vfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp)
{
- int ret;
+ int ret = 0;
#ifdef LINUX_QUOTAS_1
struct dqblk D;
ZERO_STRUCT(D);
@@ -133,8 +140,14 @@ static int get_smb_linux_vfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QU
dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
#endif
- if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D)))
- return -1;
+ ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
+
+ /* Linux can have group quotas, if getting the user quota fails, try getting the group instead. */
+ if (ret) {
+ ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, getegid(), (caddr_t)&D);
+ if (ret)
+ return ret;
+ }
dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
@@ -148,7 +161,7 @@ static int get_smb_linux_vfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QU
dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace)/ dp->bsize;
#endif
- return 0;
+ return ret;
}
/****************************************************************************
diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c
index 314ffbb4a9b..ec01a330ee2 100644
--- a/source/smbd/sesssetup.c
+++ b/source/smbd/sesssetup.c
@@ -149,7 +149,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
DATA_BLOB auth_data;
DATA_BLOB ap_rep, ap_rep_wrapped, response;
auth_serversupplied_info *server_info = NULL;
- uint8 session_key[16];
+ DATA_BLOB session_key;
uint8 tok_id[2];
BOOL foreign = False;
DATA_BLOB nullblob = data_blob(NULL, 0);
@@ -164,7 +164,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
- ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, session_key);
+ ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, &session_key);
data_blob_free(&ticket);
@@ -223,11 +223,8 @@ static int reply_spnego_kerberos(connection_struct *conn,
return ERROR_NT(ret);
}
- /* Copy out the session key from the AP_REQ. */
- memcpy(server_info->session_key, session_key, sizeof(session_key));
-
/* register_vuid keeps the server info */
- sess_vuid = register_vuid(server_info, nullblob, user);
+ sess_vuid = register_vuid(server_info, session_key, nullblob, user);
free(user);
@@ -297,9 +294,10 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out
if (NT_STATUS_IS_OK(nt_status)) {
int sess_vuid;
DATA_BLOB nullblob = data_blob(NULL, 0);
+ DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
/* register_vuid keeps the server info */
- sess_vuid = register_vuid(server_info, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
+ sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
(*auth_ntlmssp_state)->server_info = NULL;
if (sess_vuid == -1) {
@@ -474,6 +472,11 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
if (global_client_caps == 0) {
global_client_caps = IVAL(inbuf,smb_vwv10);
+
+ if (!(global_client_caps & CAP_STATUS32)) {
+ remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
+ }
+
}
p = (uint8 *)smb_buf(inbuf);
@@ -566,6 +569,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
NTSTATUS nt_status;
BOOL doencrypt = global_encrypted_passwords_negotiated;
+
+ DATA_BLOB session_key;
START_PROFILE(SMBsesssetupX);
@@ -615,17 +620,22 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
enum remote_arch_types ra_type = get_remote_arch();
char *p = smb_buf(inbuf);
- if(global_client_caps == 0)
+ if(global_client_caps == 0) {
global_client_caps = IVAL(inbuf,smb_vwv11);
- /* client_caps is used as final determination if client is NT or Win95.
- This is needed to return the correct error codes in some
- circumstances.
- */
+ if (!(global_client_caps & CAP_STATUS32)) {
+ remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
+ }
+
+ /* client_caps is used as final determination if client is NT or Win95.
+ This is needed to return the correct error codes in some
+ circumstances.
+ */
- if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
- if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
- set_remote_arch( RA_WIN95);
+ if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
+ if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
+ set_remote_arch( RA_WIN95);
+ }
}
}
@@ -686,7 +696,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
ra_lanman_string( native_lanman );
}
-
+
if (SVAL(inbuf,smb_vwv4) == 0) {
setup_new_vc_session();
}
@@ -766,18 +776,28 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
free_user_info(&user_info);
- data_blob_free(&lm_resp);
- data_blob_clear_free(&plaintext_password);
-
if (!NT_STATUS_IS_OK(nt_status)) {
nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
}
if (!NT_STATUS_IS_OK(nt_status)) {
data_blob_free(&nt_resp);
+ data_blob_free(&lm_resp);
+ data_blob_clear_free(&plaintext_password);
return ERROR_NT(nt_status_squash(nt_status));
}
+ if (server_info->nt_session_key.data) {
+ session_key = data_blob(server_info->nt_session_key.data, server_info->nt_session_key.length);
+ } else if (server_info->lm_session_key.length >= 8 && lm_resp.length == 24) {
+ session_key = data_blob(NULL, 16);
+ SMBsesskeygen_lmv1(server_info->lm_session_key.data, lm_resp.data,
+ session_key.data);
+ }
+
+ data_blob_free(&lm_resp);
+ data_blob_clear_free(&plaintext_password);
+
/* it's ok - setup a reply */
set_message(outbuf,3,0,True);
if (Protocol >= PROTOCOL_NT1) {
@@ -795,7 +815,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
to a uid can get through without a password, on the same VC */
/* register_vuid keeps the server info */
- sess_vuid = register_vuid(server_info, nt_resp, sub_user);
+ sess_vuid = register_vuid(server_info, session_key, nt_resp, sub_user);
data_blob_free(&nt_resp);
if (sess_vuid == -1) {
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index 56d1aae3a2a..525b0153791 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -3523,6 +3523,7 @@ int reply_trans2(connection_struct *conn,
/* We need to send an interim response then receive the rest
of the parameter/data bytes */
outsize = set_message(outbuf,0,0,True);
+ srv_signing_trans_stop();
if (!send_smb(smbd_server_fd(),outbuf))
exit_server("reply_trans2: send_smb failed.");
@@ -3536,6 +3537,13 @@ int reply_trans2(connection_struct *conn,
ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
+ /*
+ * The sequence number for the trans reply is always
+ * based on the last secondary received.
+ */
+
+ srv_signing_trans_start(SVAL(inbuf,smb_mid));
+
if ((ret &&
(CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
outsize = set_message(outbuf,0,0,True);
diff --git a/source/smbd/vfs-wrap.c b/source/smbd/vfs-wrap.c
index a76a7a6abdc..378a0a1e53c 100644
--- a/source/smbd/vfs-wrap.c
+++ b/source/smbd/vfs-wrap.c
@@ -237,14 +237,104 @@ ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp,
return result;
}
+/*********************************************************
+ For rename across filesystems Patch from Warren Birnbaum
+ <warrenb@hpcvscdp.cv.hp.com>
+**********************************************************/
+
+static int copy_reg(const char *source, const char *dest)
+{
+ SMB_STRUCT_STAT source_stats;
+ int saved_errno;
+ int ifd = -1;
+ int ofd = -1;
+
+ if (sys_lstat (source, &source_stats) == -1)
+ return -1;
+
+ if (!S_ISREG (source_stats.st_mode))
+ return -1;
+
+ if((ifd = sys_open (source, O_RDONLY, 0)) < 0)
+ return -1;
+
+ if (unlink (dest) && errno != ENOENT)
+ return -1;
+
+#ifdef O_NOFOLLOW
+ if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 )
+#else
+ if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 )
+#endif
+ goto err;
+
+ if (transfer_file(ifd, ofd, (size_t)-1) == -1)
+ goto err;
+
+ /*
+ * Try to preserve ownership. For non-root it might fail, but that's ok.
+ * But root probably wants to know, e.g. if NFS disallows it.
+ */
+
+ if ((fchown(ofd, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM))
+ goto err;
+
+ /*
+ * fchown turns off set[ug]id bits for non-root,
+ * so do the chmod last.
+ */
+
+#if defined(HAVE_FCHMOD)
+ if (fchmod (ofd, source_stats.st_mode & 07777))
+#else
+ if (chmod (dest, source_stats.st_mode & 07777))
+#endif
+ goto err;
+
+ if (close (ifd) == -1)
+ goto err;
+
+ if (close (ofd) == -1)
+ return -1;
+
+ /* Try to copy the old file's modtime and access time. */
+ {
+ struct utimbuf tv;
+
+ tv.actime = source_stats.st_atime;
+ tv.modtime = source_stats.st_mtime;
+ utime(dest, &tv);
+ }
+
+ if (unlink (source) == -1)
+ return -1;
+
+ return 0;
+
+ err:
+
+ saved_errno = errno;
+ if (ifd != -1)
+ close(ifd);
+ if (ofd != -1)
+ close(ofd);
+ errno = saved_errno;
+ return -1;
+}
+
int vfswrap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new)
{
- int result;
+ int result;
- START_PROFILE(syscall_rename);
- result = rename(old, new);
- END_PROFILE(syscall_rename);
- return result;
+ START_PROFILE(syscall_rename);
+ result = rename(old, new);
+ if (errno == EXDEV) {
+ /* Rename across filesystems needed. */
+ result = copy_reg(old, new);
+ }
+
+ END_PROFILE(syscall_rename);
+ return result;
}
int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd)
diff --git a/source/torture/nbio.c b/source/torture/nbio.c
index 6c51db3cf30..2e79584d23f 100644
--- a/source/torture/nbio.c
+++ b/source/torture/nbio.c
@@ -52,7 +52,7 @@ double nbio_total(void)
return total;
}
-void nb_alarm(void)
+void nb_alarm(int ignore)
{
int i;
int lines=0, num_clients=0;
@@ -79,6 +79,7 @@ void nbio_shmem(int n)
}
}
+#if 0
static int ne_find_handle(int handle)
{
int i;
@@ -88,6 +89,7 @@ static int ne_find_handle(int handle)
}
return -1;
}
+#endif
static int find_handle(int handle)
{
diff --git a/source/utils/net.c b/source/utils/net.c
index 75fa607caef..4d2b1eb439b 100644
--- a/source/utils/net.c
+++ b/source/utils/net.c
@@ -616,6 +616,7 @@ static struct functable net_func[] = {
{"GETDOMAINSID", net_getdomainsid},
{"MAXRID", net_maxrid},
{"IDMAP", net_idmap},
+ {"STATUS", net_status},
#ifdef WITH_FAKE_KASERVER
{"AFSKEY", net_afskey},
#endif
diff --git a/source/utils/net_ads.c b/source/utils/net_ads.c
index cad93608dc4..9404ae4b247 100644
--- a/source/utils/net_ads.c
+++ b/source/utils/net_ads.c
@@ -209,7 +209,7 @@ static int net_ads_workgroup(int argc, const char **argv)
{
ADS_STRUCT *ads;
TALLOC_CTX *ctx;
- char *workgroup;
+ const char *workgroup;
if (!(ads = ads_startup())) return -1;
@@ -656,7 +656,7 @@ int net_ads_join(int argc, const char **argv)
char *ou_str;
uint32 sec_channel_type = SEC_CHAN_WKSTA;
uint32 account_type = UF_WORKSTATION_TRUST_ACCOUNT;
- char *short_domain_name = NULL;
+ const char *short_domain_name = NULL;
TALLOC_CTX *ctx = NULL;
if (argc > 0) org_unit = argv[0];
diff --git a/source/utils/net_help.c b/source/utils/net_help.c
index c688beef72c..38261be90a7 100644
--- a/source/utils/net_help.c
+++ b/source/utils/net_help.c
@@ -88,11 +88,14 @@ int net_help_group(int argc, const char **argv)
{
d_printf("net [<method>] group [misc. options] [targets]"\
"\n\tList user groups\n\n");
+ d_printf("net rpc group LIST [global|local|builtin]* [misc. options]"\
+ "\n\tList specific user groups\n\n");
d_printf("net [<method>] group DELETE <name> "\
"[misc. options] [targets]"\
"\n\tDelete specified group\n");
d_printf("\nnet [<method>] group ADD <name> [-C comment] [-c container]"\
" [misc. options] [targets]\n\tCreate specified group\n");
+ d_printf("\nnet rpc group MEMBERS <name>\n\tList Group Members\n\n");
net_common_methods_usage(argc, argv);
net_common_flags_usage(argc, argv);
d_printf("\t-C or --comment=<comment>\tdescriptive comment (for add only)\n");
@@ -146,6 +149,15 @@ int net_help_file(int argc, const char **argv)
return -1;
}
+int net_help_status(int argc, const char **argv)
+{
+ d_printf(" net status sessions [parseable] "
+ "Show list of open sessions\n");
+ d_printf(" net status shares [parseable] "
+ "Show list of open shares\n");
+ return -1;
+}
+
static int net_usage(int argc, const char **argv)
{
d_printf(" net time\t\tto view or set time information\n"\
@@ -159,6 +171,7 @@ static int net_usage(int argc, const char **argv)
" net setlocalsid SID\tto set the local domain SID\n"\
" net changesecretpw\tto change the machine password in the local secrets database only\n"\
" \tthis requires the -f flag as a safety barrier\n"\
+ " net status\t\tShow server status\n"\
"\n"\
" net ads <command>\tto run ADS commands\n"\
" net rap <command>\tto run RAP (pre-RPC) commands\n"\
diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c
index 298e8ff6690..04a03307740 100644
--- a/source/utils/net_rpc.c
+++ b/source/utils/net_rpc.c
@@ -916,6 +916,26 @@ rpc_group_list_internals(const DOM_SID *domain_sid, struct cli_state *cli,
uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
struct acct_info *groups;
DOM_SID global_sid_Builtin;
+ BOOL global = False;
+ BOOL local = False;
+ BOOL builtin = False;
+
+ if (argc == 0) {
+ global = True;
+ local = True;
+ builtin = True;
+ }
+
+ for (i=0; i<argc; i++) {
+ if (strequal(argv[i], "global"))
+ global = True;
+
+ if (strequal(argv[i], "local"))
+ local = True;
+
+ if (strequal(argv[i], "builtin"))
+ builtin = True;
+ }
string_to_sid(&global_sid_Builtin, "S-1-5-32");
@@ -949,6 +969,8 @@ rpc_group_list_internals(const DOM_SID *domain_sid, struct cli_state *cli,
ZERO_STRUCT(info3);
ctr.sam.info3 = &info3;
+ if (!global) break;
+
get_query_dispinfo_params(
loop_count, &max_entries, &max_size);
@@ -967,12 +989,14 @@ rpc_group_list_internals(const DOM_SID *domain_sid, struct cli_state *cli,
printf("%-21.21s %-50.50s\n",
group, desc);
else
- printf("%-21.21s\n", group);
+ printf("%s\n", group);
}
} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
/* query domain aliases */
start_idx = 0;
do {
+ if (!local) break;
+
result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol,
&start_idx, max_entries,
&groups, &num_entries);
@@ -1006,7 +1030,7 @@ rpc_group_list_internals(const DOM_SID *domain_sid, struct cli_state *cli,
groups[i].acct_name,
description);
} else {
- printf("%-21.21s\n", groups[i].acct_name);
+ printf("%s\n", groups[i].acct_name);
}
}
} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
@@ -1022,6 +1046,8 @@ rpc_group_list_internals(const DOM_SID *domain_sid, struct cli_state *cli,
/* query builtin aliases */
start_idx = 0;
do {
+ if (!builtin) break;
+
result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol,
&start_idx, max_entries,
&groups, &num_entries);
@@ -1055,7 +1081,7 @@ rpc_group_list_internals(const DOM_SID *domain_sid, struct cli_state *cli,
groups[i].acct_name,
description);
} else {
- printf("%-21.21s\n", groups[i].acct_name);
+ printf("%s\n", groups[i].acct_name);
}
}
} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
@@ -1064,6 +1090,111 @@ rpc_group_list_internals(const DOM_SID *domain_sid, struct cli_state *cli,
return result;
}
+static int rpc_group_list(int argc, const char **argv)
+{
+ return run_rpc_command(NULL, PI_SAMR, 0,
+ rpc_group_list_internals,
+ argc, argv);
+}
+
+static NTSTATUS
+rpc_group_members_internals(const DOM_SID *domain_sid, struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc, const char **argv)
+{
+ NTSTATUS result;
+ POLICY_HND connect_pol, domain_pol, group_pol;
+ uint32 num_rids, *rids, *rid_types;
+ uint32 num_members, *group_rids, *group_attrs;
+ uint32 num_names;
+ char **names;
+ uint32 *name_types;
+ int i;
+
+ /* Get sam policy handle */
+
+ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Get domain policy handle */
+
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ domain_sid, &domain_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000,
+ 1, argv, &num_rids, &rids, &rid_types);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ if (num_rids != 1) {
+ d_printf("Could not find group %s\n", argv[0]);
+ goto done;
+ }
+
+ if (rid_types[0] != SID_NAME_DOM_GRP) {
+ d_printf("%s is not a domain group\n", argv[0]);
+ goto done;
+ }
+
+ result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ rids[0], &group_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol,
+ &num_members, &group_rids,
+ &group_attrs);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ do {
+ int this_time = 512;
+
+ if (num_members < this_time)
+ this_time = num_members;
+
+ result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol, 1000,
+ this_time, group_rids,
+ &num_names, &names, &name_types);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < this_time; i++) {
+ printf("%s\n", names[i]);
+ }
+
+ num_members -= this_time;
+ group_rids += 512;
+
+ } while (num_members > 0);
+
+ done:
+ return result;
+}
+
+static int rpc_group_members(int argc, const char **argv)
+{
+ if (argc != 1) {
+ return rpc_group_usage(argc, argv);
+ }
+
+ return run_rpc_command(NULL, PI_SAMR, 0,
+ rpc_group_members_internals,
+ argc, argv);
+}
+
/**
* 'net rpc group' entrypoint.
* @param argc Standard main() style argc
@@ -1078,6 +1209,8 @@ int net_rpc_group(int argc, const char **argv)
{"add", rpc_group_add},
{"delete", rpc_group_delete},
#endif
+ {"list", rpc_group_list},
+ {"members", rpc_group_members},
{NULL, NULL}
};
@@ -1727,7 +1860,7 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli
ctr.info.id24 = &p24;
result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24,
- cli->user_session_key, &ctr);
+ &cli->user_session_key, &ctr);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(0,("Could not set trust account password: %s\n",
diff --git a/source/utils/net_rpc_join.c b/source/utils/net_rpc_join.c
index 22ed49c74f6..96943468ad2 100644
--- a/source/utils/net_rpc_join.c
+++ b/source/utils/net_rpc_join.c
@@ -70,7 +70,7 @@ int net_rpc_join_ok(const char *domain)
/* ensure that schannel uses the right domain */
fstrcpy(cli->domain, domain);
if (! NT_STATUS_IS_OK(result = cli_nt_establish_netlogon(cli, channel, stored_md4_trust_password))) {
- DEBUG(0,("Error in domain join verfication\n"));
+ DEBUG(0,("Error in domain join verfication (fresh connection)\n"));
goto done;
}
@@ -282,7 +282,7 @@ int net_rpc_join_newstyle(int argc, const char **argv)
ctr.info.id24 = &p24;
CHECK_RPC_ERR(cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24,
- cli->user_session_key, &ctr),
+ &cli->user_session_key, &ctr),
"error setting trust account password");
/* Why do we have to try to (re-)set the ACB to be the same as what
@@ -304,7 +304,7 @@ int net_rpc_join_newstyle(int argc, const char **argv)
as a normal user with "Add workstation to domain" privilege. */
result = cli_samr_set_userinfo2(cli, mem_ctx, &user_pol, 0x10,
- cli->user_session_key, &ctr);
+ &cli->user_session_key, &ctr);
/* Now check the whole process from top-to-bottom */
cli_samr_close(cli, mem_ctx, &user_pol);
@@ -322,7 +322,7 @@ int net_rpc_join_newstyle(int argc, const char **argv)
md4_trust_password);
if (!NT_STATUS_IS_OK(result)) {
- DEBUG(0, ("Error domain join verification: %s\n\n",
+ DEBUG(0, ("Error domain join verification (reused connection): %s\n\n",
nt_errstr(result)));
if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) &&
diff --git a/source/utils/ntlm_auth.c b/source/utils/ntlm_auth.c
index 13b9550347d..4461f163dd5 100644
--- a/source/utils/ntlm_auth.c
+++ b/source/utils/ntlm_auth.c
@@ -29,14 +29,42 @@
#define SQUID_BUFFER_SIZE 2010
-enum squid_mode {
+enum stdio_helper_mode {
SQUID_2_4_BASIC,
SQUID_2_5_BASIC,
SQUID_2_5_NTLMSSP,
GSS_SPNEGO,
- GSS_SPNEGO_CLIENT
+ GSS_SPNEGO_CLIENT,
+ NUM_HELPER_MODES
+};
+
+typedef void (*stdio_helper_function)(enum stdio_helper_mode stdio_helper_mode,
+ char *buf, int length);
+
+static void manage_squid_basic_request (enum stdio_helper_mode stdio_helper_mode,
+ char *buf, int length);
+
+static void manage_squid_ntlmssp_request (enum stdio_helper_mode stdio_helper_mode,
+ char *buf, int length);
+
+static void manage_gss_spnego_request (enum stdio_helper_mode stdio_helper_mode,
+ char *buf, int length);
+
+static void manage_gss_spnego_client_request (enum stdio_helper_mode stdio_helper_mode,
+ char *buf, int length);
+
+static const struct {
+ enum stdio_helper_mode mode;
+ const char *name;
+ stdio_helper_function fn;
+} stdio_helper_protocols[] = {
+ { SQUID_2_4_BASIC, "squid-2.4-basic", manage_squid_basic_request},
+ { SQUID_2_5_BASIC, "squid-2.5-basic", manage_squid_basic_request},
+ { SQUID_2_5_NTLMSSP, "squid-2.5-ntlmssp", manage_squid_ntlmssp_request},
+ { GSS_SPNEGO, "gss-spnego", manage_gss_spnego_request},
+ { GSS_SPNEGO_CLIENT, "gss-spnego-client", manage_gss_spnego_client_request},
+ { NUM_HELPER_MODES, NULL, NULL}
};
-
extern int winbindd_fd;
@@ -96,7 +124,7 @@ static const char *get_winbind_domain(void)
if (winbindd_request(WINBINDD_DOMAIN_NAME, NULL, &response) !=
NSS_STATUS_SUCCESS) {
- d_printf("could not obtain winbind domain name!\n");
+ DEBUG(0, ("could not obtain winbind domain name!\n"));
return NULL;
}
@@ -122,7 +150,7 @@ static const char *get_winbind_netbios_name(void)
if (winbindd_request(WINBINDD_NETBIOS_NAME, NULL, &response) !=
NSS_STATUS_SUCCESS) {
- d_printf("could not obtain winbind netbios name!\n");
+ DEBUG(0, ("could not obtain winbind netbios name!\n"));
return NULL;
}
@@ -264,20 +292,42 @@ static NTSTATUS contact_winbind_auth_crap(const char *username,
return nt_status;
}
-static NTSTATUS winbind_pw_check(struct ntlmssp_state *ntlmssp_state)
+static NTSTATUS winbind_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *nt_session_key, DATA_BLOB *lm_session_key)
{
- return contact_winbind_auth_crap(ntlmssp_state->user, ntlmssp_state->domain,
- ntlmssp_state->workstation,
- &ntlmssp_state->chal,
- &ntlmssp_state->lm_resp,
- &ntlmssp_state->nt_resp,
- 0,
- NULL,
- NULL,
- NULL);
+ static const char zeros[16];
+ NTSTATUS nt_status;
+ char *error_string;
+ uint8 lm_key[8];
+ uint8 nt_key[16];
+
+ nt_status = contact_winbind_auth_crap(ntlmssp_state->user, ntlmssp_state->domain,
+ ntlmssp_state->workstation,
+ &ntlmssp_state->chal,
+ &ntlmssp_state->lm_resp,
+ &ntlmssp_state->nt_resp,
+ WBFLAG_PAM_LMKEY | WBFLAG_PAM_NTKEY,
+ lm_key, nt_key,
+ &error_string);
+
+ if (NT_STATUS_IS_OK(nt_status)) {
+ if (memcmp(lm_key, zeros, 8) != 0) {
+ *lm_session_key = data_blob(NULL, 16);
+ memcpy(lm_session_key->data, lm_key, 8);
+ memset(lm_session_key->data+8, '\0', 8);
+ }
+
+ if (memcmp(nt_key, zeros, 16) != 0) {
+ *nt_session_key = data_blob(nt_key, 16);
+ }
+ } else {
+ DEBUG(NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED) ? 0 : 3,
+ ("Login for user [%s]\\[%s]@[%s] failed due to [%s]\n",
+ ntlmssp_state->domain, ntlmssp_state->user, ntlmssp_state->workstation, error_string ? error_string : "unknown error (NULL)"));
+ }
+ return nt_status;
}
-static void manage_squid_ntlmssp_request(enum squid_mode squid_mode,
+static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mode,
char *buf, int length)
{
static NTLMSSP_STATE *ntlmssp_state = NULL;
@@ -295,7 +345,7 @@ static void manage_squid_ntlmssp_request(enum squid_mode squid_mode,
} else if (strcmp(buf, "YR") == 0) {
request = data_blob(NULL, 0);
if (ntlmssp_state)
- ntlmssp_server_end(&ntlmssp_state);
+ ntlmssp_end(&ntlmssp_state);
} else {
DEBUG(1, ("NTLMSSP query [%s] invalid", buf));
x_fprintf(x_stdout, "BH\n");
@@ -312,7 +362,7 @@ static void manage_squid_ntlmssp_request(enum squid_mode squid_mode,
DEBUG(10, ("got NTLMSSP packet:\n"));
dump_data(10, (const char *)request.data, request.length);
- nt_status = ntlmssp_server_update(ntlmssp_state, request, &reply);
+ nt_status = ntlmssp_update(ntlmssp_state, request, &reply);
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
char *reply_base64 = base64_encode_data_blob(reply);
@@ -320,6 +370,9 @@ static void manage_squid_ntlmssp_request(enum squid_mode squid_mode,
SAFE_FREE(reply_base64);
data_blob_free(&reply);
DEBUG(10, ("NTLMSSP challenge\n"));
+ } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) {
+ x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status));
+ DEBUG(0, ("NTLMSSP BH: %s\n", nt_errstr(nt_status)));
} else if (!NT_STATUS_IS_OK(nt_status)) {
x_fprintf(x_stdout, "NA %s\n", nt_errstr(nt_status));
DEBUG(10, ("NTLMSSP %s\n", nt_errstr(nt_status)));
@@ -331,7 +384,7 @@ static void manage_squid_ntlmssp_request(enum squid_mode squid_mode,
data_blob_free(&request);
}
-static void manage_squid_basic_request(enum squid_mode squid_mode,
+static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode,
char *buf, int length)
{
char *user, *pass;
@@ -346,7 +399,7 @@ static void manage_squid_basic_request(enum squid_mode squid_mode,
*pass='\0';
pass++;
- if (squid_mode == SQUID_2_5_BASIC) {
+ if (stdio_helper_mode == SQUID_2_5_BASIC) {
rfc1738_unescape(user);
rfc1738_unescape(pass);
}
@@ -409,7 +462,7 @@ static void offer_gss_spnego_mechs(void) {
return;
}
-static void manage_gss_spnego_request(enum squid_mode squid_mode,
+static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode,
char *buf, int length)
{
static NTLMSSP_STATE *ntlmssp_state = NULL;
@@ -470,9 +523,7 @@ static void manage_gss_spnego_request(enum squid_mode squid_mode,
if (request.type == SPNEGO_NEG_TOKEN_INIT) {
/* Second request from Client. This is where the
- client offers its mechanism to use. We currently
- only support NTLMSSP, the decision for Kerberos
- would be taken here. */
+ client offers its mechanism to use. */
if ( (request.negTokenInit.mechTypes == NULL) ||
(request.negTokenInit.mechTypes[0] == NULL) ) {
@@ -493,7 +544,7 @@ static void manage_gss_spnego_request(enum squid_mode squid_mode,
DEBUG(1, ("Client wants a new NTLMSSP challenge, but "
"already got one\n"));
x_fprintf(x_stdout, "BH\n");
- ntlmssp_server_end(&ntlmssp_state);
+ ntlmssp_end(&ntlmssp_state);
return;
}
@@ -510,7 +561,7 @@ static void manage_gss_spnego_request(enum squid_mode squid_mode,
response.negTokenTarg.supportedMech = strdup(OID_NTLMSSP);
response.negTokenTarg.mechListMIC = data_blob(NULL, 0);
- status = ntlmssp_server_update(ntlmssp_state,
+ status = ntlmssp_update(ntlmssp_state,
request.negTokenInit.mechToken,
&response.negTokenTarg.responseToken);
}
@@ -521,7 +572,7 @@ static void manage_gss_spnego_request(enum squid_mode squid_mode,
char *principal;
DATA_BLOB auth_data;
DATA_BLOB ap_rep;
- uint8 session_key[16];
+ DATA_BLOB session_key;
if ( request.negTokenInit.mechToken.data == NULL ) {
DEBUG(1, ("Client did not provide Kerberos data\n"));
@@ -537,7 +588,7 @@ static void manage_gss_spnego_request(enum squid_mode squid_mode,
status = ads_verify_ticket(lp_realm(),
&request.negTokenInit.mechToken,
&principal, &auth_data, &ap_rep,
- session_key);
+ &session_key);
/* Now in "principal" we have the name we are
authenticated as. */
@@ -583,7 +634,7 @@ static void manage_gss_spnego_request(enum squid_mode squid_mode,
return;
}
- status = ntlmssp_server_update(ntlmssp_state,
+ status = ntlmssp_update(ntlmssp_state,
request.negTokenTarg.responseToken,
&response.negTokenTarg.responseToken);
@@ -594,7 +645,7 @@ static void manage_gss_spnego_request(enum squid_mode squid_mode,
if (NT_STATUS_IS_OK(status)) {
user = strdup(ntlmssp_state->user);
domain = strdup(ntlmssp_state->domain);
- ntlmssp_server_end(&ntlmssp_state);
+ ntlmssp_end(&ntlmssp_state);
}
}
@@ -638,7 +689,7 @@ static void manage_gss_spnego_request(enum squid_mode squid_mode,
return;
}
-static NTLMSSP_CLIENT_STATE *client_ntlmssp_state = NULL;
+static NTLMSSP_STATE *client_ntlmssp_state = NULL;
static BOOL manage_client_ntlmssp_init(SPNEGO_DATA spnego)
{
@@ -677,7 +728,7 @@ static BOOL manage_client_ntlmssp_init(SPNEGO_DATA spnego)
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Could not start NTLMSSP client: %s\n",
nt_errstr(status)));
- ntlmssp_client_end(&client_ntlmssp_state);
+ ntlmssp_end(&client_ntlmssp_state);
return False;
}
@@ -686,7 +737,7 @@ static BOOL manage_client_ntlmssp_init(SPNEGO_DATA spnego)
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Could not set username: %s\n",
nt_errstr(status)));
- ntlmssp_client_end(&client_ntlmssp_state);
+ ntlmssp_end(&client_ntlmssp_state);
return False;
}
@@ -695,7 +746,7 @@ static BOOL manage_client_ntlmssp_init(SPNEGO_DATA spnego)
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Could not set domain: %s\n",
nt_errstr(status)));
- ntlmssp_client_end(&client_ntlmssp_state);
+ ntlmssp_end(&client_ntlmssp_state);
return False;
}
@@ -704,7 +755,7 @@ static BOOL manage_client_ntlmssp_init(SPNEGO_DATA spnego)
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Could not set password: %s\n",
nt_errstr(status)));
- ntlmssp_client_end(&client_ntlmssp_state);
+ ntlmssp_end(&client_ntlmssp_state);
return False;
}
@@ -713,13 +764,13 @@ static BOOL manage_client_ntlmssp_init(SPNEGO_DATA spnego)
spnego.negTokenInit.reqFlags = 0;
spnego.negTokenInit.mechListMIC = null_blob;
- status = ntlmssp_client_update(client_ntlmssp_state, null_blob,
+ status = ntlmssp_update(client_ntlmssp_state, null_blob,
&spnego.negTokenInit.mechToken);
if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
DEBUG(1, ("Expected MORE_PROCESSING_REQUIRED, got: %s\n",
nt_errstr(status)));
- ntlmssp_client_end(&client_ntlmssp_state);
+ ntlmssp_end(&client_ntlmssp_state);
return False;
}
@@ -746,23 +797,23 @@ static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego)
if (client_ntlmssp_state == NULL) {
DEBUG(1, ("Got NTLMSSP tArg without a client state\n"));
x_fprintf(x_stdout, "BH\n");
- ntlmssp_client_end(&client_ntlmssp_state);
+ ntlmssp_end(&client_ntlmssp_state);
return;
}
if (spnego.negTokenTarg.negResult == SPNEGO_REJECT) {
x_fprintf(x_stdout, "NA\n");
- ntlmssp_client_end(&client_ntlmssp_state);
+ ntlmssp_end(&client_ntlmssp_state);
return;
}
if (spnego.negTokenTarg.negResult == SPNEGO_ACCEPT_COMPLETED) {
x_fprintf(x_stdout, "AF\n");
- ntlmssp_client_end(&client_ntlmssp_state);
+ ntlmssp_end(&client_ntlmssp_state);
return;
}
- status = ntlmssp_client_update(client_ntlmssp_state,
+ status = ntlmssp_update(client_ntlmssp_state,
spnego.negTokenTarg.responseToken,
&request);
@@ -772,7 +823,7 @@ static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego)
nt_errstr(status)));
x_fprintf(x_stdout, "BH\n");
data_blob_free(&request);
- ntlmssp_client_end(&client_ntlmssp_state);
+ ntlmssp_end(&client_ntlmssp_state);
return;
}
@@ -798,7 +849,7 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
{
char *principal;
DATA_BLOB tkt, to_server;
- unsigned char session_key_krb5[16];
+ DATA_BLOB session_key_krb5;
SPNEGO_DATA reply;
char *reply_base64;
@@ -822,7 +873,7 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
spnego.negTokenInit.mechListMIC.length);
principal[spnego.negTokenInit.mechListMIC.length] = '\0';
- tkt = cli_krb5_get_ticket(principal, 0, session_key_krb5);
+ tkt = cli_krb5_get_ticket(principal, 0, &session_key_krb5);
if (tkt.data == NULL) {
@@ -845,9 +896,11 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
return True;
}
- tkt = cli_krb5_get_ticket(principal, 0, session_key_krb5);
+ tkt = cli_krb5_get_ticket(principal, 0, &session_key_krb5);
}
+ data_blob_free(&session_key_krb5);
+
ZERO_STRUCT(reply);
reply.type = SPNEGO_NEG_TOKEN_INIT;
@@ -896,7 +949,7 @@ static void manage_client_krb5_targ(SPNEGO_DATA spnego)
#endif
-static void manage_gss_spnego_client_request(enum squid_mode squid_mode,
+static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper_mode,
char *buf, int length)
{
DATA_BLOB request;
@@ -1000,7 +1053,7 @@ static void manage_gss_spnego_client_request(enum squid_mode squid_mode,
x_fprintf(x_stdout, "BH\n");
}
- ntlmssp_client_end(&client_ntlmssp_state);
+ ntlmssp_end(&client_ntlmssp_state);
goto out;
}
@@ -1029,7 +1082,7 @@ static void manage_gss_spnego_client_request(enum squid_mode squid_mode,
return;
}
-static void manage_squid_request(enum squid_mode squid_mode)
+static void manage_squid_request(enum stdio_helper_mode helper_mode, stdio_helper_function fn)
{
char buf[SQUID_BUFFER_SIZE+1];
int length;
@@ -1066,24 +1119,16 @@ static void manage_squid_request(enum squid_mode squid_mode)
return;
}
- if (squid_mode == SQUID_2_5_BASIC || squid_mode == SQUID_2_4_BASIC) {
- manage_squid_basic_request(squid_mode, buf, length);
- } else if (squid_mode == SQUID_2_5_NTLMSSP) {
- manage_squid_ntlmssp_request(squid_mode, buf, length);
- } else if (squid_mode == GSS_SPNEGO) {
- manage_gss_spnego_request(squid_mode, buf, length);
- } else if (squid_mode == GSS_SPNEGO_CLIENT) {
- manage_gss_spnego_client_request(squid_mode, buf, length);
- }
+ fn(helper_mode, buf, length);
}
-static void squid_stream(enum squid_mode squid_mode) {
+static void squid_stream(enum stdio_helper_mode stdio_mode, stdio_helper_function fn) {
/* initialize FDescs */
x_setbuf(x_stdout, NULL);
x_setbuf(x_stderr, NULL);
while(1) {
- manage_squid_request(squid_mode);
+ manage_squid_request(stdio_mode, fn);
}
}
@@ -2019,20 +2064,15 @@ enum {
}
if (helper_protocol) {
- if (strcmp(helper_protocol, "squid-2.5-ntlmssp")== 0) {
- squid_stream(SQUID_2_5_NTLMSSP);
- } else if (strcmp(helper_protocol, "squid-2.5-basic")== 0) {
- squid_stream(SQUID_2_5_BASIC);
- } else if (strcmp(helper_protocol, "squid-2.4-basic")== 0) {
- squid_stream(SQUID_2_4_BASIC);
- } else if (strcmp(helper_protocol, "gss-spnego")== 0) {
- squid_stream(GSS_SPNEGO);
- } else if (strcmp(helper_protocol, "gss-spnego-client") == 0) {
- squid_stream(GSS_SPNEGO_CLIENT);
- } else {
- x_fprintf(x_stderr, "unknown helper protocol [%s]\n", helper_protocol);
- exit(1);
+ int i;
+ for (i=0; i<NUM_HELPER_MODES; i++) {
+ if (strcmp(helper_protocol, stdio_helper_protocols[i].name) == 0) {
+ squid_stream(stdio_helper_protocols[i].mode, stdio_helper_protocols[i].fn);
+ exit(0);
+ }
}
+ x_fprintf(x_stderr, "unknown helper protocol [%s]\n", helper_protocol);
+ exit(1);
}
if (!opt_username) {
diff --git a/source/utils/pdbedit.c b/source/utils/pdbedit.c
index c69b1494694..d72634d78b5 100644
--- a/source/utils/pdbedit.c
+++ b/source/utils/pdbedit.c
@@ -489,7 +489,11 @@ static int delete_user_entry (struct pdb_context *in, const char *username)
return -1;
}
- return NT_STATUS_IS_OK(in->pdb_delete_sam_account (in, samaccount));
+ if (!NT_STATUS_IS_OK(in->pdb_delete_sam_account (in, samaccount))) {
+ fprintf (stderr, "Unable to delete user %s\n", username);
+ return -1;
+ }
+ return 0;
}
/*********************************************************
@@ -515,7 +519,12 @@ static int delete_machine_entry (struct pdb_context *in, const char *machinename
return -1;
}
- return NT_STATUS_IS_OK(in->pdb_delete_sam_account (in, samaccount));
+ if (!NT_STATUS_IS_OK(in->pdb_delete_sam_account (in, samaccount))) {
+ fprintf (stderr, "Unable to delete machine %s\n", name);
+ return -1;
+ }
+
+ return 0;
}
/*********************************************************
diff --git a/source/web/cgi.c b/source/web/cgi.c
index 49a8fa92de4..07e3ee38fbf 100644
--- a/source/web/cgi.c
+++ b/source/web/cgi.c
@@ -355,7 +355,8 @@ static BOOL cgi_handle_authorization(char *line)
}
err:
- cgi_setup_error("401 Bad Authorization", "",
+ cgi_setup_error("401 Bad Authorization",
+ "WWW-Authenticate: Basic realm=\"SWAT\"\r\n",
"username or password incorrect");
passwd_free(&pass);
diff --git a/source/web/diagnose.c b/source/web/diagnose.c
index efd6d1d0a19..46432c41f85 100644
--- a/source/web/diagnose.c
+++ b/source/web/diagnose.c
@@ -31,11 +31,7 @@ NSS_STATUS winbindd_request(int req_type,
BOOL winbindd_running(void)
{
-
- if (winbindd_request(WINBINDD_PING, NULL, NULL))
- return False;
-
- return True;
+ return winbind_ping();
}
#endif
diff --git a/source/web/swat.c b/source/web/swat.c
index f4046b46a26..1faef46e254 100644
--- a/source/web/swat.c
+++ b/source/web/swat.c
@@ -212,7 +212,11 @@ static void show_parameter(int snum, struct parm_struct *parm)
if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) {
char **list = *(char ***)ptr;
for (;*list;list++) {
- d_printf("%s%s", *list, ((*(list+1))?" ":""));
+ /* enclose in quotes if the string contains a space */
+ if ( strchr_m(*list, ' ') )
+ d_printf("\'%s\'%s", *list, ((*(list+1))?", ":""));
+ else
+ d_printf("%s%s", *list, ((*(list+1))?", ":""));
}
}
d_printf("\">");
@@ -221,7 +225,11 @@ static void show_parameter(int snum, struct parm_struct *parm)
if (parm->def.lvalue) {
char **list = (char **)(parm->def.lvalue);
for (; *list; list++) {
- d_printf("%s%s", *list, ((*(list+1))?" ":""));
+ /* enclose in quotes if the string contains a space */
+ if ( strchr_m(*list, ' ') )
+ d_printf("\'%s\'%s", *list, ((*(list+1))?", ":""));
+ else
+ d_printf("%s%s", *list, ((*(list+1))?", ":""));
}
}
d_printf("\'\">");
diff --git a/testsuite/build_farm/runlist b/testsuite/build_farm/runlist
index 5996f24ba89..594c172b6ff 100644
--- a/testsuite/build_farm/runlist
+++ b/testsuite/build_farm/runlist
@@ -1,6 +1,6 @@
TEST_ALL="basicsmb-sharelist basicsmb-local-pass-change \
basicsmb-sharesec basicsmb-usersec \
-basicsmb-serversec basicsmb-domainsec basicsmb-domainsec-nt4 \
+basicsmb-serversec \
basicsmb-shareguest basicsmb-hostsequiv basicsmb-invalidusers \
basicsmb-hostsdeny basicsmb-remote-pass-change \
basicsmb-preexec \
@@ -15,4 +15,4 @@ torture-RW1 torture-RW2 torture-OPEN torture-XCOPY \
torture-RENAME torture-DELETE torture-PROPERTIES \
torture-MANGLE torture-FDSESS"
-#basicsmb-serversec
+#basicsmb-domainsec basicsmb-domainsec-nt4 \ No newline at end of file