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).
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
##
sambaPwdCanChange $ sambaPwdMustChange $ sambaAcctFlags $
displayName $ sambaHomePath $ sambaHomeDrive $ sambaLogonScript $
sambaProfilePath $ description $ sambaUserWorkstations $
- sambaPrimaryGroupSID $ sambaDomainName ))
+ sambaPrimaryGroupSID $ sambaDomainName $ sambaMungedDial))
##
## Group mapping info
--- /dev/null
+/*
+ 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;
+}
# 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
# 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)
%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
#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}')
#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
%endif
Summary: Samba SMB server.
-Vendor: Samba Team
Name: %{pkg_name}%{samba_major}
%if %have_pre
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
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.
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.
%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
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
%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}"
#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}
#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
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
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}
#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
)
# 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
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
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
# 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
%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"
%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
%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
%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
# /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
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
%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
%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
%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*
%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}
%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
# 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
# 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
# =====================================
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
# 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
'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
;;
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
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) \
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.
@$(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@ \
# 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 #
# 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 #
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));
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));
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;
+ }
}
/***************************************************************************
#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;
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 */
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;
}
(*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);
}
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);
}
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];
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);
}
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];
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
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;
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)));
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;
}
}
nt_pw, &auth_context->challenge,
user_info->smb_name.str,
user_info->client_domain.str,
- user_sess_key)) {
+ NULL)) {
return NT_STATUS_OK;
}
nt_pw, &auth_context->challenge,
user_info->smb_name.str,
"",
- user_sess_key)) {
+ NULL)) {
return NT_STATUS_OK;
}
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)));
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... */
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;
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);
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;
}
{
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;
}
/****************************************************************************
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;
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;
(*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;
}
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);
;;
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)
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)
*)
CPPFLAGS="$CPPFLAGS -D_SYSV"
AC_DEFINE(_SYSV, 1, [Whether to enable System V compatibility])
- esac
+ esac
;;
#
# Tests needed for SINIX large file support.
#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
# 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"
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"
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)
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;
sid_copy(&map->sid, &sid);
}
+#endif
return True;
}
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"));
/*
* 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;
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;
/* 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;
/* 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.
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. */
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
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.
/* NTLMSSP message types */
enum NTLM_MESSAGE_TYPE
{
+ NTLMSSP_INITIAL = 0 /* samba internal state */,
NTLMSSP_NEGOTIATE = 1,
NTLMSSP_CHALLENGE = 2,
NTLMSSP_AUTH = 3,
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;
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];
Store it here, until we need it */
DATA_BLOB stored_response;
-} NTLMSSP_CLIENT_STATE;
+} NTLMSSP_STATE;
struct pdb_methods *methods;
struct user_data {
- /* initiailization flags */
+ /* initialization flags */
struct bitmap *change_flags;
struct bitmap *set_flags;
struct pdb_methods *methods;
struct group_data {
- /* initiailization flags */
+ /* initialization flags */
struct bitmap *change_flags;
struct bitmap *set_flags;
#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
} 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;
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 */
#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;
} 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)
}
}
-
/**
* Convert between character sets, allocating a new buffer using talloc for the result.
*
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;
}
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;
}
{
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;
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;
}
{
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");
{ LDAP_ATTR_DOMAIN, "sambaDomainName" },
{ LDAP_ATTR_OBJCLASS, "objectClass" },
{ LDAP_ATTR_ACB_INFO, "sambaAcctFlags" },
+ { LDAP_ATTR_MUNGED_DIAL, "sambaMungedDial" },
{ LDAP_ATTR_LIST_END, NULL }
};
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)
{
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++)) {
/* 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++;
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;
}
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;
}
#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;
}
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);
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;
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;
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);
}
/****************************************************************************
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
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;
}
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);
/* 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 */
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;
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)) {
}
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) {
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;
reply */
if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
data_blob_free(&blob);
- return False;
+ return NT_STATUS_INVALID_PARAMETER;
}
data_blob_free(&blob);
if (ret){
DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
- return False;
+ return NT_STATUS_LOGON_FAILURE;
}
}
/* 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 */
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;
}
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;
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)
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);
/*
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;
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;
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));
#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);
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};
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) {
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);
}
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);
}
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;
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);
}
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);
}
#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
*
*/
-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);
return chal;
}
+/**
+ * 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
}
}
+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
*
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);
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 = "";
}
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";
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
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,
&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));
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;
}
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;
(*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
*********************************************************************/
* @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",
ntlmssp_state->get_domain(),
ntlmssp_state->get_global_myname());
+ ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
+
return NT_STATUS_MORE_PROCESSING_REQUIRED;
}
* @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;
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",
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 {
}
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"));
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;
}
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);
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 {
/* 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);
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 */
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;
return NT_STATUS_NO_MEMORY;
}
+ (*ntlmssp_state)->role = NTLMSSP_CLIENT;
+
(*ntlmssp_state)->mem_ctx = mem_ctx;
(*ntlmssp_state)->get_global_myname = global_myname;
(*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 |
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;
-}
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)
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);
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 *);
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':
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)
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);
}
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 {
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);
*
*/
-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;
*
*/
-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;
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);
}
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);
*
*/
-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));
}
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);
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) {
#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);
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)) {
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;
/***********************************************************
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;
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",
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;
}
/***********************************************************
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;
+ }
}
/***********************************************************
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) {
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;
}
}
+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. */
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;
}
done:
/* cleanup */
if (cli) {
+ DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
cli_nt_session_close( cli );
cli_shutdown( cli );
}
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)
OPT_SET_AUTH_USER = 1000,
OPT_GET_AUTH_USER,
OPT_DOMAIN_NAME,
- OPT_SEQUENCE
+ OPT_SEQUENCE,
+ OPT_USERSIDS
};
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 },
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;
--- /dev/null
+/*
+ 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);
+}
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;
+}
{ WINBINDD_GETPWENT, winbindd_getpwent, "GETPWENT" },
{ WINBINDD_GETGROUPS, winbindd_getgroups, "GETGROUPS" },
+ { WINBINDD_GETUSERSIDS, winbindd_getusersids, "GETUSERSIDS" },
/* Group functions */
&& *(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;
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;
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 */
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;
+}
+
/* 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
};
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;
}
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);
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"));
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)) {
}
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
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);
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';
/* 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",
BOOL bPamPasswordChange;
BOOL bUnixPasswdSync;
BOOL bPasswdChatDebug;
+ int iPasswdChatTimeout;
BOOL bTimestampLogs;
BOOL bNTSmbSupport;
BOOL bNTPipeSupport;
BOOL bDebugPid;
BOOL bDebugUid;
BOOL bHostMSDfs;
- BOOL bHideLocalUsers;
BOOL bUnicode;
BOOL bUseMmap;
BOOL bHostnameLookups;
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);
* 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[] = {
{"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},
{"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},
{"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},
{"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},
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. */
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)
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)
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)
}
/***************************************************************************
- 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);
}
/***************************************************************************
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;
{
const char *guest_account = lp_guestaccount();
GROUP_MAP map;
+ BOOL ret;
if (!account_data || !pwd) {
return NT_STATUS_INVALID_PARAMETER;
}
/* 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;
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;
}
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();
pdb_free_sam(&sam_account);
return True;
}
- unbecome_root();
pdb_free_sam(&sam_account);
} 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
*/
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);
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];
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;
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); */
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),
{ 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}};
/**************************************************************************
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;
*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));
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...
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));
return True;
}
+ pjob->smbjob = jobid;
+
ret = (*(current_printif->job_submit))(snum, pjob);
if (ret)
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 */
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
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);
}
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)) {
/* 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;
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;
}
*/
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);
}
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)) {
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));
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))
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;
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);
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;
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);
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");
}
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)
{
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));
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;
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);
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))
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))
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;
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));
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;
}
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;
}
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;
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"));
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:
********************************************************************/
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"));
********************************************************************/
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"));
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;
{
UNISTR2* uni_path = &q_u->uni_path;
uint32 level = q_u->level;
+ int consumedcnt = sizeof(pstring);
pstring path;
struct junction_map jn;
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;
}
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;
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;
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;
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,
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;
* 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;
* 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;
/* 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);
}
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,
/*
* 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 ));
}
/*******************************************************************
- 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;
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;
}
{"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 },
uint32 group_entries = 0;
uint32 i;
TALLOC_CTX *mem_ctx = info->mem_ctx;
+ BOOL ret;
DEBUG(10,("load_group_domain_entries\n"));
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;
/*******************************************************************
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;
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;
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;
}
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;
}
}
- 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__));
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
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);
* 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);
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);
}
/*********************************************************************
- _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;
}
/*******************************************************************
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;
}
/*******************************************************************
fstring user_name;
uint32 grid;
uint32 tmp_rid;
+ BOOL ret;
*numgroups= 0;
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.
done:
*pgids=gids;
*numgroups=cur_gid;
- safe_free(map);
+ SAFE_FREE(map);
return True;
}
if (strequal(expected, "."))
return True;
- timeout = 2000;
+ /* Initial timeout. */
+ timeout = lp_passwd_chat_timeout() * 1000;
nread = 0;
buffer[nread] = 0;
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;
+ }
}
}
/*******************************************************************
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;
return(-1);
}
+ get_acl_group_bits(conn, fname, &st->st_mode);
+
if (S_ISDIR(st->st_mode))
dosmode |= aDIR;
else
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.");
}
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"));
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;
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;
}
/* -------------------------------------------------------------------- */
-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;
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) {
* ************************************************************************** **
*/
-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;
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('.'));
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)))
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 */
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;
}
/* 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.");
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) {
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;
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) : "" ));
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];
****************************************************************************/
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;
fsp->oplock_type = NO_OPLOCK;
errno = EPERM;
- pstrcpy(fname,fname1);
-
/* Check permissions */
/*
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
* @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;
}
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;
}
}
- 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,
} 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);
return True;
}
+/****************************************************************************
+ 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.
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);
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));
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;
}
/****************************************************************************
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);
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;
dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace)/ dp->bsize;
#endif
- return 0;
+ return ret;
}
/****************************************************************************
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);
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);
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);
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) {
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);
NTSTATUS nt_status;
BOOL doencrypt = global_encrypted_passwords_negotiated;
+
+ DATA_BLOB session_key;
START_PROFILE(SMBsesssetupX);
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);
+ }
}
}
ra_lanman_string( native_lanman );
}
-
+
if (SVAL(inbuf,smb_vwv4) == 0) {
setup_new_vc_session();
}
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) {
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) {
/* 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.");
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);
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)
return total;
}
-void nb_alarm(void)
+void nb_alarm(int ignore)
{
int i;
int lines=0, num_clients=0;
}
}
+#if 0
static int ne_find_handle(int handle)
{
int i;
}
return -1;
}
+#endif
static int find_handle(int handle)
{
{"GETDOMAINSID", net_getdomainsid},
{"MAXRID", net_maxrid},
{"IDMAP", net_idmap},
+ {"STATUS", net_status},
#ifdef WITH_FAKE_KASERVER
{"AFSKEY", net_afskey},
#endif
{
ADS_STRUCT *ads;
TALLOC_CTX *ctx;
- char *workgroup;
+ const char *workgroup;
if (!(ads = ads_startup())) return -1;
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];
{
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");
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"\
" 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"\
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");
ZERO_STRUCT(info3);
ctr.sam.info3 = &info3;
+ if (!global) break;
+
get_query_dispinfo_params(
loop_count, &max_entries, &max_size);
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);
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));
/* 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);
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));
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
{"add", rpc_group_add},
{"delete", rpc_group_delete},
#endif
+ {"list", rpc_group_list},
+ {"members", rpc_group_members},
{NULL, NULL}
};
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",
/* 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;
}
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
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);
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) &&
#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;
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;
}
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;
}
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;
} 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");
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);
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)));
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;
*pass='\0';
pass++;
- if (squid_mode == SQUID_2_5_BASIC) {
+ if (stdio_helper_mode == SQUID_2_5_BASIC) {
rfc1738_unescape(user);
rfc1738_unescape(pass);
}
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;
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) ) {
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;
}
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);
}
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"));
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. */
return;
}
- status = ntlmssp_server_update(ntlmssp_state,
+ status = ntlmssp_update(ntlmssp_state,
request.negTokenTarg.responseToken,
&response.negTokenTarg.responseToken);
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);
}
}
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)
{
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;
}
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;
}
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;
}
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;
}
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;
}
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);
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;
}
{
char *principal;
DATA_BLOB tkt, to_server;
- unsigned char session_key_krb5[16];
+ DATA_BLOB session_key_krb5;
SPNEGO_DATA reply;
char *reply_base64;
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) {
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;
#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;
x_fprintf(x_stdout, "BH\n");
}
- ntlmssp_client_end(&client_ntlmssp_state);
+ ntlmssp_end(&client_ntlmssp_state);
goto out;
}
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;
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);
}
}
}
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) {
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;
}
/*********************************************************
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;
}
/*********************************************************
}
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);
BOOL winbindd_running(void)
{
-
- if (winbindd_request(WINBINDD_PING, NULL, NULL))
- return False;
-
- return True;
+ return winbind_ping();
}
#endif
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("\">");
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("\'\">");
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 \
torture-RENAME torture-DELETE torture-PROPERTIES \
torture-MANGLE torture-FDSESS"
-#basicsmb-serversec
+#basicsmb-domainsec basicsmb-domainsec-nt4
\ No newline at end of file