summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs-xml/smbdotconf/security/forcecreatemode.xml17
-rwxr-xr-xpackaging/RHEL-CTDB/makerpms.sh7
-rw-r--r--packaging/RHEL-CTDB/samba.spec69
-rw-r--r--source3/Makefile.in3
-rw-r--r--source3/client/client.c12
-rw-r--r--source3/client/mount.cifs.c5
-rw-r--r--source3/configure.in90
-rw-r--r--source3/groupdb/mapping_ldb.c11
-rw-r--r--source3/include/ads.h25
-rw-r--r--source3/include/async_smb.h126
-rw-r--r--source3/include/client.h41
-rw-r--r--source3/include/doserr.h1
-rw-r--r--source3/include/includes.h2
-rw-r--r--source3/include/proto.h39
-rw-r--r--source3/include/rpc_client.h48
-rw-r--r--source3/lib/ldb/common/ldb.c2
-rw-r--r--source3/lib/netapi/examples/Makefile.in14
-rw-r--r--source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c43
-rw-r--r--source3/lib/netapi/examples/netdomjoin/netdomjoin.c4
-rw-r--r--source3/lib/netapi/examples/share/share_add.c110
-rw-r--r--source3/lib/netapi/examples/user/user_getgroups.c133
-rw-r--r--source3/lib/netapi/examples/user/user_getinfo.c149
-rw-r--r--source3/lib/netapi/examples/user/user_setinfo.c122
-rw-r--r--source3/lib/netapi/joindomain.c2
-rw-r--r--source3/lib/netapi/libnetapi.c98
-rw-r--r--source3/lib/netapi/libnetapi.h19
-rw-r--r--source3/lib/netapi/netapi.h194
-rw-r--r--source3/lib/netapi/share.c133
-rw-r--r--source3/lib/netapi/user.c919
-rw-r--r--source3/lib/time.c46
-rw-r--r--source3/libads/kerberos_keytab.c11
-rw-r--r--source3/libnet/libnet_join.c27
-rw-r--r--source3/libnet/libnet_keytab.c40
-rw-r--r--source3/librpc/gen_ndr/libnetapi.h92
-rw-r--r--source3/librpc/gen_ndr/ndr_libnetapi.c251
-rw-r--r--source3/librpc/gen_ndr/ndr_libnetapi.h69
-rw-r--r--source3/librpc/idl/libnetapi.idl95
-rw-r--r--source3/libsmb/async_smb.c697
-rw-r--r--source3/libsmb/clientgen.c166
-rw-r--r--source3/libsmb/clifile.c235
-rw-r--r--source3/libsmb/clikrb5.c42
-rw-r--r--source3/libsmb/clireadwrite.c129
-rw-r--r--source3/libsmb/doserr.c2
-rw-r--r--source3/libsmb/passchange.c22
-rw-r--r--source3/libsmb/samlogon_cache.c54
-rw-r--r--source3/nsswitch/libwbclient/wbc_pam.c271
-rw-r--r--source3/nsswitch/libwbclient/wbc_sid.c9
-rw-r--r--source3/nsswitch/libwbclient/wbclient.c2
-rw-r--r--source3/nsswitch/libwbclient/wbclient.h78
-rw-r--r--source3/nsswitch/wbinfo.c34
-rw-r--r--source3/passdb/lookup_sid.c42
-rw-r--r--source3/rpc_client/cli_pipe.c69
-rw-r--r--source3/rpc_client/ndr.c2
-rw-r--r--source3/rpc_parse/parse_prs.c26
-rw-r--r--source3/smbd/process.c2
-rw-r--r--source3/smbd/reply.c32
-rw-r--r--source3/torture/torture.c113
-rw-r--r--source3/utils/net_dom.c8
-rw-r--r--source3/utils/net_rpc.c492
-rw-r--r--source3/utils/net_rpc_shell.c9
-rw-r--r--source3/utils/smbpasswd.c42
-rw-r--r--source3/winbindd/winbindd_ads.c9
-rw-r--r--source3/winbindd/winbindd_cache.c23
-rw-r--r--source3/winbindd/winbindd_dual.c4
-rw-r--r--source3/winbindd/winbindd_pam.c4
65 files changed, 4322 insertions, 1365 deletions
diff --git a/docs-xml/smbdotconf/security/forcecreatemode.xml b/docs-xml/smbdotconf/security/forcecreatemode.xml
index 8a6449fe21..a3f1c2c105 100644
--- a/docs-xml/smbdotconf/security/forcecreatemode.xml
+++ b/docs-xml/smbdotconf/security/forcecreatemode.xml
@@ -2,17 +2,16 @@
context="S"
xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
<description>
- <para>This parameter specifies a set of UNIX mode bit
- permissions that will <emphasis>always</emphasis> be set on a
- file created by Samba. This is done by bitwise 'OR'ing these bits onto
- the mode bits of a file that is being created or having its
- permissions changed. The default for this parameter is (in octal)
- 000. The modes in this parameter are bitwise 'OR'ed onto the file
- mode after the mask set in the <parameter moreinfo="none">create mask</parameter>
+ <para>This parameter specifies a set of UNIX mode bit
+ permissions that will <emphasis>always</emphasis> be set on a
+ file created by Samba. This is done by bitwise 'OR'ing these bits onto
+ the mode bits of a file that is being created. The default for this parameter is (in octal)
+ 000. The modes in this parameter are bitwise 'OR'ed onto the file
+ mode after the mask set in the <parameter moreinfo="none">create mask</parameter>
parameter is applied.</para>
- <para>The example below would force all created files to have read and execute
- permissions set for 'group' and 'other' as well as the
+ <para>The example below would force all newly created files to have read and execute
+ permissions set for 'group' and 'other' as well as the
read/write/execute bits set for the 'user'.</para>
</description>
diff --git a/packaging/RHEL-CTDB/makerpms.sh b/packaging/RHEL-CTDB/makerpms.sh
index 8a0345bbeb..485c810bdb 100755
--- a/packaging/RHEL-CTDB/makerpms.sh
+++ b/packaging/RHEL-CTDB/makerpms.sh
@@ -21,9 +21,10 @@ SRCDIR=`rpm --eval %_sourcedir`
# At this point the SPECDIR and SRCDIR variables must have a value!
-VERSION='3.3.0'
-REVISION='ctdb'
+DIRNAME=$(dirname $0)
+
SPECFILE="samba.spec"
+VERSION=$(grep ^Version ${DIRNAME}/${SPECFILE} | sed -e 's/^Version:\ \+//')
DOCS="docs.tar.bz2"
RPMVER=`rpm --version | awk '{print $3}'`
RPM="rpmbuild"
@@ -41,8 +42,6 @@ case $RPMVER in
;;
esac
-DIRNAME=$(dirname $0)
-
pushd ${DIRNAME}/../..
echo -n "Creating samba-${VERSION}.tar.bz2 ... "
git archive --prefix=samba-${VERSION}/ HEAD | bzip2 > ${SRCDIR}/samba-${VERSION}.tar.bz2
diff --git a/packaging/RHEL-CTDB/samba.spec b/packaging/RHEL-CTDB/samba.spec
index 16340c6d4b..5f5edad05e 100644
--- a/packaging/RHEL-CTDB/samba.spec
+++ b/packaging/RHEL-CTDB/samba.spec
@@ -147,7 +147,8 @@ CFLAGS="$RPM_OPT_FLAGS $EXTRA -D_GNU_SOURCE" ./configure \
--prefix=%{_prefix} \
--localstatedir=/var \
--with-configdir=%{_sysconfdir}/samba \
- --with-libdir=%{_libarchdir}/samba \
+ --libdir=%{_libarchdir} \
+ --with-modulesdir=%{_libarchdir}/samba \
--with-lockdir=/var/lib/samba \
--with-logfilebase=/var/log/samba \
--with-mandir=%{_mandir} \
@@ -229,67 +230,21 @@ make DESTDIR=$RPM_BUILD_ROOT \
install
cd ..
-# pam_smbpass
-cp source/bin/pam_smbpass.so $RPM_BUILD_ROOT/%{_libarch}/security/pam_smbpass.so
-
# NSS & PAM winbind support
install -m 755 source/bin/pam_winbind.so $RPM_BUILD_ROOT/%{_libarch}/security/pam_winbind.so
-install -m 755 source/nsswitch/libnss_winbind.so $RPM_BUILD_ROOT/%{_libarch}/libnss_winbind.so
-#install -m 755 source/nsswitch/libnss_wins.so $RPM_BUILD_ROOT/%{_libarch}/libnss_wins.so
+install -m 755 source/nsswitch/libnss_winbind.so $RPM_BUILD_ROOT/%{_libarch}/libnss_winbind.so.2
( cd $RPM_BUILD_ROOT/%{_libarch};
- ln -sf libnss_winbind.so libnss_winbind.so.2 )
+ ln -sf libnss_winbind.so.2 libnss_winbind.so )
+#
+# do not install libnss_wins.so in order to reduce dependencies
+# (we do not need it for the samba-ctdb scenario)
+#
+#install -m 755 source/nsswitch/libnss_wins.so $RPM_BUILD_ROOT/%{_libarch}/libnss_wins.so
# ( cd $RPM_BUILD_ROOT/%{_libarch}; ln -sf libnss_wins.so libnss_wins.so.2 )
-# make install puts libsmbclient.so in the wrong place on x86_64
-rm -f $RPM_BUILD_ROOT/usr/lib*/samba/libsmbclient.so* $RPM_BUILD_ROOT/usr/lib*/samba/libsmbclient.a || true
-install -m 755 source/bin/libsmbclient.so.0 $RPM_BUILD_ROOT%{_libarchdir}/libsmbclient.so.0
-install -m 755 source/bin/libsmbclient.a $RPM_BUILD_ROOT%{_libarchdir}/libsmbclient.a
-install -m 644 source/include/libsmbclient.h $RPM_BUILD_ROOT%{_includedir}
-ln -s libsmbclient.so.0 $RPM_BUILD_ROOT%{_libarchdir}/libsmbclient.so
-
-# make install puts libmsrpc.so in the wrong place on x86_64
-#rm -f $RPM_BUILD_ROOT/usr/lib*/samba/libmsrpc.so $RPM_BUILD_ROOT/usr/lib*/samba/libmsrpc.a || true
-#install -m 755 source/bin/libmsrpc.so $RPM_BUILD_ROOT%{_libarchdir}/libmsrpc.so
-#install -m 755 source/bin/libmsrpc.a $RPM_BUILD_ROOT%{_libarchdir}/libmsrpc.a
-#install -m 644 source/include/libmsrpc.h $RPM_BUILD_ROOT%{_includedir}
-#rm -f $RPM_BUILD_ROOT%{_libarchdir}/samba/libmsrpc.*
-#ln -s /%{_libarchdir}/libmsrpc.so $RPM_BUILD_ROOT%{_libarchdir}/libmsrpc.so.0
-
-# make install puts libsmbsharemodes.so in the wrong place on x86_64
-rm -f $RPM_BUILD_ROOT/usr/lib*/samba/libsmbsharemodes.so* $RPM_BUILD_ROOT/usr/lib*/samba/libsmbsharemodes.a || true
-install -m 755 source/bin/libsmbsharemodes.so.0 $RPM_BUILD_ROOT%{_libarchdir}/libsmbsharemodes.so.0
-install -m 755 source/bin/libsmbsharemodes.a $RPM_BUILD_ROOT%{_libarchdir}/libsmbsharemodes.a
-install -m 644 source/include/smb_share_modes.h $RPM_BUILD_ROOT%{_includedir}
-rm -f $RPM_BUILD_ROOT%{_libarchdir}/samba/libsmbsharemodes.*
-ln -s libsmbsharemodes.so.0 $RPM_BUILD_ROOT%{_libarchdir}/libsmbsharemodes.so
-
# Install pam_smbpass.so
install -m755 source/bin/pam_smbpass.so $RPM_BUILD_ROOT/%{_libarch}/security/pam_smbpass.so
-# Put the shared libraries to their SONAME under /usr/lib{,64}
-# and create the proper .so symlinks
-#
-# libwbclient
-rm -f $RPM_BUILD_ROOT%{_libarchdir}/samba/libwbclient.so*
-install -m 755 source/bin/libwbclient.so.0 \
- $RPM_BUILD_ROOT%{_libarchdir}/libwbclient.so.0
-ln -s libwbclient.so.0 $RPM_BUILD_ROOT%{_libarchdir}/libwbclient.so
-# libtalloc
-rm -f $RPM_BUILD_ROOT%{_libarchdir}/samba/libtalloc.so*
-install -m 755 source/bin/libtalloc.so.1 \
- $RPM_BUILD_ROOT%{_libarchdir}/libtalloc.so.1
-ln -s libtalloc.so.1 $RPM_BUILD_ROOT%{_libarchdir}/libtalloc.so
-# libtdb
-rm -f $RPM_BUILD_ROOT%{_libarchdir}/samba/libtdb.so*
-install -m 755 source/bin/libtdb.so.1 \
- $RPM_BUILD_ROOT%{_libarchdir}/libtdb.so.1
-ln -s libtdb.so.1 $RPM_BUILD_ROOT%{_libarchdir}/libtdb.so
-# libnetapi
-rm -f $RPM_BUILD_ROOT%{_libarchdir}/samba/libnetapi.so*
-install -m 755 source/bin/libnetapi.so.0 \
- $RPM_BUILD_ROOT%{_libarchdir}/libnetapi.so.0
-ln -s libnetapi.so.0 $RPM_BUILD_ROOT%{_libarchdir}/libnetapi.so
-
## cleanup
/bin/rm -rf $RPM_BUILD_ROOT/usr/lib*/samba/security
@@ -552,6 +507,12 @@ exit 0
%{_mandir}/man8/net.8*
%{_mandir}/man7/pam_winbind.7*
%{_mandir}/man7/libsmbclient.7*
+%{_mandir}/man1/ldbadd.1*
+%{_mandir}/man1/ldbdel.1*
+%{_mandir}/man1/ldbedit.1*
+%{_mandir}/man1/ldbmodify.1*
+%{_mandir}/man1/ldbsearch.1*
+%{_mandir}/man8/cifs.upcall.8*
%ifarch i386 i486 i586 i686 ppc s390
%files winbind-32bit
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 486d47f5f8..5793b5ef4d 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -1835,7 +1835,8 @@ LIBNETAPI_OBJ0 = lib/netapi/netapi.o \
lib/netapi/group.o \
lib/netapi/localgroup.o \
lib/netapi/samr.o \
- lib/netapi/sid.o
+ lib/netapi/sid.o \
+ lib/netapi/share.o
LIBNETAPI_OBJ = $(LIBNETAPI_OBJ0) $(LIBNET_OBJ) \
$(LIBSMBCONF_OBJ) \
diff --git a/source3/client/client.c b/source3/client/client.c
index 18b286324b..85f653e903 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -943,6 +943,7 @@ static int cmd_echo(void)
TALLOC_CTX *ctx = talloc_tos();
char *num;
char *data;
+ NTSTATUS status;
if (!next_token_talloc(ctx, &cmd_ptr, &num, NULL)
|| !next_token_talloc(ctx, &cmd_ptr, &data, NULL)) {
@@ -950,9 +951,10 @@ static int cmd_echo(void)
return 1;
}
- if (!cli_echo(cli, atoi(num), (uint8 *)data, strlen(data))) {
- d_printf("echo failed: %s\n",
- nt_errstr(cli_get_nt_error(cli)));
+ status = cli_echo(cli, atoi(num), data_blob_const(data, strlen(data)));
+
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("echo failed: %s\n", nt_errstr(status));
return 1;
}
@@ -1078,7 +1080,7 @@ static int do_get(const char *rname, const char *lname_in, bool reget)
get_total_time_ms += this_time;
get_total_size += nread;
- DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n",
+ DEBUG(1,("(%3.1f KiloBytes/sec) (average %3.1f KiloBytes/sec)\n",
nread / (1.024*this_time + 1.0e-4),
get_total_size / (1.024*get_total_time_ms)));
}
@@ -4417,7 +4419,7 @@ static void readline_callback(void)
{
unsigned char garbage[16];
memset(garbage, 0xf0, sizeof(garbage));
- cli_echo(cli, 1, garbage, sizeof(garbage));
+ cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage)));
}
}
diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c
index dd878aa07b..9d2b449195 100644
--- a/source3/client/mount.cifs.c
+++ b/source3/client/mount.cifs.c
@@ -196,7 +196,7 @@ static int open_cred_file(char * file_name)
line_buf = (char *)malloc(4096);
if(line_buf == NULL) {
fclose(fs);
- return -ENOMEM;
+ return ENOMEM;
}
while(fgets(line_buf,4096,fs)) {
@@ -537,7 +537,8 @@ static int parse_options(char ** optionsp, int * filesys_flags)
if (value && *value) {
rc = open_cred_file(value);
if(rc) {
- printf("error %d opening credential file %s\n",rc, value);
+ printf("error %d (%s) opening credential file %s\n",
+ rc, strerror(rc), value);
return 1;
}
} else {
diff --git a/source3/configure.in b/source3/configure.in
index 9436fed1ff..bc5a827b8c 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -1354,6 +1354,96 @@ if test x"$samba_cv_stat_hires_notimespec" = x"yes" ; then
[whether struct stat has sub-second timestamps without struct timespec])
fi
+AC_CACHE_CHECK([whether struct stat has st_birthtimespec], samba_cv_stat_st_birthtimespec,
+ [
+ AC_TRY_COMPILE(
+ [
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+ ],
+ [
+ struct timespec t;
+ struct stat s = {0};
+ t = s.st_birthtimespec;
+ ],
+ samba_cv_stat_st_birthtimespec=yes, samba_cv_stat_birthtimespec=no)
+ ])
+
+if test x"$samba_cv_stat_st_birthtimespec" = x"yes" ; then
+ AC_DEFINE(HAVE_STAT_ST_BIRTHTIMESPEC, 1, [whether struct stat contains st_birthtimespec])
+fi
+
+AC_CACHE_CHECK([whether struct stat has st_birthtimensec], samba_cv_stat_st_birthtimensec,
+ [
+ AC_TRY_COMPILE(
+ [
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+ ],
+ [
+ struct timespec t;
+ struct stat s = {0};
+ t.tv_nsec = s.st_birthtimensec;
+ ],
+ samba_cv_stat_st_birthtimensec=yes, samba_cv_stat_birthtimensec=no)
+ ])
+
+if test x"$samba_cv_stat_st_birthtimensec" = x"yes" ; then
+ AC_DEFINE(HAVE_STAT_ST_BIRTHTIMENSEC, 1, [whether struct stat contains st_birthtimensec])
+fi
+
+AC_CACHE_CHECK([whether struct stat has st_birthtime], samba_cv_stat_st_birthtime,
+ [
+ AC_TRY_COMPILE(
+ [
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+ ],
+ [
+ struct time_t t;
+ struct stat s = {0};
+ t = s.st_birthtime;
+ ],
+ samba_cv_stat_st_birthtime=yes, samba_cv_stat_birthtime=no)
+ ])
+
+if test x"$samba_cv_stat_st_birthtime" = x"yes" ; then
+ AC_DEFINE(HAVE_STAT_ST_BIRTHTIME, 1, [whether struct stat contains st_birthtime])
+fi
+
#####################################
# needed for SRV lookups
AC_CHECK_LIB(resolv, dn_expand)
diff --git a/source3/groupdb/mapping_ldb.c b/source3/groupdb/mapping_ldb.c
index 6775f612e7..7ce879fb6e 100644
--- a/source3/groupdb/mapping_ldb.c
+++ b/source3/groupdb/mapping_ldb.c
@@ -60,6 +60,9 @@ static bool init_group_mapping(void)
ldb = ldb_init(NULL);
if (ldb == NULL) goto failed;
+ /* Ensure this db is created read/write for root only. */
+ ldb_set_create_perms(ldb, 0600);
+
existed = file_exist(db_path, NULL);
if (lp_parm_bool(-1, "groupmap", "nosync", False)) {
@@ -74,7 +77,13 @@ static bool init_group_mapping(void)
if (ret != LDB_SUCCESS) {
goto failed;
}
-
+
+ /* force the permissions on the ldb to 0600 - this will fix
+ existing databases as well as new ones */
+ if (chmod(db_path, 0600) != 0) {
+ goto failed;
+ }
+
if (!existed) {
/* initialise the ldb with an index */
struct ldb_ldif *ldif;
diff --git a/source3/include/ads.h b/source3/include/ads.h
index 0d464b2d81..97faf0b6eb 100644
--- a/source3/include/ads.h
+++ b/source3/include/ads.h
@@ -372,9 +372,30 @@ typedef struct {
krb5_addresses *addrs;
#else
#error UNKNOWN_KRB5_ADDRESS_TYPE
-#endif
+#endif /* defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) */
} smb_krb5_addresses;
-#endif
+
+#ifdef HAVE_KRB5_KEYBLOCK_KEYVALUE /* Heimdal */
+#define KRB5_KEY_TYPE(k) ((k)->keytype)
+#define KRB5_KEY_LENGTH(k) ((k)->keyvalue.length)
+#define KRB5_KEY_DATA(k) ((k)->keyvalue.data)
+#define KRB5_KEY_DATA_CAST void
+#else /* MIT */
+#define KRB5_KEY_TYPE(k) ((k)->enctype)
+#define KRB5_KEY_LENGTH(k) ((k)->length)
+#define KRB5_KEY_DATA(k) ((k)->contents)
+#define KRB5_KEY_DATA_CAST krb5_octet
+#endif /* HAVE_KRB5_KEYBLOCK_KEYVALUE */
+
+#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEY /* MIT */
+#define KRB5_KT_KEY(k) (&(k)->key)
+#elif HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */
+#define KRB5_KT_KEY(k) (&(k)->keyblock)
+#else
+#error krb5_keytab_entry has no key or keyblock member
+#endif /* HAVE_KRB5_KEYTAB_ENTRY_KEY */
+
+#endif /* HAVE_KRB5 */
enum ads_extended_dn_flags {
ADS_EXTENDED_DN_HEX_STRING = 0,
diff --git a/source3/include/async_smb.h b/source3/include/async_smb.h
index 19408be74b..e9e10023e3 100644
--- a/source3/include/async_smb.h
+++ b/source3/include/async_smb.h
@@ -17,23 +17,117 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#ifndef __ASYNC_SMB_H__
+#define __ASYNC_SMB_H__
+
#include "includes.h"
-/*
- * Create a fresh async smb request
+/**
+ * struct cli_request is the state holder for an async client request we sent
+ * to the server. It can consist of more than one struct async_req that we
+ * have to server if the application did a cli_chain_cork() and
+ * cli_chain_uncork()
*/
-struct async_req *cli_request_new(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli,
- uint8_t num_words, size_t num_bytes,
- struct cli_request **preq);
+struct cli_request {
+ /**
+ * "prev" and "next" form the doubly linked list in
+ * cli_state->outstanding_requests
+ */
+ struct cli_request *prev, *next;
+
+ /**
+ * num_async: How many chained requests do we serve?
+ */
+ int num_async;
+
+ /**
+ * async: This is the list of chained requests that were queued up by
+ * cli_request_chain before we sent out this request
+ */
+ struct async_req **async;
+
+ /**
+ * The client connection for this request
+ */
+ struct cli_state *cli;
+
+ /**
+ * The enc_state to decrypt the reply
+ */
+ struct smb_trans_enc_state *enc_state;
+
+ /**
+ * The mid we used for this request. Mainly used to demultiplex on
+ * receiving replies.
+ */
+ uint16_t mid;
+
+ /**
+ * The bytes we have to ship to the server
+ */
+ char *outbuf;
+
+ /**
+ * How much from "outbuf" did we already send
+ */
+ size_t sent;
+
+ /**
+ * The reply comes in here. Its intended size is implicit by
+ * smb_len(), its current size can be read via talloc_get_size()
+ */
+ char *inbuf;
+
+ /**
+ * Specific requests might add stuff here. Maybe convert this to a
+ * private_pointer at some point.
+ */
+ union {
+ struct {
+ off_t ofs;
+ size_t size;
+ ssize_t received;
+ uint8_t *rcvbuf;
+ } read;
+ struct {
+ DATA_BLOB data;
+ uint16_t num_echos;
+ } echo;
+ } data;
+
+ /**
+ * For requests that don't follow the strict request/reply pattern
+ * such as the transaction request family and echo requests it is
+ * necessary to break the standard procedure in
+ * handle_incoming_pdu(). For a simple example look at
+ * cli_echo_recv_helper().
+ */
+ struct {
+ void (*fn)(struct async_req *req);
+ void *priv;
+ } recv_helper;
+};
/*
- * Convenience function to get the SMB part out of an async_req
+ * Ship a new smb request to the server
*/
-struct cli_request *cli_request_get(struct async_req *req);
+struct async_req *cli_request_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ uint8_t smb_command,
+ uint8_t additional_flags,
+ uint8_t wct, const uint16_t *vwv,
+ uint16_t num_bytes, const uint8_t *bytes);
+
+bool cli_chain_cork(struct cli_state *cli, struct event_context *ev,
+ size_t size_hint);
+void cli_chain_uncork(struct cli_state *cli);
+
+NTSTATUS cli_pull_reply(struct async_req *req,
+ uint8_t *pwct, uint16_t **pvwv,
+ uint16_t *pnum_bytes, uint8_t **pbytes);
/*
* Fetch an error out of a NBT packet
@@ -47,16 +141,4 @@ NTSTATUS cli_pull_error(char *buf);
void cli_set_error(struct cli_state *cli, NTSTATUS status);
-/*
- * Create a temporary event context for use in the sync helper functions
- */
-
-struct cli_tmp_event *cli_tmp_event_ctx(TALLOC_CTX *mem_ctx,
- struct cli_state *cli);
-
-/*
- * Attach an event context permanently to a cli_struct
- */
-
-NTSTATUS cli_add_event_ctx(struct cli_state *cli,
- struct event_context *event_ctx);
+#endif
diff --git a/source3/include/client.h b/source3/include/client.h
index 51ced9907f..9b564fc48e 100644
--- a/source3/include/client.h
+++ b/source3/include/client.h
@@ -204,35 +204,28 @@ struct cli_state {
bool force_dos_errors;
bool case_sensitive; /* False by default. */
- struct event_context *event_ctx;
+ /**
+ * fd_event is around while we have async requests outstanding or are
+ * building a chained request.
+ *
+ * (fd_event!=NULL) &&
+ * ((outstanding_request!=NULL)||(chain_accumulator!=NULL))
+ *
+ * should always be true, as well as the reverse: If both cli_request
+ * pointers are NULL, no fd_event is around.
+ */
struct fd_event *fd_event;
char *evt_inbuf;
+ /**
+ * A linked list of requests that are waiting for a reply
+ */
struct cli_request *outstanding_requests;
-};
-
-struct cli_request {
- struct cli_request *prev, *next;
- struct async_req *async;
-
- struct cli_state *cli;
-
- struct smb_trans_enc_state *enc_state;
- uint16_t mid;
-
- char *outbuf;
- size_t sent;
- char *inbuf;
-
- union {
- struct {
- off_t ofs;
- size_t size;
- ssize_t received;
- uint8_t *rcvbuf;
- } read;
- } data;
+ /**
+ * The place to build up the list of chained requests.
+ */
+ struct cli_request *chain_accumulator;
};
typedef struct file_info {
diff --git a/source3/include/doserr.h b/source3/include/doserr.h
index 9dd20e87e7..c901df28e4 100644
--- a/source3/include/doserr.h
+++ b/source3/include/doserr.h
@@ -214,6 +214,7 @@
#define WERR_GROUP_EXISTS W_ERROR(1318)
#define WERR_MEMBER_IN_GROUP W_ERROR(1320)
#define WERR_USER_NOT_IN_GROUP W_ERROR(1321)
+#define WERR_WRONG_PASSWORD W_ERROR(1323)
#define WERR_PASSWORD_RESTRICTION W_ERROR(1325)
#define WERR_LOGON_FAILURE W_ERROR(1326)
#define WERR_NO_SUCH_DOMAIN W_ERROR(1355)
diff --git a/source3/include/includes.h b/source3/include/includes.h
index fa385cba2a..958e7cba1f 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -1234,7 +1234,7 @@ krb5_error_code smb_krb5_mk_error(krb5_context context,
krb5_error_code error_code,
const krb5_principal server,
krb5_data *reply);
-krb5_enctype smb_get_enctype_from_kt_entry(const krb5_keytab_entry *kt_entry);
+krb5_enctype smb_get_enctype_from_kt_entry(krb5_keytab_entry *kt_entry);
krb5_error_code smb_krb5_enctype_to_string(krb5_context context,
krb5_enctype enctype,
char **etype_s);
diff --git a/source3/include/proto.h b/source3/include/proto.h
index d757b2db80..a81375c2db 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -1185,7 +1185,6 @@ void srv_put_dos_date2(char *buf,int offset, time_t unixdate);
void srv_put_dos_date3(char *buf,int offset,time_t unixdate);
void put_long_date_timespec(char *p, struct timespec ts);
void put_long_date(char *p, time_t t);
-time_t get_create_time(const SMB_STRUCT_STAT *st,bool fake_dirs);
struct timespec get_create_timespec(const SMB_STRUCT_STAT *st,bool fake_dirs);
struct timespec get_atimespec(const SMB_STRUCT_STAT *pst);
void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts);
@@ -4202,21 +4201,6 @@ bool asn1_write_enumerated(ASN1_DATA *data, uint8 v);
bool ber_write_OID_String(DATA_BLOB *blob, const char *OID);
bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, const char **OID);
-/* The following definitions come from libsmb/async_smb.c */
-
-NTSTATUS cli_pull_error(char *buf);
-void cli_set_error(struct cli_state *cli, NTSTATUS status);
-struct async_req *cli_request_new(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli,
- uint8_t num_words, size_t num_bytes,
- struct cli_request **preq);
-struct cli_request *cli_request_get(struct async_req *req);
-struct cli_tmp_event *cli_tmp_event_ctx(TALLOC_CTX *mem_ctx,
- struct cli_state *cli);
-NTSTATUS cli_add_event_ctx(struct cli_state *cli,
- struct event_context *event_ctx);
-
/* The following definitions come from libsmb/cliconnect.c */
ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
@@ -4354,8 +4338,11 @@ void cli_sockopt(struct cli_state *cli, const char *options);
uint16 cli_setpid(struct cli_state *cli, uint16 pid);
bool cli_set_case_sensitive(struct cli_state *cli, bool case_sensitive);
bool cli_send_keepalive(struct cli_state *cli);
-bool cli_echo(struct cli_state *cli, uint16 num_echos,
- unsigned char *data, size_t length);
+struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli, uint16_t num_echos,
+ DATA_BLOB data);
+NTSTATUS cli_echo_recv(struct async_req *req);
+NTSTATUS cli_echo(struct cli_state *cli, uint16_t num_echos, DATA_BLOB data);
/* The following definitions come from libsmb/clierror.c */
@@ -4394,7 +4381,14 @@ int cli_nt_create_full(struct cli_state *cli, const char *fname,
uint32 CreateDisposition, uint32 CreateOptions,
uint8 SecuityFlags);
int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess);
+struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli,
+ const char *fname, int flags, int share_mode);
+NTSTATUS cli_open_recv(struct async_req *req, int *fnum);
int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode);
+struct async_req *cli_close_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli, int fnum);
+NTSTATUS cli_close_recv(struct async_req *req);
bool cli_close(struct cli_state *cli, int fnum);
bool cli_ftruncate(struct cli_state *cli, int fnum, uint64_t size);
NTSTATUS cli_locktype(struct cli_state *cli, int fnum,
@@ -4628,11 +4622,14 @@ int cli_NetConnectionEnum(struct cli_state *cli, const char *qualifier,
/* The following definitions come from libsmb/clireadwrite.c */
struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
struct cli_state *cli, int fnum,
off_t offset, size_t size);
NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received,
uint8_t **rcvbuf);
-struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli,
+struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
uint16_t fnum, off_t start_offset,
SMB_OFF_T size, size_t window_size,
NTSTATUS (*sink)(char *buf, size_t n,
@@ -5003,7 +5000,7 @@ void pwd_get_cleartext(struct pwd_info *pwd, fstring clr);
bool netsamlogon_cache_init(void);
bool netsamlogon_cache_shutdown(void);
-void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, struct netr_SamInfo3 *info3);
+void netsamlogon_clear_cached_user(struct netr_SamInfo3 *info3);
bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3);
struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid);
bool netsamlogon_cache_have(const DOM_SID *user_sid);
@@ -7829,6 +7826,8 @@ uint32 prs_data_size(prs_struct *ps);
uint32 prs_offset(prs_struct *ps);
bool prs_set_offset(prs_struct *ps, uint32 offset);
bool prs_append_prs_data(prs_struct *dst, prs_struct *src);
+bool prs_append_some_data(prs_struct *dst, void *src_base, uint32_t start,
+ uint32_t len);
bool prs_append_some_prs_data(prs_struct *dst, prs_struct *src, int32 start, uint32 len);
bool prs_copy_data_in(prs_struct *dst, const char *src, uint32 len);
bool prs_copy_data_out(char *dst, prs_struct *src, uint32 len);
diff --git a/source3/include/rpc_client.h b/source3/include/rpc_client.h
index d1af6f958d..684044b871 100644
--- a/source3/include/rpc_client.h
+++ b/source3/include/rpc_client.h
@@ -42,54 +42,6 @@
/* macro to expand cookie-cutter code in cli_xxx() using rpc_api_pipe_req() */
-#define CLI_DO_RPC_INTERNAL( pcli, ctx, interface, opnum, q_in, r_out, \
- q_ps, r_ps, q_io_fn, r_io_fn, default_error, copy_sess_key ) \
-{\
- SMB_ASSERT(ndr_syntax_id_equal(&pcli->abstract_syntax, interface)); \
- if (!prs_init( &q_ps, RPC_MAX_PDU_FRAG_LEN, ctx, MARSHALL )) { \
- return NT_STATUS_NO_MEMORY;\
- }\
- prs_init_empty( &r_ps, ctx, UNMARSHALL );\
- if ( copy_sess_key) prs_set_session_key(&q_ps, (const char *)pcli->dc->sess_key);\
- if ( q_io_fn("", &q_in, &q_ps, 0) ) {\
- NTSTATUS _smb_pipe_stat_ = rpc_api_pipe_req(pcli, opnum, &q_ps, &r_ps); \
- if (!NT_STATUS_IS_OK(_smb_pipe_stat_)) {\
- prs_mem_free( &q_ps );\
- prs_mem_free( &r_ps );\
- return _smb_pipe_stat_;\
- }\
- if ( copy_sess_key ) prs_set_session_key(&r_ps, (const char *)pcli->dc->sess_key);\
- if (!r_io_fn("", &r_out, &r_ps, 0)) {\
- prs_mem_free( &q_ps );\
- prs_mem_free( &r_ps );\
- return default_error;\
- }\
- } else {\
- prs_mem_free( &q_ps );\
- prs_mem_free( &r_ps );\
- return default_error;\
- }\
- prs_mem_free( &q_ps );\
- prs_mem_free( &r_ps );\
-}
-
-#define CLI_DO_RPC_COPY_SESS_KEY( pcli, ctx, p_idx, opnum, q_in, r_out, \
- q_ps, r_ps, q_io_fn, r_io_fn, default_error ) \
-{\
- CLI_DO_RPC_INTERNAL( pcli, ctx, p_idx, opnum, q_in, r_out, \
- q_ps, r_ps, q_io_fn, r_io_fn, default_error, True ); \
-}
-
-#define CLI_DO_RPC( pcli, ctx, p_idx, opnum, q_in, r_out, \
- q_ps, r_ps, q_io_fn, r_io_fn, default_error ) \
-{\
- CLI_DO_RPC_INTERNAL( pcli, ctx, p_idx, opnum, q_in, r_out, \
- q_ps, r_ps, q_io_fn, r_io_fn, default_error, False ); \
-}
-
-
-/* Arrrgg. Same but with WERRORS. Needed for registry code. */
-
#define CLI_DO_RPC_WERR( pcli, ctx, interface, opnum, q_in, r_out, \
q_ps, r_ps, q_io_fn, r_io_fn, default_error ) \
{\
diff --git a/source3/lib/ldb/common/ldb.c b/source3/lib/ldb/common/ldb.c
index e469c49399..743711b967 100644
--- a/source3/lib/ldb/common/ldb.c
+++ b/source3/lib/ldb/common/ldb.c
@@ -51,7 +51,7 @@ struct ldb_context *ldb_init(void *mem_ctx)
}
ldb_set_utf8_default(ldb);
- ldb_set_create_perms(ldb, 0666);
+ ldb_set_create_perms(ldb, 0600);
return ldb;
}
diff --git a/source3/lib/netapi/examples/Makefile.in b/source3/lib/netapi/examples/Makefile.in
index 0b7553c389..d48457a694 100644
--- a/source3/lib/netapi/examples/Makefile.in
+++ b/source3/lib/netapi/examples/Makefile.in
@@ -31,6 +31,7 @@ PROGS = bin/getdc@EXEEXT@ \
bin/user_setinfo@EXEEXT@ \
bin/user_modalsget@EXEEXT@ \
bin/user_modalsset@EXEEXT@ \
+ bin/user_getgroups@EXEEXT@ \
bin/group_add@EXEEXT@ \
bin/group_del@EXEEXT@ \
bin/group_enum@EXEEXT@ \
@@ -48,7 +49,8 @@ PROGS = bin/getdc@EXEEXT@ \
bin/localgroup_delmembers@EXEEXT@ \
bin/localgroup_setmembers@EXEEXT@ \
bin/localgroup_getmembers@EXEEXT@ \
- bin/remote_tod@EXEEXT@
+ bin/remote_tod@EXEEXT@ \
+ bin/share_add@EXEEXT@
all: $(PROGS)
@@ -91,6 +93,7 @@ USERGETINFO_OBJ = user/user_getinfo.o $(CMDLINE_OBJ)
USERSETINFO_OBJ = user/user_setinfo.o $(CMDLINE_OBJ)
USERMODALSGET_OBJ = user/user_modalsget.o $(CMDLINE_OBJ)
USERMODALSSET_OBJ = user/user_modalsset.o $(CMDLINE_OBJ)
+USERGETGROUPS_OBJ = user/user_getgroups.o $(CMDLINE_OBJ)
GROUPADD_OBJ = group/group_add.o $(CMDLINE_OBJ)
GROUPDEL_OBJ = group/group_del.o $(CMDLINE_OBJ)
GROUPENUM_OBJ = group/group_enum.o $(CMDLINE_OBJ)
@@ -109,6 +112,7 @@ LOCALGROUPDELMEMBERS_OBJ = localgroup/localgroup_delmembers.o $(CMDLINE_OBJ)
LOCALGROUPSETMEMBERS_OBJ = localgroup/localgroup_setmembers.o $(CMDLINE_OBJ)
LOCALGROUPGETMEMBERS_OBJ = localgroup/localgroup_getmembers.o $(CMDLINE_OBJ)
REMOTETOD_OBJ = server/remote_tod.o $(CMDLINE_OBJ)
+SHAREADD_OBJ = share/share_add.o $(CMDLINE_OBJ)
bin/getdc@EXEEXT@: $(BINARY_PREREQS) $(GETDC_OBJ)
@echo Linking $@
@@ -166,6 +170,10 @@ bin/user_modalsset@EXEEXT@: $(BINARY_PREREQS) $(USERMODALSSET_OBJ)
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(USERMODALSSET_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+bin/user_getgroups@EXEEXT@: $(BINARY_PREREQS) $(USERGETGROUPS_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(USERGETGROUPS_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
bin/group_add@EXEEXT@: $(BINARY_PREREQS) $(GROUPADD_OBJ)
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(GROUPADD_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
@@ -238,6 +246,10 @@ bin/remote_tod@EXEEXT@: $(BINARY_PREREQS) $(REMOTETOD_OBJ)
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(REMOTETOD_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+bin/share_add@EXEEXT@: $(BINARY_PREREQS) $(SHAREADD_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(SHAREADD_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
clean:
-rm -f $(PROGS)
-rm -f core */*~ *~ \
diff --git a/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c b/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c
index 418b9c8b8e..4e0488ed59 100644
--- a/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c
+++ b/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c
@@ -38,11 +38,6 @@
#define SAMBA_IMAGE_PATH "/usr/share/pixmaps/samba/logo.png"
#define SAMBA_IMAGE_PATH_SMALL "/usr/share/pixmaps/samba/logo-small.png"
-#define WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED ( 0x00000020 )
-#define WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE ( 0x00000004 )
-#define WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE ( 0x00000002 )
-#define WKSSVC_JOIN_FLAGS_JOIN_TYPE ( 0x00000001 )
-
#define NetSetupWorkgroupName ( 2 )
#define NetSetupDomainName ( 3 )
@@ -631,9 +626,9 @@ static void callback_do_join(GtkWidget *widget,
if (state->name_type_new == NetSetupDomainName) {
domain_join = TRUE;
join_creds_required = TRUE;
- join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
- WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
- WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED; /* for testing */
+ join_flags = NETSETUP_JOIN_DOMAIN |
+ NETSETUP_ACCT_CREATE |
+ NETSETUP_DOMAIN_JOIN_IF_JOINED; /* for testing */
}
if ((state->name_type_initial == NetSetupDomainName) &&
@@ -641,8 +636,8 @@ static void callback_do_join(GtkWidget *widget,
try_unjoin = TRUE;
unjoin_creds_required = TRUE;
join_creds_required = FALSE;
- unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
- WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
+ unjoin_flags = NETSETUP_JOIN_DOMAIN |
+ NETSETUP_ACCT_DELETE;
}
if (try_unjoin) {
@@ -823,9 +818,13 @@ static void callback_enter_hostname_and_unlock(GtkWidget *widget,
}
state->hostname_changed = TRUE;
if (state->name_type_initial == NetSetupDomainName) {
- asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain);
+ if (asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain) == -1) {
+ return;
+ }
} else {
- asprintf(&str, "%s.", entry_text);
+ if (asprintf(&str, "%s.", entry_text) == -1) {
+ return;
+ }
}
gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), str);
free(str);
@@ -1132,10 +1131,14 @@ static void callback_do_change(GtkWidget *widget,
char *str = NULL;
entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
if (state->name_type_initial == NetSetupDomainName) {
- asprintf(&str, "%s.%s", entry_text,
- state->my_dnsdomain);
+ if (asprintf(&str, "%s.%s", entry_text,
+ state->my_dnsdomain) == -1) {
+ return;
+ }
} else {
- asprintf(&str, "%s.", entry_text);
+ if (asprintf(&str, "%s.", entry_text) == -1) {
+ return;
+ }
}
gtk_label_set_text(GTK_LABEL(state->label_full_computer_name),
str);
@@ -1436,10 +1439,14 @@ static int draw_main_window(struct join_state *state)
/* Label */
char *str = NULL;
if (state->name_type_initial == NetSetupDomainName) {
- asprintf(&str, "%s.%s", state->my_hostname,
- state->my_dnsdomain);
+ if (asprintf(&str, "%s.%s", state->my_hostname,
+ state->my_dnsdomain) == -1) {
+ return -1;
+ }
} else {
- asprintf(&str, "%s.", state->my_hostname);
+ if (asprintf(&str, "%s.", state->my_hostname) == -1) {
+ return -1;
+ }
}
label = gtk_label_new(str);
diff --git a/source3/lib/netapi/examples/netdomjoin/netdomjoin.c b/source3/lib/netapi/examples/netdomjoin/netdomjoin.c
index bd7c36382a..08ce71b938 100644
--- a/source3/lib/netapi/examples/netdomjoin/netdomjoin.c
+++ b/source3/lib/netapi/examples/netdomjoin/netdomjoin.c
@@ -39,7 +39,9 @@ int main(int argc, const char **argv)
const char *account_ou = NULL;
const char *account = NULL;
const char *password = NULL;
- uint32_t join_flags = 0x00000023;
+ uint32_t join_flags = NETSETUP_JOIN_DOMAIN |
+ NETSETUP_ACCT_CREATE |
+ NETSETUP_DOMAIN_JOIN_IF_JOINED;
struct libnetapi_ctx *ctx = NULL;
poptContext pc;
diff --git a/source3/lib/netapi/examples/share/share_add.c b/source3/lib/netapi/examples/share/share_add.c
new file mode 100644
index 0000000000..3d7948840d
--- /dev/null
+++ b/source3/lib/netapi/examples/share/share_add.c
@@ -0,0 +1,110 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetShareAdd query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *sharename = NULL;
+ const char *path = NULL;
+ uint32_t level = 0;
+ uint32_t parm_err = 0;
+
+ struct SHARE_INFO_2 i2;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("share_add", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname sharename path");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ sharename = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ path = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetShareAdd */
+
+ i2.shi2_netname = sharename;
+ i2.shi2_type = 0;
+ i2.shi2_remark = "Test share created via NetApi";
+ i2.shi2_permissions = 0;
+ i2.shi2_max_uses = (uint32_t)-1;
+ i2.shi2_current_uses = 0;
+ i2.shi2_path = path;
+ i2.shi2_passwd = NULL;
+
+ status = NetShareAdd(hostname,
+ 2,
+ (uint8_t *)&i2,
+ &parm_err);
+ if (status != 0) {
+ printf("NetShareAdd failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/user/user_getgroups.c b/source3/lib/netapi/examples/user/user_getgroups.c
new file mode 100644
index 0000000000..939415e0eb
--- /dev/null
+++ b/source3/lib/netapi/examples/user/user_getgroups.c
@@ -0,0 +1,133 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserGetGroups query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *username = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ int i;
+
+ struct GROUP_USERS_INFO_0 *info0 = NULL;
+ struct GROUP_USERS_INFO_1 *info1 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_getgroups", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname username level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetUserGetGroups */
+
+ do {
+ status = NetUserGetGroups(hostname,
+ username,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+
+ switch (level) {
+ case 0:
+ info0 = (struct GROUP_USERS_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct GROUP_USERS_INFO_1 *)buffer;
+ break;
+ default:
+ break;
+ }
+
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ printf("#%d group: %s\n", i, info0->grui0_name);
+ info0++;
+ break;
+ case 1:
+ printf("#%d group: %s\n", i, info1->grui1_name);
+ printf("#%d attributes: %d\n", i, info1->grui1_attributes);
+ info1++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetUserGetGroups failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/user/user_getinfo.c b/source3/lib/netapi/examples/user/user_getinfo.c
index 19234d0532..9e95260b5a 100644
--- a/source3/lib/netapi/examples/user/user_getinfo.c
+++ b/source3/lib/netapi/examples/user/user_getinfo.c
@@ -36,10 +36,15 @@ int main(int argc, const char **argv)
uint8_t *buffer = NULL;
uint32_t level = 0;
char *sid_str = NULL;
+ int i;
struct USER_INFO_0 *u0;
struct USER_INFO_1 *u1;
+ struct USER_INFO_2 *u2;
+ struct USER_INFO_3 *u3;
+ struct USER_INFO_4 *u4;
struct USER_INFO_10 *u10;
+ struct USER_INFO_11 *u11;
struct USER_INFO_20 *u20;
struct USER_INFO_23 *u23;
@@ -107,6 +112,121 @@ int main(int argc, const char **argv)
printf("flags: 0x%08x\n", u1->usri1_flags);
printf("script: %s\n", u1->usri1_script_path);
break;
+ case 2:
+ u2 = (struct USER_INFO_2 *)buffer;
+ printf("name: %s\n", u2->usri2_name);
+ printf("password: %s\n", u2->usri2_password);
+ printf("password_age: %d\n", u2->usri2_password_age);
+ printf("priv: %d\n", u2->usri2_priv);
+ printf("homedir: %s\n", u2->usri2_home_dir);
+ printf("comment: %s\n", u2->usri2_comment);
+ printf("flags: 0x%08x\n", u2->usri2_flags);
+ printf("script: %s\n", u2->usri2_script_path);
+ printf("auth flags: 0x%08x\n", u2->usri2_auth_flags);
+ printf("full name: %s\n", u2->usri2_full_name);
+ printf("user comment: %s\n", u2->usri2_usr_comment);
+ printf("user parameters: %s\n", u2->usri2_parms);
+ printf("workstations: %s\n", u2->usri2_workstations);
+ printf("last logon (seconds since jan. 1, 1970 GMT): %d\n",
+ u2->usri2_last_logon);
+ printf("last logoff (seconds since jan. 1, 1970 GMT): %d\n",
+ u2->usri2_last_logoff);
+ printf("account expires (seconds since jan. 1, 1970 GMT): %d\n",
+ u2->usri2_acct_expires);
+ printf("max storage: %d\n", u2->usri2_max_storage);
+ printf("units per week: %d\n", u2->usri2_units_per_week);
+ printf("logon hours:");
+ for (i=0; i<21; i++) {
+ printf(" %x", (uint8_t)u2->usri2_logon_hours[i]);
+ }
+ printf("\n");
+ printf("bad password count: %d\n", u2->usri2_bad_pw_count);
+ printf("logon count: %d\n", u2->usri2_num_logons);
+ printf("logon server: %s\n", u2->usri2_logon_server);
+ printf("country code: %d\n", u2->usri2_country_code);
+ printf("code page: %d\n", u2->usri2_code_page);
+ break;
+ case 3:
+ u3 = (struct USER_INFO_3 *)buffer;
+ printf("name: %s\n", u3->usri3_name);
+ printf("password_age: %d\n", u3->usri3_password_age);
+ printf("priv: %d\n", u3->usri3_priv);
+ printf("homedir: %s\n", u3->usri3_home_dir);
+ printf("comment: %s\n", u3->usri3_comment);
+ printf("flags: 0x%08x\n", u3->usri3_flags);
+ printf("script: %s\n", u3->usri3_script_path);
+ printf("auth flags: 0x%08x\n", u3->usri3_auth_flags);
+ printf("full name: %s\n", u3->usri3_full_name);
+ printf("user comment: %s\n", u3->usri3_usr_comment);
+ printf("user parameters: %s\n", u3->usri3_parms);
+ printf("workstations: %s\n", u3->usri3_workstations);
+ printf("last logon (seconds since jan. 1, 1970 GMT): %d\n",
+ u3->usri3_last_logon);
+ printf("last logoff (seconds since jan. 1, 1970 GMT): %d\n",
+ u3->usri3_last_logoff);
+ printf("account expires (seconds since jan. 1, 1970 GMT): %d\n",
+ u3->usri3_acct_expires);
+ printf("max storage: %d\n", u3->usri3_max_storage);
+ printf("units per week: %d\n", u3->usri3_units_per_week);
+ printf("logon hours:");
+ for (i=0; i<21; i++) {
+ printf(" %x", (uint8_t)u3->usri3_logon_hours[i]);
+ }
+ printf("\n");
+ printf("bad password count: %d\n", u3->usri3_bad_pw_count);
+ printf("logon count: %d\n", u3->usri3_num_logons);
+ printf("logon server: %s\n", u3->usri3_logon_server);
+ printf("country code: %d\n", u3->usri3_country_code);
+ printf("code page: %d\n", u3->usri3_code_page);
+ printf("user id: %d\n", u3->usri3_user_id);
+ printf("primary group id: %d\n", u3->usri3_primary_group_id);
+ printf("profile: %s\n", u3->usri3_profile);
+ printf("home dir drive: %s\n", u3->usri3_home_dir_drive);
+ printf("password expired: %d\n", u3->usri3_password_expired);
+ break;
+ case 4:
+ u4 = (struct USER_INFO_4 *)buffer;
+ printf("name: %s\n", u4->usri4_name);
+ printf("password: %s\n", u4->usri4_password);
+ printf("password_age: %d\n", u4->usri4_password_age);
+ printf("priv: %d\n", u4->usri4_priv);
+ printf("homedir: %s\n", u4->usri4_home_dir);
+ printf("comment: %s\n", u4->usri4_comment);
+ printf("flags: 0x%08x\n", u4->usri4_flags);
+ printf("script: %s\n", u4->usri4_script_path);
+ printf("auth flags: 0x%08x\n", u4->usri4_auth_flags);
+ printf("full name: %s\n", u4->usri4_full_name);
+ printf("user comment: %s\n", u4->usri4_usr_comment);
+ printf("user parameters: %s\n", u4->usri4_parms);
+ printf("workstations: %s\n", u4->usri4_workstations);
+ printf("last logon (seconds since jan. 1, 1970 GMT): %d\n",
+ u4->usri4_last_logon);
+ printf("last logoff (seconds since jan. 1, 1970 GMT): %d\n",
+ u4->usri4_last_logoff);
+ printf("account expires (seconds since jan. 1, 1970 GMT): %d\n",
+ u4->usri4_acct_expires);
+ printf("max storage: %d\n", u4->usri4_max_storage);
+ printf("units per week: %d\n", u4->usri4_units_per_week);
+ printf("logon hours:");
+ for (i=0; i<21; i++) {
+ printf(" %x", (uint8_t)u4->usri4_logon_hours[i]);
+ }
+ printf("\n");
+ printf("bad password count: %d\n", u4->usri4_bad_pw_count);
+ printf("logon count: %d\n", u4->usri4_num_logons);
+ printf("logon server: %s\n", u4->usri4_logon_server);
+ printf("country code: %d\n", u4->usri4_country_code);
+ printf("code page: %d\n", u4->usri4_code_page);
+ if (ConvertSidToStringSid(u4->usri4_user_sid,
+ &sid_str)) {
+ printf("user_sid: %s\n", sid_str);
+ free(sid_str);
+ }
+ printf("primary group id: %d\n", u4->usri4_primary_group_id);
+ printf("profile: %s\n", u4->usri4_profile);
+ printf("home dir drive: %s\n", u4->usri4_home_dir_drive);
+ printf("password expired: %d\n", u4->usri4_password_expired);
+ break;
case 10:
u10 = (struct USER_INFO_10 *)buffer;
printf("name: %s\n", u10->usri10_name);
@@ -114,6 +234,35 @@ int main(int argc, const char **argv)
printf("usr_comment: %s\n", u10->usri10_usr_comment);
printf("full_name: %s\n", u10->usri10_full_name);
break;
+ case 11:
+ u11 = (struct USER_INFO_11 *)buffer;
+ printf("name: %s\n", u11->usri11_name);
+ printf("comment: %s\n", u11->usri11_comment);
+ printf("user comment: %s\n", u11->usri11_usr_comment);
+ printf("full name: %s\n", u11->usri11_full_name);
+ printf("priv: %d\n", u11->usri11_priv);
+ printf("auth flags: 0x%08x\n", u11->usri11_auth_flags);
+ printf("password_age: %d\n", u11->usri11_password_age);
+ printf("homedir: %s\n", u11->usri11_home_dir);
+ printf("user parameters: %s\n", u11->usri11_parms);
+ printf("last logon (seconds since jan. 1, 1970 GMT): %d\n",
+ u11->usri11_last_logon);
+ printf("last logoff (seconds since jan. 1, 1970 GMT): %d\n",
+ u11->usri11_last_logoff);
+ printf("bad password count: %d\n", u11->usri11_bad_pw_count);
+ printf("logon count: %d\n", u11->usri11_num_logons);
+ printf("logon server: %s\n", u11->usri11_logon_server);
+ printf("country code: %d\n", u11->usri11_country_code);
+ printf("workstations: %s\n", u11->usri11_workstations);
+ printf("max storage: %d\n", u11->usri11_max_storage);
+ printf("units per week: %d\n", u11->usri11_units_per_week);
+ printf("logon hours:");
+ for (i=0; i<21; i++) {
+ printf(" %x", (uint8_t)u11->usri11_logon_hours[i]);
+ }
+ printf("\n");
+ printf("code page: %d\n", u11->usri11_code_page);
+ break;
case 20:
u20 = (struct USER_INFO_20 *)buffer;
printf("name: %s\n", u20->usri20_name);
diff --git a/source3/lib/netapi/examples/user/user_setinfo.c b/source3/lib/netapi/examples/user/user_setinfo.c
index ec464232e9..4f02ae7781 100644
--- a/source3/lib/netapi/examples/user/user_setinfo.c
+++ b/source3/lib/netapi/examples/user/user_setinfo.c
@@ -33,10 +33,34 @@ int main(int argc, const char **argv)
struct libnetapi_ctx *ctx = NULL;
const char *hostname = NULL;
const char *username = NULL;
- uint32_t level = 1007;
+ uint32_t level = 0;
uint32_t parm_err = 0;
-
+ uint8_t *buffer = NULL;
+ const char *val = NULL;
+
+ struct USER_INFO_0 u0;
+ struct USER_INFO_1 u1;
+ struct USER_INFO_2 u2;
+ struct USER_INFO_3 u3;
+ struct USER_INFO_4 u4;
+ struct USER_INFO_21 u21;
+ struct USER_INFO_22 u22;
+ struct USER_INFO_1003 u1003;
+ struct USER_INFO_1005 u1005;
+ struct USER_INFO_1006 u1006;
struct USER_INFO_1007 u1007;
+ struct USER_INFO_1008 u1008;
+ struct USER_INFO_1009 u1009;
+ struct USER_INFO_1010 u1010;
+ struct USER_INFO_1011 u1011;
+ struct USER_INFO_1012 u1012;
+ struct USER_INFO_1014 u1014;
+ struct USER_INFO_1017 u1017;
+ struct USER_INFO_1020 u1020;
+ struct USER_INFO_1024 u1024;
+ struct USER_INFO_1051 u1051;
+ struct USER_INFO_1052 u1052;
+ struct USER_INFO_1053 u1053;
poptContext pc;
int opt;
@@ -70,18 +94,104 @@ int main(int argc, const char **argv)
}
username = poptGetArg(pc);
- if (poptPeekArg(pc)) {
- level = atoi(poptGetArg(pc));
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ level = atoi(poptGetArg(pc));
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
}
+ val = poptGetArg(pc);
/* NetUserSetInfo */
- u1007.usri1007_comment = "NetApi test comment";
+ switch (level) {
+ case 0:
+ u0.usri0_name = val;
+ buffer = (uint8_t *)&u0;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ break;
+ case 21:
+ break;
+ case 22:
+ break;
+ case 1003:
+ u1003.usri1003_password = val;
+ buffer = (uint8_t *)&u1003;
+ break;
+ case 1005:
+ u1005.usri1005_priv = atoi(val);
+ buffer = (uint8_t *)&u1005;
+ break;
+ case 1006:
+ u1006.usri1006_home_dir = val;
+ buffer = (uint8_t *)&u1006;
+ break;
+ case 1007:
+ u1007.usri1007_comment = val;
+ buffer = (uint8_t *)&u1007;
+ break;
+ case 1008:
+ u1008.usri1008_flags = atoi(val);
+ buffer = (uint8_t *)&u1008;
+ break;
+ case 1009:
+ u1009.usri1009_script_path = val;
+ buffer = (uint8_t *)&u1009;
+ break;
+ case 1010:
+ u1010.usri1010_auth_flags = atoi(val);
+ buffer = (uint8_t *)&u1010;
+ break;
+ case 1011:
+ u1011.usri1011_full_name = val;
+ buffer = (uint8_t *)&u1011;
+ break;
+ case 1012:
+ u1012.usri1012_usr_comment = val;
+ buffer = (uint8_t *)&u1012;
+ break;
+ case 1014:
+ u1014.usri1014_workstations = val;
+ buffer = (uint8_t *)&u1014;
+ break;
+ case 1017:
+ u1017.usri1017_acct_expires = atoi(val);
+ buffer = (uint8_t *)&u1017;
+ break;
+ case 1020:
+ break;
+ case 1024:
+ u1024.usri1024_country_code = atoi(val);
+ buffer = (uint8_t *)&u1024;
+ break;
+ case 1051:
+ u1051.usri1051_primary_group_id = atoi(val);
+ buffer = (uint8_t *)&u1051;
+ break;
+ case 1052:
+ u1052.usri1052_profile = val;
+ buffer = (uint8_t *)&u1052;
+ break;
+ case 1053:
+ u1053.usri1053_home_dir_drive = val;
+ buffer = (uint8_t *)&u1053;
+ break;
+ default:
+ break;
+ }
status = NetUserSetInfo(hostname,
username,
level,
- (uint8_t *)&u1007,
+ buffer,
&parm_err);
if (status != 0) {
printf("NetUserSetInfo failed with: %s\n",
diff --git a/source3/lib/netapi/joindomain.c b/source3/lib/netapi/joindomain.c
index 2a6fc80ca3..17ea3923fe 100644
--- a/source3/lib/netapi/joindomain.c
+++ b/source3/lib/netapi/joindomain.c
@@ -364,7 +364,7 @@ WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
dc = strip_hostname(info->dc_unc);
- ads = ads_init(r->in.domain, r->in.domain, dc);
+ ads = ads_init(info->domain_name, info->domain_name, dc);
if (!ads) {
return WERR_GENERAL_FAILURE;
}
diff --git a/source3/lib/netapi/libnetapi.c b/source3/lib/netapi/libnetapi.c
index 5fe48077a8..b4f2bb6ac2 100644
--- a/source3/lib/netapi/libnetapi.c
+++ b/source3/lib/netapi/libnetapi.c
@@ -726,6 +726,58 @@ NET_API_STATUS NetUserSetInfo(const char * server_name /* [in] */,
}
/****************************************************************
+ NetUserGetGroups
+****************************************************************/
+
+NET_API_STATUS NetUserGetGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */)
+{
+ struct NetUserGetGroups r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.user_name = user_name;
+ r.in.level = level;
+ r.in.prefmaxlen = prefmaxlen;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserGetGroups, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserGetGroups_l(ctx, &r);
+ } else {
+ werr = NetUserGetGroups_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserGetGroups, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
NetUserModalsGet
****************************************************************/
@@ -1721,3 +1773,49 @@ NET_API_STATUS NetRemoteTOD(const char * server_name /* [in] */,
return r.out.result;
}
+/****************************************************************
+ NetShareAdd
+****************************************************************/
+
+NET_API_STATUS NetShareAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetShareAdd r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetShareAdd, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetShareAdd_l(ctx, &r);
+ } else {
+ werr = NetShareAdd_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetShareAdd, &r);
+ }
+
+ return r.out.result;
+}
+
diff --git a/source3/lib/netapi/libnetapi.h b/source3/lib/netapi/libnetapi.h
index b0ff8e5baf..9a75b396fe 100644
--- a/source3/lib/netapi/libnetapi.h
+++ b/source3/lib/netapi/libnetapi.h
@@ -125,6 +125,17 @@ WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
struct NetUserSetInfo *r);
WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
struct NetUserSetInfo *r);
+NET_API_STATUS NetUserGetGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */);
+WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
+ struct NetUserGetGroups *r);
+WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
+ struct NetUserGetGroups *r);
NET_API_STATUS NetUserModalsGet(const char * server_name /* [in] */,
uint32_t level /* [in] */,
uint8_t **buffer /* [out] [ref] */);
@@ -306,4 +317,12 @@ WERROR NetRemoteTOD_r(struct libnetapi_ctx *ctx,
struct NetRemoteTOD *r);
WERROR NetRemoteTOD_l(struct libnetapi_ctx *ctx,
struct NetRemoteTOD *r);
+NET_API_STATUS NetShareAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetShareAdd_r(struct libnetapi_ctx *ctx,
+ struct NetShareAdd *r);
+WERROR NetShareAdd_l(struct libnetapi_ctx *ctx,
+ struct NetShareAdd *r);
#endif /* __LIBNETAPI_LIBNETAPI__ */
diff --git a/source3/lib/netapi/netapi.h b/source3/lib/netapi/netapi.h
index f7bf1880cc..05c702cb3f 100644
--- a/source3/lib/netapi/netapi.h
+++ b/source3/lib/netapi/netapi.h
@@ -33,6 +33,8 @@ typedef enum {
#define ERROR_MORE_DATA ( 234L )
+#define ENCRYPTED_PWLEN ( 16 )
+
/****************************************************************
****************************************************************/
@@ -73,6 +75,20 @@ struct DOMAIN_CONTROLLER_INFO {
const char * client_site_name;
};
+/* bitmap NetJoinFlags */
+#define NETSETUP_JOIN_DOMAIN ( 0x00000001 )
+#define NETSETUP_ACCT_CREATE ( 0x00000002 )
+#define NETSETUP_ACCT_DELETE ( 0x00000004 )
+#define NETSETUP_WIN9X_UPGRADE ( 0x00000010 )
+#define NETSETUP_DOMAIN_JOIN_IF_JOINED ( 0x00000020 )
+#define NETSETUP_JOIN_UNSECURE ( 0x00000040 )
+#define NETSETUP_MACHINE_PWD_PASSED ( 0x00000080 )
+#define NETSETUP_DEFER_SPN_SET ( 0x00000100 )
+#define NETSETUP_JOIN_DC_ACCOUNT ( 0x00000200 )
+#define NETSETUP_JOIN_WITH_NEW_NAME ( 0x00000400 )
+#define NETSETUP_INSTALL_INVOCATION ( 0x00040000 )
+#define NETSETUP_IGNORE_UNSUPPORTED_FLAGS ( 0x10000000 )
+
#define FILTER_TEMP_DUPLICATE_ACCOUNT ( 0x0001 )
#define FILTER_NORMAL_ACCOUNT ( 0x0002 )
#define FILTER_INTERDOMAIN_TRUST_ACCOUNT ( 0x0008 )
@@ -89,6 +105,10 @@ struct USER_INFO_0 {
const char * usri0_name;
};
+#define USER_PRIV_GUEST ( 0 )
+#define USER_PRIV_USER ( 1 )
+#define USER_PRIV_ADMIN ( 2 )
+
struct USER_INFO_1 {
const char * usri1_name;
const char * usri1_password;
@@ -100,6 +120,11 @@ struct USER_INFO_1 {
const char * usri1_script_path;
};
+#define AF_OP_PRINT ( 0x1 )
+#define AF_OP_COMM ( 0x2 )
+#define AF_OP_SERVER ( 0x4 )
+#define AF_OP_ACCOUNTS ( 0x8 )
+
struct USER_INFO_2 {
const char * usri2_name;
const char * usri2_password;
@@ -183,7 +208,7 @@ struct USER_INFO_4 {
const char * usri4_logon_server;
uint32_t usri4_country_code;
uint32_t usri4_code_page;
- struct dom_sid *usri4_user_sid;/* [unique] */
+ struct domsid *usri4_user_sid;/* [unique] */
uint32_t usri4_primary_group_id;
const char * usri4_profile;
const char * usri4_home_dir_drive;
@@ -228,6 +253,37 @@ struct USER_INFO_20 {
uint32_t usri20_user_id;
};
+struct USER_INFO_21 {
+ uint8_t *usri21_password;
+};
+
+struct USER_INFO_22 {
+ const char * usri22_name;
+ uint8_t *usri22_password;
+ uint32_t usri22_password_age;
+ uint32_t usri22_priv;
+ const char * usri22_home_dir;
+ const char * usri22_comment;
+ uint32_t usri22_flags;
+ uint32_t usri22_script_path;
+ uint32_t usri22_auth_flags;
+ const char * usri22_full_name;
+ const char * usri22_usr_comment;
+ const char * usri22_parms;
+ const char * usri22_workstations;
+ uint32_t usri22_last_logon;
+ uint32_t usri22_last_logoff;
+ uint32_t usri22_acct_expires;
+ uint32_t usri22_max_storage;
+ uint32_t usri22_units_per_week;
+ uint8_t *usri22_logon_hours;/* [unique] */
+ uint32_t usri22_bad_pw_count;
+ uint32_t usri22_num_logons;
+ const char * usri22_logon_server;
+ uint32_t usri22_country_code;
+ uint32_t usri22_code_page;
+};
+
struct USER_INFO_23 {
const char * usri23_name;
const char * usri23_full_name;
@@ -236,10 +292,87 @@ struct USER_INFO_23 {
struct domsid *usri23_user_sid;/* [unique] */
};
+struct USER_INFO_1003 {
+ const char * usri1003_password;
+};
+
+struct USER_INFO_1005 {
+ uint32_t usri1005_priv;
+};
+
+struct USER_INFO_1006 {
+ const char * usri1006_home_dir;
+};
+
struct USER_INFO_1007 {
const char * usri1007_comment;
};
+struct USER_INFO_1008 {
+ uint32_t usri1008_flags;
+};
+
+struct USER_INFO_1009 {
+ const char * usri1009_script_path;
+};
+
+struct USER_INFO_1010 {
+ uint32_t usri1010_auth_flags;
+};
+
+struct USER_INFO_1011 {
+ const char * usri1011_full_name;
+};
+
+struct USER_INFO_1012 {
+ const char * usri1012_usr_comment;
+};
+
+struct USER_INFO_1013 {
+ const char * usri1013_parms;
+};
+
+struct USER_INFO_1014 {
+ const char * usri1014_workstations;
+};
+
+struct USER_INFO_1017 {
+ uint32_t usri1017_acct_expires;
+};
+
+struct USER_INFO_1018 {
+ uint32_t usri1018_max_storage;
+};
+
+struct USER_INFO_1020 {
+ uint32_t usri1020_units_per_week;
+ uint8_t *usri1020_logon_hours;/* [unique] */
+};
+
+struct USER_INFO_1023 {
+ const char * usri1023_logon_server;
+};
+
+struct USER_INFO_1024 {
+ uint32_t usri1024_country_code;
+};
+
+struct USER_INFO_1025 {
+ uint32_t usri1025_code_page;
+};
+
+struct USER_INFO_1051 {
+ uint32_t usri1051_primary_group_id;
+};
+
+struct USER_INFO_1052 {
+ const char * usri1052_profile;
+};
+
+struct USER_INFO_1053 {
+ const char * usri1053_home_dir_drive;
+};
+
struct USER_MODALS_INFO_0 {
uint32_t usrmod0_min_passwd_len;
uint32_t usrmod0_max_passwd_age;
@@ -418,6 +551,17 @@ struct TIME_OF_DAY_INFO {
uint32_t tod_weekday;
};
+struct SHARE_INFO_2 {
+ const char * shi2_netname;
+ uint32_t shi2_type;
+ const char * shi2_remark;
+ uint32_t shi2_permissions;
+ uint32_t shi2_max_uses;
+ uint32_t shi2_current_uses;
+ const char * shi2_path;
+ const char * shi2_passwd;
+};
+
#endif /* _HEADER_libnetapi */
/****************************************************************
@@ -890,6 +1034,33 @@ NET_API_STATUS NetUserModalsSet(const char * server_name /* [in] */,
/************************************************************//**
*
+ * NetUserGetGroups
+ *
+ * @brief Enumerate grouplist of a user on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] user_name The user name to query
+ * @param[in] level The enumeration level used for the query (Currently only
+ * level 0 is supported)
+ * @param[out] buffer The returned enumeration buffer
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of returned entries
+ * @param[out] total_entries The number of total entries
+ * @return NET_API_STATUS
+ *
+ * example user/user_getgroups.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserGetGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */);
+
+/************************************************************//**
+ *
* NetQueryDisplayInformation
*
* @brief Enumerate accounts on a server
@@ -1309,6 +1480,27 @@ NET_API_STATUS NetLocalGroupSetMembers(const char * server_name /* [in] */,
NET_API_STATUS NetRemoteTOD(const char * server_name /* [in] */,
uint8_t **buf /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetShareAdd
+ *
+ * @brief Add Share
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level defining the requested SHARE_INFO_X structure
+ * @param[in] buf The buffer containing a SHARE_INFO_X structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example share/share_add.c
+ ***************************************************************/
+
+NET_API_STATUS NetShareAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/source3/lib/netapi/share.c b/source3/lib/netapi/share.c
new file mode 100644
index 0000000000..3b99a8d291
--- /dev/null
+++ b/source3/lib/netapi/share.c
@@ -0,0 +1,133 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Share Support
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS map_SHARE_INFO_buffer_to_srvsvc_share_info(TALLOC_CTX *mem_ctx,
+ uint8_t *buffer,
+ uint32_t level,
+ union srvsvc_NetShareInfo *info)
+{
+ struct SHARE_INFO_2 *i2 = NULL;
+ struct srvsvc_NetShareInfo2 *s2 = NULL;
+
+ if (!buffer) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ switch (level) {
+ case 2:
+ i2 = (struct SHARE_INFO_2 *)buffer;
+
+ s2 = TALLOC_P(mem_ctx, struct srvsvc_NetShareInfo2);
+ NT_STATUS_HAVE_NO_MEMORY(s2);
+
+ s2->name = i2->shi2_netname;
+ s2->type = i2->shi2_type;
+ s2->comment = i2->shi2_remark;
+ s2->permissions = i2->shi2_permissions;
+ s2->max_users = i2->shi2_max_uses;
+ s2->current_users = i2->shi2_current_uses;
+ s2->path = i2->shi2_path;
+ s2->password = i2->shi2_passwd;
+
+ info->info2 = s2;
+
+ break;
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareAdd_r(struct libnetapi_ctx *ctx,
+ struct NetShareAdd *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ union srvsvc_NetShareInfo info;
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 2:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_srvsvc.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = map_SHARE_INFO_buffer_to_srvsvc_share_info(ctx,
+ r->in.buffer,
+ r->in.level,
+ &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_srvsvc_NetShareAdd(pipe_cli, ctx,
+ r->in.server_name,
+ r->in.level,
+ &info,
+ r->out.parm_err,
+ &werr);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareAdd_l(struct libnetapi_ctx *ctx,
+ struct NetShareAdd *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareAdd);
+}
diff --git a/source3/lib/netapi/user.c b/source3/lib/netapi/user.c
index 7b530f4308..ae8d2ecd89 100644
--- a/source3/lib/netapi/user.c
+++ b/source3/lib/netapi/user.c
@@ -30,18 +30,20 @@
static void convert_USER_INFO_X_to_samr_user_info21(struct USER_INFO_X *infoX,
struct samr_UserInfo21 *info21)
{
- uint32_t fields_present = SAMR_FIELD_ACCT_FLAGS;
+ uint32_t fields_present = 0;
struct samr_LogonHours zero_logon_hours;
struct lsa_BinaryString zero_parameters;
- uint32_t acct_flags = 0;
NTTIME password_age;
ZERO_STRUCTP(info21);
ZERO_STRUCT(zero_logon_hours);
ZERO_STRUCT(zero_parameters);
+ if (infoX->usriX_flags) {
+ fields_present |= SAMR_FIELD_ACCT_FLAGS;
+ }
if (infoX->usriX_name) {
- fields_present |= SAMR_FIELD_FULL_NAME;
+ fields_present |= SAMR_FIELD_ACCOUNT_NAME;
}
if (infoX->usriX_password) {
fields_present |= SAMR_FIELD_PASSWORD;
@@ -64,8 +66,27 @@ static void convert_USER_INFO_X_to_samr_user_info21(struct USER_INFO_X *infoX,
if (infoX->usriX_password_age) {
fields_present |= SAMR_FIELD_FORCE_PWD_CHANGE;
}
-
- acct_flags |= infoX->usriX_flags | ACB_NORMAL;
+ if (infoX->usriX_full_name) {
+ fields_present |= SAMR_FIELD_FULL_NAME;
+ }
+ if (infoX->usriX_usr_comment) {
+ fields_present |= SAMR_FIELD_COMMENT;
+ }
+ if (infoX->usriX_profile) {
+ fields_present |= SAMR_FIELD_PROFILE_PATH;
+ }
+ if (infoX->usriX_home_dir_drive) {
+ fields_present |= SAMR_FIELD_HOME_DRIVE;
+ }
+ if (infoX->usriX_primary_group_id) {
+ fields_present |= SAMR_FIELD_PRIMARY_GID;
+ }
+ if (infoX->usriX_country_code) {
+ fields_present |= SAMR_FIELD_COUNTRY_CODE;
+ }
+ if (infoX->usriX_workstations) {
+ fields_present |= SAMR_FIELD_WORKSTATIONS;
+ }
unix_to_nt_time_abs(&password_age, infoX->usriX_password_age);
@@ -77,24 +98,24 @@ static void convert_USER_INFO_X_to_samr_user_info21(struct USER_INFO_X *infoX,
0,
0,
password_age,
- NULL,
infoX->usriX_name,
+ infoX->usriX_full_name,
infoX->usriX_home_dir,
- NULL,
+ infoX->usriX_home_dir_drive,
infoX->usriX_script_path,
- NULL,
+ infoX->usriX_profile,
infoX->usriX_comment,
- NULL,
- NULL,
+ infoX->usriX_workstations,
+ infoX->usriX_usr_comment,
&zero_parameters,
0,
- 0,
- acct_flags,
+ infoX->usriX_primary_group_id,
+ infoX->usriX_flags,
fields_present,
zero_logon_hours,
0,
0,
- 0,
+ infoX->usriX_country_code,
0,
0,
0,
@@ -111,7 +132,17 @@ static NTSTATUS construct_USER_INFO_X(uint32_t level,
struct USER_INFO_0 *u0 = NULL;
struct USER_INFO_1 *u1 = NULL;
struct USER_INFO_2 *u2 = NULL;
+ struct USER_INFO_1003 *u1003 = NULL;
+ struct USER_INFO_1006 *u1006 = NULL;
struct USER_INFO_1007 *u1007 = NULL;
+ struct USER_INFO_1009 *u1009 = NULL;
+ struct USER_INFO_1011 *u1011 = NULL;
+ struct USER_INFO_1012 *u1012 = NULL;
+ struct USER_INFO_1014 *u1014 = NULL;
+ struct USER_INFO_1024 *u1024 = NULL;
+ struct USER_INFO_1051 *u1051 = NULL;
+ struct USER_INFO_1052 *u1052 = NULL;
+ struct USER_INFO_1053 *u1053 = NULL;
if (!buffer || !uX) {
return NT_STATUS_INVALID_PARAMETER;
@@ -162,10 +193,50 @@ static NTSTATUS construct_USER_INFO_X(uint32_t level,
uX->usriX_country_code = u2->usri2_country_code;
uX->usriX_code_page = u2->usri2_code_page;
break;
+ case 1003:
+ u1003 = (struct USER_INFO_1003 *)buffer;
+ uX->usriX_password = u1003->usri1003_password;
+ break;
+ case 1006:
+ u1006 = (struct USER_INFO_1006 *)buffer;
+ uX->usriX_home_dir = u1006->usri1006_home_dir;
+ break;
case 1007:
u1007 = (struct USER_INFO_1007 *)buffer;
uX->usriX_comment = u1007->usri1007_comment;
break;
+ case 1009:
+ u1009 = (struct USER_INFO_1009 *)buffer;
+ uX->usriX_script_path = u1009->usri1009_script_path;
+ break;
+ case 1011:
+ u1011 = (struct USER_INFO_1011 *)buffer;
+ uX->usriX_full_name = u1011->usri1011_full_name;
+ break;
+ case 1012:
+ u1012 = (struct USER_INFO_1012 *)buffer;
+ uX->usriX_usr_comment = u1012->usri1012_usr_comment;
+ break;
+ case 1014:
+ u1014 = (struct USER_INFO_1014 *)buffer;
+ uX->usriX_workstations = u1014->usri1014_workstations;
+ break;
+ case 1024:
+ u1024 = (struct USER_INFO_1024 *)buffer;
+ uX->usriX_country_code = u1024->usri1024_country_code;
+ break;
+ case 1051:
+ u1051 = (struct USER_INFO_1051 *)buffer;
+ uX->usriX_primary_group_id = u1051->usri1051_primary_group_id;
+ break;
+ case 1052:
+ u1052 = (struct USER_INFO_1052 *)buffer;
+ uX->usriX_profile = u1052->usri1052_profile;
+ break;
+ case 1053:
+ u1053 = (struct USER_INFO_1053 *)buffer;
+ uX->usriX_home_dir_drive = u1053->usri1053_home_dir_drive;
+ break;
case 3:
case 4:
default:
@@ -178,6 +249,66 @@ static NTSTATUS construct_USER_INFO_X(uint32_t level,
/****************************************************************
****************************************************************/
+static NTSTATUS set_user_info_USER_INFO_X(TALLOC_CTX *ctx,
+ struct rpc_pipe_client *pipe_cli,
+ DATA_BLOB *session_key,
+ struct policy_handle *user_handle,
+ struct USER_INFO_X *uX)
+{
+ union samr_UserInfo user_info;
+ struct samr_UserInfo21 info21;
+ NTSTATUS status;
+
+ if (!uX) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ convert_USER_INFO_X_to_samr_user_info21(uX, &info21);
+
+ ZERO_STRUCT(user_info);
+
+ if (uX->usriX_password) {
+
+ user_info.info25.info = info21;
+
+ init_samr_CryptPasswordEx(uX->usriX_password,
+ session_key,
+ &user_info.info25.password);
+
+ status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
+ user_handle,
+ 25,
+ &user_info);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) {
+
+ user_info.info23.info = info21;
+
+ init_samr_CryptPassword(uX->usriX_password,
+ session_key,
+ &user_info.info23.password);
+
+ status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
+ user_handle,
+ 23,
+ &user_info);
+ }
+ } else {
+
+ user_info.info21 = info21;
+
+ status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
+ user_handle,
+ 21,
+ &user_info);
+ }
+
+ return status;
+}
+
+/****************************************************************
+****************************************************************/
+
WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
struct NetUserAdd *r)
{
@@ -188,7 +319,6 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
POLICY_HND connect_handle, domain_handle, user_handle;
struct lsa_String lsa_account_name;
struct dom_sid2 *domain_sid = NULL;
- struct samr_UserInfo21 info21;
union samr_UserInfo *user_info = NULL;
struct samr_PwInfo pw_info;
uint32_t access_granted = 0;
@@ -282,47 +412,12 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
goto done;
}
- convert_USER_INFO_X_to_samr_user_info21(&uX,
- &info21);
-
- ZERO_STRUCTP(user_info);
-
- if (uX.usriX_password) {
-
- user_info->info25.info = info21;
-
- init_samr_CryptPasswordEx(uX.usriX_password,
- &cli->user_session_key,
- &user_info->info25.password);
-
- status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
- &user_handle,
- 25,
- user_info);
-
- if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) {
-
- user_info->info23.info = info21;
-
- init_samr_CryptPassword(uX.usriX_password,
- &cli->user_session_key,
- &user_info->info23.password);
-
- status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
- &user_handle,
- 23,
- user_info);
- }
- } else {
-
- user_info->info21 = info21;
+ uX.usriX_flags |= ACB_NORMAL;
- status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
- &user_handle,
- 21,
- user_info);
-
- }
+ status = set_user_info_USER_INFO_X(ctx, pipe_cli,
+ &cli->user_session_key,
+ &user_handle,
+ &uX);
if (!NT_STATUS_IS_OK(status)) {
werr = ntstatus_to_werror(status);
goto failed;
@@ -489,10 +584,12 @@ static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
struct policy_handle *domain_handle,
struct policy_handle *builtin_handle,
const char *user_name,
+ const struct dom_sid *domain_sid,
uint32_t rid,
uint32_t level,
struct samr_UserInfo21 **info21,
- struct sec_desc_buf **sec_desc)
+ struct sec_desc_buf **sec_desc,
+ uint32_t *auth_flag_p)
{
NTSTATUS status;
@@ -507,11 +604,20 @@ static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
switch (level) {
case 0:
+ break;
case 1:
+ access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
+ SAMR_USER_ACCESS_GET_GROUPS;
+ break;
case 2:
case 3:
- case 10:
+ case 4:
case 11:
+ access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
+ SAMR_USER_ACCESS_GET_GROUPS |
+ SAMR_USER_ACCESS_GET_LOCALE;
+ break;
+ case 10:
case 20:
case 23:
break;
@@ -548,7 +654,14 @@ static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
goto done;
}
- if (level == 1) {
+ if (access_mask & SAMR_USER_ACCESS_GET_GROUPS) {
+
+ struct lsa_SidArray sid_array;
+ struct samr_Ids alias_rids;
+ int i;
+ uint32_t auth_flag = 0;
+ struct dom_sid sid;
+
status = rpccli_samr_GetGroupsForUser(pipe_cli, mem_ctx,
&user_handle,
&rid_array);
@@ -556,15 +669,48 @@ static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
goto done;
}
-#if 0
- status = rpccli_samr_GetAliasMembership(pipe_cli, ctx,
- &builtin_handle,
- &sids,
- &rids);
+ sid_array.num_sids = rid_array->count + 1;
+ sid_array.sids = talloc_array(mem_ctx, struct lsa_SidPtr,
+ sid_array.num_sids);
+ NT_STATUS_HAVE_NO_MEMORY(sid_array.sids);
+
+ for (i=0; i<rid_array->count; i++) {
+ sid_compose(&sid, domain_sid, rid_array->rids[i].rid);
+ sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sid);
+ NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
+ }
+
+ sid_compose(&sid, domain_sid, rid);
+ sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sid);
+ NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
+
+ status = rpccli_samr_GetAliasMembership(pipe_cli, mem_ctx,
+ builtin_handle,
+ &sid_array,
+ &alias_rids);
if (!NT_STATUS_IS_OK(status)) {
goto done;
}
-#endif
+
+ for (i=0; i<alias_rids.count; i++) {
+ switch (alias_rids.ids[i]) {
+ case 550: /* Print Operators */
+ auth_flag |= AF_OP_PRINT;
+ break;
+ case 549: /* Server Operators */
+ auth_flag |= AF_OP_SERVER;
+ break;
+ case 548: /* Account Operators */
+ auth_flag |= AF_OP_ACCOUNTS;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (auth_flag_p) {
+ *auth_flag_p = auth_flag;
+ }
}
*info21 = &user_info->info21;
@@ -580,6 +726,283 @@ static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
/****************************************************************
****************************************************************/
+static uint32_t samr_rid_to_priv_level(uint32_t rid)
+{
+ switch (rid) {
+ case DOMAIN_RID_ADMINISTRATOR:
+ return USER_PRIV_ADMIN;
+ case DOMAIN_RID_GUEST:
+ return USER_PRIV_GUEST;
+ default:
+ return USER_PRIV_USER;
+ }
+}
+
+/****************************************************************
+****************************************************************/
+
+static uint32_t samr_acb_flags_to_netapi_flags(uint32_t acb)
+{
+ uint32_t fl = UF_SCRIPT; /* god knows why */
+
+ fl |= ads_acb2uf(acb);
+
+ return fl;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_1(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ struct USER_INFO_1 *i)
+{
+ ZERO_STRUCTP(i);
+ i->usri1_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri1_name);
+ i->usri1_password = NULL;
+ i->usri1_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
+ i->usri1_priv = samr_rid_to_priv_level(i21->rid);
+ i->usri1_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
+ i->usri1_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri1_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ i->usri1_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_2(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ uint32_t auth_flag,
+ struct USER_INFO_2 *i)
+{
+ ZERO_STRUCTP(i);
+
+ i->usri2_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri2_name);
+ i->usri2_password = NULL;
+ i->usri2_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
+ i->usri2_priv = samr_rid_to_priv_level(i21->rid);
+ i->usri2_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
+ i->usri2_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri2_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ i->usri2_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
+ i->usri2_auth_flags = auth_flag;
+ i->usri2_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri2_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
+ i->usri2_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
+ i->usri2_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
+ i->usri2_last_logon = nt_time_to_unix(i21->last_logon);
+ i->usri2_last_logoff = nt_time_to_unix(i21->last_logoff);
+ i->usri2_acct_expires = nt_time_to_unix(i21->acct_expiry);
+ i->usri2_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
+ i->usri2_units_per_week = i21->logon_hours.units_per_week;
+ i->usri2_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
+ i->usri2_bad_pw_count = i21->bad_password_count;
+ i->usri2_num_logons = i21->logon_count;
+ i->usri2_logon_server = talloc_strdup(mem_ctx, "\\\\*");
+ i->usri2_country_code = i21->country_code;
+ i->usri2_code_page = i21->code_page;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_3(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ uint32_t auth_flag,
+ struct USER_INFO_3 *i)
+{
+ ZERO_STRUCTP(i);
+
+ i->usri3_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri3_name);
+ i->usri3_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
+ i->usri3_priv = samr_rid_to_priv_level(i21->rid);
+ i->usri3_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
+ i->usri3_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri3_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ i->usri3_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
+ i->usri3_auth_flags = auth_flag;
+ i->usri3_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri3_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
+ i->usri3_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
+ i->usri3_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
+ i->usri3_last_logon = nt_time_to_unix(i21->last_logon);
+ i->usri3_last_logoff = nt_time_to_unix(i21->last_logoff);
+ i->usri3_acct_expires = nt_time_to_unix(i21->acct_expiry);
+ i->usri3_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
+ i->usri3_units_per_week = i21->logon_hours.units_per_week;
+ i->usri3_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
+ i->usri3_bad_pw_count = i21->bad_password_count;
+ i->usri3_num_logons = i21->logon_count;
+ i->usri3_logon_server = talloc_strdup(mem_ctx, "\\\\*");
+ i->usri3_country_code = i21->country_code;
+ i->usri3_code_page = i21->code_page;
+ i->usri3_user_id = i21->rid;
+ i->usri3_primary_group_id = i21->primary_gid;
+ i->usri3_profile = talloc_strdup(mem_ctx, i21->profile_path.string);
+ i->usri3_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
+ i->usri3_password_expired = i21->password_expired;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_4(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ uint32_t auth_flag,
+ struct dom_sid *domain_sid,
+ struct USER_INFO_4 *i)
+{
+ struct dom_sid sid;
+
+ ZERO_STRUCTP(i);
+
+ i->usri4_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri4_name);
+ i->usri4_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
+ i->usri4_password = NULL;
+ i->usri4_priv = samr_rid_to_priv_level(i21->rid);
+ i->usri4_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
+ i->usri4_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri4_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ i->usri4_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
+ i->usri4_auth_flags = auth_flag;
+ i->usri4_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri4_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
+ i->usri4_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
+ i->usri4_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
+ i->usri4_last_logon = nt_time_to_unix(i21->last_logon);
+ i->usri4_last_logoff = nt_time_to_unix(i21->last_logoff);
+ i->usri4_acct_expires = nt_time_to_unix(i21->acct_expiry);
+ i->usri4_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
+ i->usri4_units_per_week = i21->logon_hours.units_per_week;
+ i->usri4_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
+ i->usri4_bad_pw_count = i21->bad_password_count;
+ i->usri4_num_logons = i21->logon_count;
+ i->usri4_logon_server = talloc_strdup(mem_ctx, "\\\\*");
+ i->usri4_country_code = i21->country_code;
+ i->usri4_code_page = i21->code_page;
+ if (!sid_compose(&sid, domain_sid, i21->rid)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ i->usri4_user_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
+ i->usri4_primary_group_id = i21->primary_gid;
+ i->usri4_profile = talloc_strdup(mem_ctx, i21->profile_path.string);
+ i->usri4_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
+ i->usri4_password_expired = i21->password_expired;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_10(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ struct USER_INFO_10 *i)
+{
+ ZERO_STRUCTP(i);
+
+ i->usri10_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri10_name);
+ i->usri10_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri10_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri10_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_11(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ uint32_t auth_flag,
+ struct USER_INFO_11 *i)
+{
+ ZERO_STRUCTP(i);
+
+ i->usri11_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri11_name);
+ i->usri11_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri11_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
+ i->usri11_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri11_priv = samr_rid_to_priv_level(i21->rid);
+ i->usri11_auth_flags = auth_flag;
+ i->usri11_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
+ i->usri11_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
+ i->usri11_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
+ i->usri11_last_logon = nt_time_to_unix(i21->last_logon);
+ i->usri11_last_logoff = nt_time_to_unix(i21->last_logoff);
+ i->usri11_bad_pw_count = i21->bad_password_count;
+ i->usri11_num_logons = i21->logon_count;
+ i->usri11_logon_server = talloc_strdup(mem_ctx, "\\\\*");
+ i->usri11_country_code = i21->country_code;
+ i->usri11_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
+ i->usri11_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
+ i->usri11_units_per_week = i21->logon_hours.units_per_week;
+ i->usri11_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
+ i->usri11_code_page = i21->code_page;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_20(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ struct USER_INFO_20 *i)
+{
+ ZERO_STRUCTP(i);
+
+ i->usri20_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri20_name);
+ i->usri20_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri20_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri20_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ i->usri20_user_id = i21->rid;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_23(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ struct dom_sid *domain_sid,
+ struct USER_INFO_23 *i)
+{
+ struct dom_sid sid;
+
+ ZERO_STRUCTP(i);
+
+ i->usri23_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri23_name);
+ i->usri23_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri23_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri23_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ if (!sid_compose(&sid, domain_sid, i21->rid)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ i->usri23_user_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
struct rpc_pipe_client *pipe_cli,
struct dom_sid *domain_sid,
@@ -595,10 +1018,15 @@ static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
struct samr_UserInfo21 *info21 = NULL;
struct sec_desc_buf *sec_desc = NULL;
- struct dom_sid sid;
+ uint32_t auth_flag = 0;
struct USER_INFO_0 info0;
+ struct USER_INFO_1 info1;
+ struct USER_INFO_2 info2;
+ struct USER_INFO_3 info3;
+ struct USER_INFO_4 info4;
struct USER_INFO_10 info10;
+ struct USER_INFO_11 info11;
struct USER_INFO_20 info20;
struct USER_INFO_23 info23;
@@ -607,6 +1035,7 @@ static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
case 1:
case 2:
case 3:
+ case 4:
case 10:
case 11:
case 20:
@@ -630,73 +1059,86 @@ static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
domain_handle,
builtin_handle,
user_name,
+ domain_sid,
rid,
level,
&info21,
- &sec_desc);
+ &sec_desc,
+ &auth_flag);
if (!NT_STATUS_IS_OK(status)) {
goto done;
}
switch (level) {
- case 10:
- info10.usri10_name = talloc_strdup(mem_ctx, user_name);
- NT_STATUS_HAVE_NO_MEMORY(info10.usri10_name);
-
- info10.usri10_comment = talloc_strdup(mem_ctx,
- info21->description.string);
+ case 0:
+ /* already returned above */
+ break;
+ case 1:
+ status = info21_to_USER_INFO_1(mem_ctx, info21, &info1);
+ NT_STATUS_NOT_OK_RETURN(status);
- info10.usri10_full_name = talloc_strdup(mem_ctx,
- info21->full_name.string);
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_1, info1,
+ (struct USER_INFO_1 **)buffer, num_entries);
- info10.usri10_usr_comment = talloc_strdup(mem_ctx,
- info21->comment.string);
+ break;
+ case 2:
+ status = info21_to_USER_INFO_2(mem_ctx, info21, auth_flag, &info2);
+ NT_STATUS_NOT_OK_RETURN(status);
- ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, info10,
- (struct USER_INFO_10 **)buffer, num_entries);
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_2, info2,
+ (struct USER_INFO_2 **)buffer, num_entries);
break;
+ case 3:
+ status = info21_to_USER_INFO_3(mem_ctx, info21, auth_flag, &info3);
+ NT_STATUS_NOT_OK_RETURN(status);
- case 20:
- info20.usri20_name = talloc_strdup(mem_ctx, user_name);
- NT_STATUS_HAVE_NO_MEMORY(info20.usri20_name);
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_3, info3,
+ (struct USER_INFO_3 **)buffer, num_entries);
- info20.usri20_comment = talloc_strdup(mem_ctx,
- info21->description.string);
+ break;
+ case 4:
+ status = info21_to_USER_INFO_4(mem_ctx, info21, auth_flag, domain_sid, &info4);
+ NT_STATUS_NOT_OK_RETURN(status);
- info20.usri20_full_name = talloc_strdup(mem_ctx,
- info21->full_name.string);
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_4, info4,
+ (struct USER_INFO_4 **)buffer, num_entries);
- info20.usri20_flags = info21->acct_flags;
- info20.usri20_user_id = rid;
+ break;
+ case 10:
+ status = info21_to_USER_INFO_10(mem_ctx, info21, &info10);
+ NT_STATUS_NOT_OK_RETURN(status);
- ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, info20,
- (struct USER_INFO_20 **)buffer, num_entries);
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, info10,
+ (struct USER_INFO_10 **)buffer, num_entries);
break;
- case 23:
- info23.usri23_name = talloc_strdup(mem_ctx, user_name);
- NT_STATUS_HAVE_NO_MEMORY(info23.usri23_name);
-
- info23.usri23_comment = talloc_strdup(mem_ctx,
- info21->description.string);
+ case 11:
+ status = info21_to_USER_INFO_11(mem_ctx, info21, auth_flag, &info11);
+ NT_STATUS_NOT_OK_RETURN(status);
- info23.usri23_full_name = talloc_strdup(mem_ctx,
- info21->full_name.string);
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_11, info11,
+ (struct USER_INFO_11 **)buffer, num_entries);
- info23.usri23_flags = info21->acct_flags;
+ break;
+ case 20:
+ status = info21_to_USER_INFO_20(mem_ctx, info21, &info20);
+ NT_STATUS_NOT_OK_RETURN(status);
- if (!sid_compose(&sid, domain_sid, rid)) {
- return NT_STATUS_NO_MEMORY;
- }
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, info20,
+ (struct USER_INFO_20 **)buffer, num_entries);
- info23.usri23_user_sid =
- (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
+ break;
+ case 23:
+ status = info21_to_USER_INFO_23(mem_ctx, info21, domain_sid, &info23);
+ NT_STATUS_NOT_OK_RETURN(status);
ADD_TO_ARRAY(mem_ctx, struct USER_INFO_23, info23,
(struct USER_INFO_23 **)buffer, num_entries);
break;
+ default:
+ return NT_STATUS_INVALID_LEVEL;
}
done:
@@ -713,7 +1155,7 @@ WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
struct rpc_pipe_client *pipe_cli = NULL;
struct policy_handle connect_handle;
struct dom_sid2 *domain_sid = NULL;
- struct policy_handle domain_handle;
+ struct policy_handle domain_handle, builtin_handle;
struct samr_SamArray *sam = NULL;
uint32_t filter = ACB_NORMAL;
int i;
@@ -724,6 +1166,7 @@ WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
ZERO_STRUCT(connect_handle);
ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(builtin_handle);
if (!r->out.buffer) {
return WERR_INVALID_PARAM;
@@ -734,16 +1177,17 @@ WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
switch (r->in.level) {
case 0:
- case 10:
- case 20:
- case 23:
- break;
case 1:
case 2:
case 3:
+ case 4:
+ case 10:
case 11:
+ case 20:
+ case 23:
+ break;
default:
- return WERR_NOT_SUPPORTED;
+ return WERR_UNKNOWN_LEVEL;
}
werr = libnetapi_open_pipe(ctx, r->in.server_name,
@@ -754,6 +1198,17 @@ WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
goto done;
}
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
+ SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
werr = libnetapi_samr_open_domain(ctx, pipe_cli,
SAMR_ACCESS_ENUM_DOMAINS |
SAMR_ACCESS_OPEN_DOMAIN,
@@ -805,7 +1260,7 @@ WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
domain_sid,
&domain_handle,
- NULL, /*&builtin_handle, */
+ &builtin_handle,
sam->entries[i].name.string,
sam->entries[i].idx,
r->in.level,
@@ -828,6 +1283,7 @@ WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
if (ctx->disable_policy_handle_cache) {
libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
libnetapi_samr_close_connect_handle(ctx, &connect_handle);
}
}
@@ -1151,13 +1607,17 @@ WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
switch (r->in.level) {
case 0:
- /* case 1: */
+ case 1:
+ case 2:
+ case 3:
+ case 4:
case 10:
+ case 11:
case 20:
case 23:
break;
default:
- werr = WERR_NOT_SUPPORTED;
+ werr = WERR_UNKNOWN_LEVEL;
goto done;
}
@@ -1259,7 +1719,7 @@ WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
struct lsa_String lsa_account_name;
struct dom_sid2 *domain_sid = NULL;
struct samr_Ids user_rids, name_types;
- union samr_UserInfo user_info;
+ uint32_t user_mask = 0;
struct USER_INFO_X uX;
@@ -1274,11 +1734,41 @@ WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
switch (r->in.level) {
case 0:
+ case 1003:
+ user_mask = SAMR_USER_ACCESS_SET_PASSWORD;
+ break;
+ case 1006:
case 1007:
+ case 1009:
+ case 1011:
+ case 1014:
+ case 1052:
+ case 1053:
+ user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
break;
- default:
+ case 1012:
+ case 1024:
+ user_mask = SAMR_USER_ACCESS_SET_LOC_COM;
+ case 1051:
+ user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES |
+ SAMR_USER_ACCESS_GET_GROUPS;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 21:
+ case 22:
+ case 1005:
+ case 1008:
+ case 1010:
+ case 1017:
+ case 1020:
werr = WERR_NOT_SUPPORTED;
goto done;
+ default:
+ werr = WERR_UNKNOWN_LEVEL;
+ goto done;
}
werr = libnetapi_open_pipe(ctx, r->in.server_name,
@@ -1327,7 +1817,7 @@ WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
status = rpccli_samr_OpenUser(pipe_cli, ctx,
&domain_handle,
- SAMR_USER_ACCESS_SET_ATTRIBUTES,
+ user_mask,
user_rids.ids[0],
&user_handle);
if (!NT_STATUS_IS_OK(status)) {
@@ -1341,12 +1831,10 @@ WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
goto done;
}
- convert_USER_INFO_X_to_samr_user_info21(&uX, &user_info.info21);
-
- status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
- &user_handle,
- 21,
- &user_info);
+ status = set_user_info_USER_INFO_X(ctx, pipe_cli,
+ &cli->user_session_key,
+ &user_handle,
+ &uX);
if (!NT_STATUS_IS_OK(status)) {
werr = ntstatus_to_werror(status);
goto done;
@@ -2244,3 +2732,194 @@ WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
{
LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsSet);
}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS add_GROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ const char *group_name,
+ uint32_t attributes,
+ uint8_t **buffer,
+ uint32_t *num_entries)
+{
+ struct GROUP_USERS_INFO_0 u0;
+ struct GROUP_USERS_INFO_1 u1;
+
+ switch (level) {
+ case 0:
+ u0.grui0_name = talloc_strdup(mem_ctx, group_name);
+ NT_STATUS_HAVE_NO_MEMORY(u0.grui0_name);
+
+ ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_0, u0,
+ (struct GROUP_USERS_INFO_0 **)buffer, num_entries);
+ break;
+ case 1:
+ u1.grui1_name = talloc_strdup(mem_ctx, group_name);
+ NT_STATUS_HAVE_NO_MEMORY(u1.grui1_name);
+
+ u1.grui1_attributes = attributes;
+
+ ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_1, u1,
+ (struct GROUP_USERS_INFO_1 **)buffer, num_entries);
+ break;
+ default:
+ return NT_STATUS_INVALID_INFO_CLASS;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
+ struct NetUserGetGroups *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle, domain_handle, user_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct samr_Ids user_rids, name_types;
+ struct samr_RidWithAttributeArray *rid_array = NULL;
+ struct lsa_Strings names;
+ struct samr_Ids types;
+ uint32_t *rids = NULL;
+
+ int i;
+ uint32_t entries_read = 0;
+
+ NTSTATUS status = NT_STATUS_OK;
+ WERROR werr;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ *r->out.buffer = NULL;
+ *r->out.entries_read = 0;
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.user_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &user_rids,
+ &name_types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_OpenUser(pipe_cli, ctx,
+ &domain_handle,
+ SAMR_USER_ACCESS_GET_GROUPS,
+ user_rids.ids[0],
+ &user_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
+ &user_handle,
+ &rid_array);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ rids = talloc_array(ctx, uint32_t, rid_array->count);
+ if (!rids) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+
+ for (i=0; i < rid_array->count; i++) {
+ rids[i] = rid_array->rids[i].rid;
+ }
+
+ status = rpccli_samr_LookupRids(pipe_cli, ctx,
+ &domain_handle,
+ rid_array->count,
+ rids,
+ &names,
+ &types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ for (i=0; i < rid_array->count; i++) {
+ status = add_GROUP_USERS_INFO_X_buffer(ctx,
+ r->in.level,
+ names.names[i].string,
+ rid_array->rids[i].attributes,
+ r->out.buffer,
+ &entries_read);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ if (r->out.entries_read) {
+ *r->out.entries_read = entries_read;
+ }
+ if (r->out.total_entries) {
+ *r->out.total_entries = entries_read;
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
+ struct NetUserGetGroups *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetGroups);
+}
diff --git a/source3/lib/time.c b/source3/lib/time.c
index 9db88b3fc8..8cefef6e23 100644
--- a/source3/lib/time.c
+++ b/source3/lib/time.c
@@ -826,14 +826,10 @@ void put_long_date(char *p, time_t t)
structure.
****************************************************************************/
-time_t get_create_time(const SMB_STRUCT_STAT *st,bool fake_dirs)
+static time_t calc_create_time(const SMB_STRUCT_STAT *st)
{
time_t ret, ret1;
- if(S_ISDIR(st->st_mode) && fake_dirs) {
- return (time_t)315493200L; /* 1/1/1980 */
- }
-
ret = MIN(st->st_ctime, st->st_mtime);
ret1 = MIN(ret, st->st_atime);
@@ -848,12 +844,42 @@ time_t get_create_time(const SMB_STRUCT_STAT *st,bool fake_dirs)
return ret;
}
-struct timespec get_create_timespec(const SMB_STRUCT_STAT *st,bool fake_dirs)
+/****************************************************************************
+ Return the 'create time' from a stat struct if it exists (birthtime) or else
+ use the best approximation.
+****************************************************************************/
+
+struct timespec get_create_timespec(const SMB_STRUCT_STAT *pst,bool fake_dirs)
{
- struct timespec ts;
- ts.tv_sec = get_create_time(st, fake_dirs);
- ts.tv_nsec = 0;
- return ts;
+ struct timespec ret;
+
+ if(S_ISDIR(pst->st_mode) && fake_dirs) {
+ ret.tv_sec = 315493200L; /* 1/1/1980 */
+ ret.tv_nsec = 0;
+ return ret;
+ }
+
+#if defined(HAVE_STAT_ST_BIRTHTIMESPEC)
+ ret = pst->st_birthtimespec;
+#elif defined(HAVE_STAT_ST_BIRTHTIMENSEC)
+ ret.tv_sec = pst->st_birthtime;
+ ret.tv_nsec = pst->st_birthtimenspec;
+#elif defined(HAVE_STAT_ST_BIRTHTIME)
+ ret.tv_sec = pst->st_birthtime;
+ ret.tv_nsec = 0;
+#else
+ ret.tv_sec = calc_create_time(pst);
+ ret.tv_nsec = 0;
+#endif
+
+ /* Deal with systems that don't initialize birthtime correctly.
+ * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
+ */
+ if (null_timespec(ret)) {
+ ret.tv_sec = calc_create_time(pst);
+ ret.tv_nsec = 0;
+ }
+ return ret;
}
/****************************************************************************
diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c
index 77a50e4221..883f582445 100644
--- a/source3/libads/kerberos_keytab.c
+++ b/source3/libads/kerberos_keytab.c
@@ -161,15 +161,8 @@ int smb_krb5_kt_add_entry_ext(krb5_context context,
for (i = 0; enctypes[i]; i++) {
krb5_keyblock *keyp;
-#if !defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) && !defined(HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK)
-#error krb5_keytab_entry has no key or keyblock member
-#endif
-#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEY /* MIT */
- keyp = &kt_entry.key;
-#endif
-#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */
- keyp = &kt_entry.keyblock;
-#endif
+ keyp = KRB5_KT_KEY(&kt_entry);
+
if (create_kerberos_key_from_string(context, princ, &password, keyp, enctypes[i], no_salt)) {
continue;
}
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index b7a15c558b..a39dee676f 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -1503,10 +1503,23 @@ static WERROR libnet_join_post_processing(TALLOC_CTX *mem_ctx,
return werr;
}
- if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
- saf_store(r->in.domain_name, r->in.dc_name);
+ if (!(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE)) {
+ return WERR_OK;
}
+ saf_store(r->in.domain_name, r->in.dc_name);
+
+#ifdef WITH_ADS
+ if (r->out.domain_is_ad) {
+ ADS_STATUS ads_status;
+
+ ads_status = libnet_join_post_processing_ads(mem_ctx, r);
+ if (!ADS_ERR_OK(ads_status)) {
+ return WERR_GENERAL_FAILURE;
+ }
+ }
+#endif /* WITH_ADS */
+
libnet_join_add_dom_rids_to_builtins(r->out.domain_sid);
return WERR_OK;
@@ -1754,16 +1767,6 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
goto done;
}
-#ifdef WITH_ADS
- if (r->out.domain_is_ad) {
- ads_status = libnet_join_post_processing_ads(mem_ctx, r);
- if (!ADS_ERR_OK(ads_status)) {
- werr = WERR_GENERAL_FAILURE;
- goto done;
- }
- }
-#endif /* WITH_ADS */
-
werr = WERR_OK;
done:
diff --git a/source3/libnet/libnet_keytab.c b/source3/libnet/libnet_keytab.c
index 6447183958..46c17b219c 100644
--- a/source3/libnet/libnet_keytab.c
+++ b/source3/libnet/libnet_keytab.c
@@ -24,16 +24,6 @@
#ifdef HAVE_KRB5
-#ifdef HAVE_KRB5_KEYBLOCK_KEYVALUE /* Heimdal */
-#define KRB5_KEY_TYPE(k) ((k)->keytype)
-#define KRB5_KEY_LENGTH(k) ((k)->keyvalue.length)
-#define KRB5_KEY_DATA(k) ((k)->keyvalue.data)
-#else /* MIT */
-#define KRB5_KEY_TYPE(k) ((k)->enctype)
-#define KRB5_KEY_LENGTH(k) ((k)->length)
-#define KRB5_KEY_DATA(k) ((k)->contents)
-#endif /* HAVE_KRB5_KEYBLOCK_KEYVALUE */
-
/****************************************************************
****************************************************************/
@@ -148,15 +138,7 @@ static krb5_error_code libnet_keytab_remove_entries(krb5_context context,
goto cont;
}
-#if !defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) && !defined(HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK)
-#error krb5_keytab_entry has no key or keyblock member
-#endif
-#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEY /* MIT */
- keyp = &kt_entry.key;
-#endif
-#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */
- keyp = &kt_entry.keyblock;
-#endif
+ keyp = KRB5_KT_KEY(&kt_entry);
if (KRB5_KEY_TYPE(keyp) != enctype) {
goto cont;
@@ -250,15 +232,7 @@ static krb5_error_code libnet_keytab_add_entry(krb5_context context,
return ret;
}
-#if !defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) && !defined(HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK)
-#error krb5_keytab_entry has no key or keyblock member
-#endif
-#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEY /* MIT */
- keyp = &kt_entry.key;
-#endif
-#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */
- keyp = &kt_entry.keyblock;
-#endif
+ keyp = KRB5_KT_KEY(&kt_entry);
if (create_kerberos_key_from_string(context, kt_entry.principal,
&password, keyp, enctype, true))
@@ -364,15 +338,7 @@ struct libnet_keytab_entry *libnet_keytab_search(struct libnet_keytab_context *c
goto cont;
}
-#if !defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) && !defined(HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK)
-#error krb5_keytab_entry has no key or keyblock member
-#endif
-#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEY /* MIT */
- keyp = &kt_entry.key;
-#endif
-#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */
- keyp = &kt_entry.keyblock;
-#endif
+ keyp = KRB5_KT_KEY(&kt_entry);
if (KRB5_KEY_TYPE(keyp) != enctype) {
goto cont;
diff --git a/source3/librpc/gen_ndr/libnetapi.h b/source3/librpc/gen_ndr/libnetapi.h
index 825557d573..33ca253b60 100644
--- a/source3/librpc/gen_ndr/libnetapi.h
+++ b/source3/librpc/gen_ndr/libnetapi.h
@@ -10,7 +10,16 @@
#define _HEADER_libnetapi
#define ERROR_MORE_DATA ( 234L )
-#define ENCRYPTED_PWLEN ( 256 )
+#define USER_PRIV_GUEST ( 0 )
+#define USER_PRIV_USER ( 1 )
+#define USER_PRIV_ADMIN ( 2 )
+#define AF_OP_PRINT ( 0x1 )
+#define AF_OP_COMM ( 0x2 )
+#define AF_OP_SERVER ( 0x4 )
+#define AF_OP_ACCOUNTS ( 0x8 )
+#define AF_SETTABLE_BITS ( (AF_OP_PRINT|AF_OP_COMM|AF_OP_SERVER|AF_OP_ACCOUNTS) )
+#define USER_MAXSTORAGE_UNLIMITED ( (uint32_t)-1L )
+#define ENCRYPTED_PWLEN ( 16 )
#define FILTER_TEMP_DUPLICATE_ACCOUNT ( 0x0001 )
#define FILTER_NORMAL_ACCOUNT ( 0x0002 )
#define FILTER_INTERDOMAIN_TRUST_ACCOUNT ( 0x0008 )
@@ -35,6 +44,20 @@ struct domsid {
uint32_t *sub_auths;
};
+/* bitmap NetJoinFlags */
+#define NETSETUP_JOIN_DOMAIN ( 0x00000001 )
+#define NETSETUP_ACCT_CREATE ( 0x00000002 )
+#define NETSETUP_ACCT_DELETE ( 0x00000004 )
+#define NETSETUP_WIN9X_UPGRADE ( 0x00000010 )
+#define NETSETUP_DOMAIN_JOIN_IF_JOINED ( 0x00000020 )
+#define NETSETUP_JOIN_UNSECURE ( 0x00000040 )
+#define NETSETUP_MACHINE_PWD_PASSED ( 0x00000080 )
+#define NETSETUP_DEFER_SPN_SET ( 0x00000100 )
+#define NETSETUP_JOIN_DC_ACCOUNT ( 0x00000200 )
+#define NETSETUP_JOIN_WITH_NEW_NAME ( 0x00000400 )
+#define NETSETUP_INSTALL_INVOCATION ( 0x00040000 )
+#define NETSETUP_IGNORE_UNSUPPORTED_FLAGS ( 0x10000000 )
+
struct SERVER_INFO_1005 {
const char * sv1005_comment;
};
@@ -149,7 +172,7 @@ struct USER_INFO_4 {
const char * usri4_logon_server;
uint32_t usri4_country_code;
uint32_t usri4_code_page;
- struct dom_sid *usri4_user_sid;/* [unique] */
+ struct domsid *usri4_user_sid;/* [unique] */
uint32_t usri4_primary_group_id;
const char * usri4_profile;
const char * usri4_home_dir_drive;
@@ -339,6 +362,18 @@ struct USER_INFO_X {
const char * usriX_logon_server;
uint32_t usriX_country_code;
uint32_t usriX_code_page;
+ const char * usriX_profile;
+ const char * usriX_home_dir_drive;
+ uint32_t usriX_primary_group_id;
+};
+
+struct GROUP_USERS_INFO_0 {
+ const char * grui0_name;
+};
+
+struct GROUP_USERS_INFO_1 {
+ const char * grui1_name;
+ uint32_t grui1_attributes;
};
struct USER_MODALS_INFO_0 {
@@ -449,15 +484,6 @@ struct GROUP_INFO_1005 {
uint32_t grpi1005_attributes;
};
-struct GROUP_USERS_INFO_0 {
- const char * grui0_name;
-};
-
-struct GROUP_USERS_INFO_1 {
- const char * grui1_name;
- uint32_t grui1_attributes;
-};
-
struct LOCALGROUP_INFO_0 {
const char * lgrpi0_name;
};
@@ -535,6 +561,17 @@ struct TIME_OF_DAY_INFO {
uint32_t tod_weekday;
};
+struct SHARE_INFO_2 {
+ const char * shi2_netname;
+ uint32_t shi2_type;
+ const char * shi2_remark;
+ uint32_t shi2_permissions;
+ uint32_t shi2_max_uses;
+ uint32_t shi2_current_uses;
+ const char * shi2_path;
+ const char * shi2_passwd;
+};
+
struct NetJoinDomain {
struct {
@@ -767,6 +804,24 @@ struct NetUserSetInfo {
};
+struct NetUserGetGroups {
+ struct {
+ const char * server_name;
+ const char * user_name;
+ uint32_t level;
+ uint32_t prefmaxlen;
+ } in;
+
+ struct {
+ uint8_t **buffer;/* [ref] */
+ uint32_t *entries_read;/* [ref] */
+ uint32_t *total_entries;/* [ref] */
+ enum NET_API_STATUS result;
+ } out;
+
+};
+
+
struct NetUserModalsGet {
struct {
const char * server_name;
@@ -1098,4 +1153,19 @@ struct NetRemoteTOD {
};
+
+struct NetShareAdd {
+ struct {
+ const char * server_name;
+ uint32_t level;
+ uint8_t *buffer;/* [ref] */
+ } in;
+
+ struct {
+ uint32_t *parm_err;/* [ref] */
+ enum NET_API_STATUS result;
+ } out;
+
+};
+
#endif /* _HEADER_libnetapi */
diff --git a/source3/librpc/gen_ndr/ndr_libnetapi.c b/source3/librpc/gen_ndr/ndr_libnetapi.c
index 4d4a291a28..4f2579f256 100644
--- a/source3/librpc/gen_ndr/ndr_libnetapi.c
+++ b/source3/librpc/gen_ndr/ndr_libnetapi.c
@@ -87,6 +87,39 @@ _PUBLIC_ void ndr_print_domsid(struct ndr_print *ndr, const char *name, const st
ndr->depth--;
}
+_PUBLIC_ enum ndr_err_code ndr_push_NetJoinFlags(struct ndr_push *ndr, int ndr_flags, uint32_t r)
+{
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r));
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_NetJoinFlags(struct ndr_pull *ndr, int ndr_flags, uint32_t *r)
+{
+ uint32_t v;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+ *r = v;
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_NetJoinFlags(struct ndr_print *ndr, const char *name, uint32_t r)
+{
+ ndr_print_uint32(ndr, name, r);
+ ndr->depth++;
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "NETSETUP_JOIN_DOMAIN", NETSETUP_JOIN_DOMAIN, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "NETSETUP_ACCT_CREATE", NETSETUP_ACCT_CREATE, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "NETSETUP_ACCT_DELETE", NETSETUP_ACCT_DELETE, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "NETSETUP_WIN9X_UPGRADE", NETSETUP_WIN9X_UPGRADE, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "NETSETUP_DOMAIN_JOIN_IF_JOINED", NETSETUP_DOMAIN_JOIN_IF_JOINED, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "NETSETUP_JOIN_UNSECURE", NETSETUP_JOIN_UNSECURE, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "NETSETUP_MACHINE_PWD_PASSED", NETSETUP_MACHINE_PWD_PASSED, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "NETSETUP_DEFER_SPN_SET", NETSETUP_DEFER_SPN_SET, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "NETSETUP_JOIN_DC_ACCOUNT", NETSETUP_JOIN_DC_ACCOUNT, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "NETSETUP_JOIN_WITH_NEW_NAME", NETSETUP_JOIN_WITH_NEW_NAME, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "NETSETUP_INSTALL_INVOCATION", NETSETUP_INSTALL_INVOCATION, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "NETSETUP_IGNORE_UNSUPPORTED_FLAGS", NETSETUP_IGNORE_UNSUPPORTED_FLAGS, r);
+ ndr->depth--;
+}
+
_PUBLIC_ enum ndr_err_code ndr_push_SERVER_INFO_1005(struct ndr_push *ndr, int ndr_flags, const struct SERVER_INFO_1005 *r)
{
if (ndr_flags & NDR_SCALARS) {
@@ -543,7 +576,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_USER_INFO_4(struct ndr_push *ndr, int ndr_fl
NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, *r->usri4_logon_hours));
}
if (r->usri4_user_sid) {
- NDR_CHECK(ndr_push_dom_sid(ndr, NDR_SCALARS|NDR_BUFFERS, r->usri4_user_sid));
+ NDR_CHECK(ndr_push_domsid(ndr, NDR_SCALARS, r->usri4_user_sid));
}
}
return NDR_ERR_SUCCESS;
@@ -607,7 +640,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_USER_INFO_4(struct ndr_pull *ndr, int ndr_fl
if (r->usri4_user_sid) {
_mem_save_usri4_user_sid_0 = NDR_PULL_GET_MEM_CTX(ndr);
NDR_PULL_SET_MEM_CTX(ndr, r->usri4_user_sid, 0);
- NDR_CHECK(ndr_pull_dom_sid(ndr, NDR_SCALARS|NDR_BUFFERS, r->usri4_user_sid));
+ NDR_CHECK(ndr_pull_domsid(ndr, NDR_SCALARS, r->usri4_user_sid));
NDR_PULL_SET_MEM_CTX(ndr, _mem_save_usri4_user_sid_0, 0);
}
}
@@ -650,7 +683,7 @@ _PUBLIC_ void ndr_print_USER_INFO_4(struct ndr_print *ndr, const char *name, con
ndr_print_ptr(ndr, "usri4_user_sid", r->usri4_user_sid);
ndr->depth++;
if (r->usri4_user_sid) {
- ndr_print_dom_sid(ndr, "usri4_user_sid", r->usri4_user_sid);
+ ndr_print_domsid(ndr, "usri4_user_sid", r->usri4_user_sid);
}
ndr->depth--;
ndr_print_uint32(ndr, "usri4_primary_group_id", r->usri4_primary_group_id);
@@ -1716,6 +1749,9 @@ _PUBLIC_ enum ndr_err_code ndr_push_USER_INFO_X(struct ndr_push *ndr, int ndr_fl
NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->usriX_logon_server));
NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->usriX_country_code));
NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->usriX_code_page));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->usriX_profile));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->usriX_home_dir_drive));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->usriX_primary_group_id));
}
if (ndr_flags & NDR_BUFFERS) {
if (r->usriX_logon_hours) {
@@ -1760,6 +1796,9 @@ _PUBLIC_ enum ndr_err_code ndr_pull_USER_INFO_X(struct ndr_pull *ndr, int ndr_fl
NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->usriX_logon_server));
NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->usriX_country_code));
NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->usriX_code_page));
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->usriX_profile));
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->usriX_home_dir_drive));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->usriX_primary_group_id));
}
if (ndr_flags & NDR_BUFFERS) {
if (r->usriX_logon_hours) {
@@ -1805,6 +1844,72 @@ _PUBLIC_ void ndr_print_USER_INFO_X(struct ndr_print *ndr, const char *name, con
ndr_print_string(ndr, "usriX_logon_server", r->usriX_logon_server);
ndr_print_uint32(ndr, "usriX_country_code", r->usriX_country_code);
ndr_print_uint32(ndr, "usriX_code_page", r->usriX_code_page);
+ ndr_print_string(ndr, "usriX_profile", r->usriX_profile);
+ ndr_print_string(ndr, "usriX_home_dir_drive", r->usriX_home_dir_drive);
+ ndr_print_uint32(ndr, "usriX_primary_group_id", r->usriX_primary_group_id);
+ ndr->depth--;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_GROUP_USERS_INFO_0(struct ndr_push *ndr, int ndr_flags, const struct GROUP_USERS_INFO_0 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->grui0_name));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_GROUP_USERS_INFO_0(struct ndr_pull *ndr, int ndr_flags, struct GROUP_USERS_INFO_0 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->grui0_name));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_GROUP_USERS_INFO_0(struct ndr_print *ndr, const char *name, const struct GROUP_USERS_INFO_0 *r)
+{
+ ndr_print_struct(ndr, name, "GROUP_USERS_INFO_0");
+ ndr->depth++;
+ ndr_print_string(ndr, "grui0_name", r->grui0_name);
+ ndr->depth--;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_GROUP_USERS_INFO_1(struct ndr_push *ndr, int ndr_flags, const struct GROUP_USERS_INFO_1 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->grui1_name));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->grui1_attributes));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_GROUP_USERS_INFO_1(struct ndr_pull *ndr, int ndr_flags, struct GROUP_USERS_INFO_1 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->grui1_name));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->grui1_attributes));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_GROUP_USERS_INFO_1(struct ndr_print *ndr, const char *name, const struct GROUP_USERS_INFO_1 *r)
+{
+ ndr_print_struct(ndr, name, "GROUP_USERS_INFO_1");
+ ndr->depth++;
+ ndr_print_string(ndr, "grui1_name", r->grui1_name);
+ ndr_print_uint32(ndr, "grui1_attributes", r->grui1_attributes);
ndr->depth--;
}
@@ -1937,69 +2042,6 @@ _PUBLIC_ void ndr_print_NET_DISPLAY_GROUP(struct ndr_print *ndr, const char *nam
ndr->depth--;
}
-_PUBLIC_ enum ndr_err_code ndr_push_GROUP_USERS_INFO_0(struct ndr_push *ndr, int ndr_flags, const struct GROUP_USERS_INFO_0 *r)
-{
- if (ndr_flags & NDR_SCALARS) {
- NDR_CHECK(ndr_push_align(ndr, 4));
- NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->grui0_name));
- }
- if (ndr_flags & NDR_BUFFERS) {
- }
- return NDR_ERR_SUCCESS;
-}
-
-_PUBLIC_ enum ndr_err_code ndr_pull_GROUP_USERS_INFO_0(struct ndr_pull *ndr, int ndr_flags, struct GROUP_USERS_INFO_0 *r)
-{
- if (ndr_flags & NDR_SCALARS) {
- NDR_CHECK(ndr_pull_align(ndr, 4));
- NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->grui0_name));
- }
- if (ndr_flags & NDR_BUFFERS) {
- }
- return NDR_ERR_SUCCESS;
-}
-
-_PUBLIC_ void ndr_print_GROUP_USERS_INFO_0(struct ndr_print *ndr, const char *name, const struct GROUP_USERS_INFO_0 *r)
-{
- ndr_print_struct(ndr, name, "GROUP_USERS_INFO_0");
- ndr->depth++;
- ndr_print_string(ndr, "grui0_name", r->grui0_name);
- ndr->depth--;
-}
-
-_PUBLIC_ enum ndr_err_code ndr_push_GROUP_USERS_INFO_1(struct ndr_push *ndr, int ndr_flags, const struct GROUP_USERS_INFO_1 *r)
-{
- if (ndr_flags & NDR_SCALARS) {
- NDR_CHECK(ndr_push_align(ndr, 4));
- NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->grui1_name));
- NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->grui1_attributes));
- }
- if (ndr_flags & NDR_BUFFERS) {
- }
- return NDR_ERR_SUCCESS;
-}
-
-_PUBLIC_ enum ndr_err_code ndr_pull_GROUP_USERS_INFO_1(struct ndr_pull *ndr, int ndr_flags, struct GROUP_USERS_INFO_1 *r)
-{
- if (ndr_flags & NDR_SCALARS) {
- NDR_CHECK(ndr_pull_align(ndr, 4));
- NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->grui1_name));
- NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->grui1_attributes));
- }
- if (ndr_flags & NDR_BUFFERS) {
- }
- return NDR_ERR_SUCCESS;
-}
-
-_PUBLIC_ void ndr_print_GROUP_USERS_INFO_1(struct ndr_print *ndr, const char *name, const struct GROUP_USERS_INFO_1 *r)
-{
- ndr_print_struct(ndr, name, "GROUP_USERS_INFO_1");
- ndr->depth++;
- ndr_print_string(ndr, "grui1_name", r->grui1_name);
- ndr_print_uint32(ndr, "grui1_attributes", r->grui1_attributes);
- ndr->depth--;
-}
-
_PUBLIC_ void ndr_print_NetJoinDomain(struct ndr_print *ndr, const char *name, int flags, const struct NetJoinDomain *r)
{
ndr_print_struct(ndr, name, "NetJoinDomain");
@@ -2038,7 +2080,7 @@ _PUBLIC_ void ndr_print_NetJoinDomain(struct ndr_print *ndr, const char *name, i
ndr_print_string(ndr, "password", r->in.password);
}
ndr->depth--;
- ndr_print_uint32(ndr, "join_flags", r->in.join_flags);
+ ndr_print_NetJoinFlags(ndr, "join_flags", r->in.join_flags);
ndr->depth--;
}
if (flags & NDR_OUT) {
@@ -2078,7 +2120,7 @@ _PUBLIC_ void ndr_print_NetUnjoinDomain(struct ndr_print *ndr, const char *name,
ndr_print_string(ndr, "password", r->in.password);
}
ndr->depth--;
- ndr_print_uint32(ndr, "unjoin_flags", r->in.unjoin_flags);
+ ndr_print_NetJoinFlags(ndr, "unjoin_flags", r->in.unjoin_flags);
ndr->depth--;
}
if (flags & NDR_OUT) {
@@ -2613,6 +2655,48 @@ _PUBLIC_ void ndr_print_NetUserSetInfo(struct ndr_print *ndr, const char *name,
ndr->depth--;
}
+_PUBLIC_ void ndr_print_NetUserGetGroups(struct ndr_print *ndr, const char *name, int flags, const struct NetUserGetGroups *r)
+{
+ ndr_print_struct(ndr, name, "NetUserGetGroups");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "NetUserGetGroups");
+ ndr->depth++;
+ ndr_print_string(ndr, "server_name", r->in.server_name);
+ ndr_print_string(ndr, "user_name", r->in.user_name);
+ ndr_print_uint32(ndr, "level", r->in.level);
+ ndr_print_uint32(ndr, "prefmaxlen", r->in.prefmaxlen);
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "NetUserGetGroups");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "buffer", r->out.buffer);
+ ndr->depth++;
+ ndr_print_ptr(ndr, "buffer", *r->out.buffer);
+ ndr->depth++;
+ if (*r->out.buffer) {
+ ndr_print_uint8(ndr, "buffer", **r->out.buffer);
+ }
+ ndr->depth--;
+ ndr->depth--;
+ ndr_print_ptr(ndr, "entries_read", r->out.entries_read);
+ ndr->depth++;
+ ndr_print_uint32(ndr, "entries_read", *r->out.entries_read);
+ ndr->depth--;
+ ndr_print_ptr(ndr, "total_entries", r->out.total_entries);
+ ndr->depth++;
+ ndr_print_uint32(ndr, "total_entries", *r->out.total_entries);
+ ndr->depth--;
+ ndr_print_NET_API_STATUS(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
_PUBLIC_ void ndr_print_NetUserModalsGet(struct ndr_print *ndr, const char *name, int flags, const struct NetUserModalsGet *r)
{
ndr_print_struct(ndr, name, "NetUserModalsGet");
@@ -3313,3 +3397,34 @@ _PUBLIC_ void ndr_print_NetRemoteTOD(struct ndr_print *ndr, const char *name, in
ndr->depth--;
}
+_PUBLIC_ void ndr_print_NetShareAdd(struct ndr_print *ndr, const char *name, int flags, const struct NetShareAdd *r)
+{
+ ndr_print_struct(ndr, name, "NetShareAdd");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "NetShareAdd");
+ ndr->depth++;
+ ndr_print_string(ndr, "server_name", r->in.server_name);
+ ndr_print_uint32(ndr, "level", r->in.level);
+ ndr_print_ptr(ndr, "buffer", r->in.buffer);
+ ndr->depth++;
+ ndr_print_uint8(ndr, "buffer", *r->in.buffer);
+ ndr->depth--;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "NetShareAdd");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "parm_err", r->out.parm_err);
+ ndr->depth++;
+ ndr_print_uint32(ndr, "parm_err", *r->out.parm_err);
+ ndr->depth--;
+ ndr_print_NET_API_STATUS(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
diff --git a/source3/librpc/gen_ndr/ndr_libnetapi.h b/source3/librpc/gen_ndr/ndr_libnetapi.h
index 9b5d8e7c35..8324ac3188 100644
--- a/source3/librpc/gen_ndr/ndr_libnetapi.h
+++ b/source3/librpc/gen_ndr/ndr_libnetapi.h
@@ -36,55 +36,62 @@
#define NDR_NETUSERSETINFO (0x0e)
-#define NDR_NETUSERMODALSGET (0x0f)
+#define NDR_NETUSERGETGROUPS (0x0f)
-#define NDR_NETUSERMODALSSET (0x10)
+#define NDR_NETUSERMODALSGET (0x10)
-#define NDR_NETQUERYDISPLAYINFORMATION (0x11)
+#define NDR_NETUSERMODALSSET (0x11)
-#define NDR_NETGROUPADD (0x12)
+#define NDR_NETQUERYDISPLAYINFORMATION (0x12)
-#define NDR_NETGROUPDEL (0x13)
+#define NDR_NETGROUPADD (0x13)
-#define NDR_NETGROUPENUM (0x14)
+#define NDR_NETGROUPDEL (0x14)
-#define NDR_NETGROUPSETINFO (0x15)
+#define NDR_NETGROUPENUM (0x15)
-#define NDR_NETGROUPGETINFO (0x16)
+#define NDR_NETGROUPSETINFO (0x16)
-#define NDR_NETGROUPADDUSER (0x17)
+#define NDR_NETGROUPGETINFO (0x17)
-#define NDR_NETGROUPDELUSER (0x18)
+#define NDR_NETGROUPADDUSER (0x18)
-#define NDR_NETGROUPGETUSERS (0x19)
+#define NDR_NETGROUPDELUSER (0x19)
-#define NDR_NETLOCALGROUPADD (0x1a)
+#define NDR_NETGROUPGETUSERS (0x1a)
-#define NDR_NETLOCALGROUPDEL (0x1b)
+#define NDR_NETLOCALGROUPADD (0x1b)
-#define NDR_NETLOCALGROUPGETINFO (0x1c)
+#define NDR_NETLOCALGROUPDEL (0x1c)
-#define NDR_NETLOCALGROUPSETINFO (0x1d)
+#define NDR_NETLOCALGROUPGETINFO (0x1d)
-#define NDR_NETLOCALGROUPENUM (0x1e)
+#define NDR_NETLOCALGROUPSETINFO (0x1e)
-#define NDR_NETLOCALGROUPADDMEMBERS (0x1f)
+#define NDR_NETLOCALGROUPENUM (0x1f)
-#define NDR_NETLOCALGROUPDELMEMBERS (0x20)
+#define NDR_NETLOCALGROUPADDMEMBERS (0x20)
-#define NDR_NETLOCALGROUPGETMEMBERS (0x21)
+#define NDR_NETLOCALGROUPDELMEMBERS (0x21)
-#define NDR_NETLOCALGROUPSETMEMBERS (0x22)
+#define NDR_NETLOCALGROUPGETMEMBERS (0x22)
-#define NDR_NETREMOTETOD (0x23)
+#define NDR_NETLOCALGROUPSETMEMBERS (0x23)
-#define NDR_LIBNETAPI_CALL_COUNT (36)
+#define NDR_NETREMOTETOD (0x24)
+
+#define NDR_NETSHAREADD (0x25)
+
+#define NDR_LIBNETAPI_CALL_COUNT (38)
enum ndr_err_code ndr_push_NET_API_STATUS(struct ndr_push *ndr, int ndr_flags, enum NET_API_STATUS r);
enum ndr_err_code ndr_pull_NET_API_STATUS(struct ndr_pull *ndr, int ndr_flags, enum NET_API_STATUS *r);
void ndr_print_NET_API_STATUS(struct ndr_print *ndr, const char *name, enum NET_API_STATUS r);
enum ndr_err_code ndr_push_domsid(struct ndr_push *ndr, int ndr_flags, const struct domsid *r);
enum ndr_err_code ndr_pull_domsid(struct ndr_pull *ndr, int ndr_flags, struct domsid *r);
void ndr_print_domsid(struct ndr_print *ndr, const char *name, const struct domsid *r);
+enum ndr_err_code ndr_push_NetJoinFlags(struct ndr_push *ndr, int ndr_flags, uint32_t r);
+enum ndr_err_code ndr_pull_NetJoinFlags(struct ndr_pull *ndr, int ndr_flags, uint32_t *r);
+void ndr_print_NetJoinFlags(struct ndr_print *ndr, const char *name, uint32_t r);
enum ndr_err_code ndr_push_SERVER_INFO_1005(struct ndr_push *ndr, int ndr_flags, const struct SERVER_INFO_1005 *r);
enum ndr_err_code ndr_pull_SERVER_INFO_1005(struct ndr_pull *ndr, int ndr_flags, struct SERVER_INFO_1005 *r);
void ndr_print_SERVER_INFO_1005(struct ndr_print *ndr, const char *name, const struct SERVER_INFO_1005 *r);
@@ -187,6 +194,12 @@ void ndr_print_USER_INFO_1053(struct ndr_print *ndr, const char *name, const str
enum ndr_err_code ndr_push_USER_INFO_X(struct ndr_push *ndr, int ndr_flags, const struct USER_INFO_X *r);
enum ndr_err_code ndr_pull_USER_INFO_X(struct ndr_pull *ndr, int ndr_flags, struct USER_INFO_X *r);
void ndr_print_USER_INFO_X(struct ndr_print *ndr, const char *name, const struct USER_INFO_X *r);
+enum ndr_err_code ndr_push_GROUP_USERS_INFO_0(struct ndr_push *ndr, int ndr_flags, const struct GROUP_USERS_INFO_0 *r);
+enum ndr_err_code ndr_pull_GROUP_USERS_INFO_0(struct ndr_pull *ndr, int ndr_flags, struct GROUP_USERS_INFO_0 *r);
+void ndr_print_GROUP_USERS_INFO_0(struct ndr_print *ndr, const char *name, const struct GROUP_USERS_INFO_0 *r);
+enum ndr_err_code ndr_push_GROUP_USERS_INFO_1(struct ndr_push *ndr, int ndr_flags, const struct GROUP_USERS_INFO_1 *r);
+enum ndr_err_code ndr_pull_GROUP_USERS_INFO_1(struct ndr_pull *ndr, int ndr_flags, struct GROUP_USERS_INFO_1 *r);
+void ndr_print_GROUP_USERS_INFO_1(struct ndr_print *ndr, const char *name, const struct GROUP_USERS_INFO_1 *r);
enum ndr_err_code ndr_push_NET_DISPLAY_USER(struct ndr_push *ndr, int ndr_flags, const struct NET_DISPLAY_USER *r);
enum ndr_err_code ndr_pull_NET_DISPLAY_USER(struct ndr_pull *ndr, int ndr_flags, struct NET_DISPLAY_USER *r);
void ndr_print_NET_DISPLAY_USER(struct ndr_print *ndr, const char *name, const struct NET_DISPLAY_USER *r);
@@ -196,12 +209,6 @@ void ndr_print_NET_DISPLAY_MACHINE(struct ndr_print *ndr, const char *name, cons
enum ndr_err_code ndr_push_NET_DISPLAY_GROUP(struct ndr_push *ndr, int ndr_flags, const struct NET_DISPLAY_GROUP *r);
enum ndr_err_code ndr_pull_NET_DISPLAY_GROUP(struct ndr_pull *ndr, int ndr_flags, struct NET_DISPLAY_GROUP *r);
void ndr_print_NET_DISPLAY_GROUP(struct ndr_print *ndr, const char *name, const struct NET_DISPLAY_GROUP *r);
-enum ndr_err_code ndr_push_GROUP_USERS_INFO_0(struct ndr_push *ndr, int ndr_flags, const struct GROUP_USERS_INFO_0 *r);
-enum ndr_err_code ndr_pull_GROUP_USERS_INFO_0(struct ndr_pull *ndr, int ndr_flags, struct GROUP_USERS_INFO_0 *r);
-void ndr_print_GROUP_USERS_INFO_0(struct ndr_print *ndr, const char *name, const struct GROUP_USERS_INFO_0 *r);
-enum ndr_err_code ndr_push_GROUP_USERS_INFO_1(struct ndr_push *ndr, int ndr_flags, const struct GROUP_USERS_INFO_1 *r);
-enum ndr_err_code ndr_pull_GROUP_USERS_INFO_1(struct ndr_pull *ndr, int ndr_flags, struct GROUP_USERS_INFO_1 *r);
-void ndr_print_GROUP_USERS_INFO_1(struct ndr_print *ndr, const char *name, const struct GROUP_USERS_INFO_1 *r);
enum ndr_err_code ndr_push_NetJoinDomain(struct ndr_push *ndr, int flags, const struct NetJoinDomain *r);
enum ndr_err_code ndr_pull_NetJoinDomain(struct ndr_pull *ndr, int flags, struct NetJoinDomain *r);
void ndr_print_NetJoinDomain(struct ndr_print *ndr, const char *name, int flags, const struct NetJoinDomain *r);
@@ -247,6 +254,9 @@ void ndr_print_NetUserGetInfo(struct ndr_print *ndr, const char *name, int flags
enum ndr_err_code ndr_push_NetUserSetInfo(struct ndr_push *ndr, int flags, const struct NetUserSetInfo *r);
enum ndr_err_code ndr_pull_NetUserSetInfo(struct ndr_pull *ndr, int flags, struct NetUserSetInfo *r);
void ndr_print_NetUserSetInfo(struct ndr_print *ndr, const char *name, int flags, const struct NetUserSetInfo *r);
+enum ndr_err_code ndr_push_NetUserGetGroups(struct ndr_push *ndr, int flags, const struct NetUserGetGroups *r);
+enum ndr_err_code ndr_pull_NetUserGetGroups(struct ndr_pull *ndr, int flags, struct NetUserGetGroups *r);
+void ndr_print_NetUserGetGroups(struct ndr_print *ndr, const char *name, int flags, const struct NetUserGetGroups *r);
enum ndr_err_code ndr_push_NetUserModalsGet(struct ndr_push *ndr, int flags, const struct NetUserModalsGet *r);
enum ndr_err_code ndr_pull_NetUserModalsGet(struct ndr_pull *ndr, int flags, struct NetUserModalsGet *r);
void ndr_print_NetUserModalsGet(struct ndr_print *ndr, const char *name, int flags, const struct NetUserModalsGet *r);
@@ -310,4 +320,7 @@ void ndr_print_NetLocalGroupSetMembers(struct ndr_print *ndr, const char *name,
enum ndr_err_code ndr_push_NetRemoteTOD(struct ndr_push *ndr, int flags, const struct NetRemoteTOD *r);
enum ndr_err_code ndr_pull_NetRemoteTOD(struct ndr_pull *ndr, int flags, struct NetRemoteTOD *r);
void ndr_print_NetRemoteTOD(struct ndr_print *ndr, const char *name, int flags, const struct NetRemoteTOD *r);
+enum ndr_err_code ndr_push_NetShareAdd(struct ndr_push *ndr, int flags, const struct NetShareAdd *r);
+enum ndr_err_code ndr_pull_NetShareAdd(struct ndr_pull *ndr, int flags, struct NetShareAdd *r);
+void ndr_print_NetShareAdd(struct ndr_print *ndr, const char *name, int flags, const struct NetShareAdd *r);
#endif /* _HEADER_NDR_libnetapi */
diff --git a/source3/librpc/idl/libnetapi.idl b/source3/librpc/idl/libnetapi.idl
index 1bb0aafe94..0b91876832 100644
--- a/source3/librpc/idl/libnetapi.idl
+++ b/source3/librpc/idl/libnetapi.idl
@@ -29,13 +29,28 @@ interface libnetapi
/* NetJoinDomain */
/*******************************************/
+ typedef [public,bitmap32bit] bitmap {
+ NETSETUP_JOIN_DOMAIN = 0x00000001,
+ NETSETUP_ACCT_CREATE = 0x00000002,
+ NETSETUP_ACCT_DELETE = 0x00000004,
+ NETSETUP_WIN9X_UPGRADE = 0x00000010,
+ NETSETUP_DOMAIN_JOIN_IF_JOINED = 0x00000020,
+ NETSETUP_JOIN_UNSECURE = 0x00000040,
+ NETSETUP_MACHINE_PWD_PASSED = 0x00000080,
+ NETSETUP_DEFER_SPN_SET = 0x00000100,
+ NETSETUP_JOIN_DC_ACCOUNT = 0x00000200,
+ NETSETUP_JOIN_WITH_NEW_NAME = 0x00000400,
+ NETSETUP_INSTALL_INVOCATION = 0x00040000,
+ NETSETUP_IGNORE_UNSUPPORTED_FLAGS = 0x10000000
+ } NetJoinFlags;
+
[nopush,nopull] NET_API_STATUS NetJoinDomain(
[in,unique] string *server,
[in,ref] string *domain,
[in,unique] string *account_ou,
[in,unique] string *account,
[in,unique] string *password,
- [in] uint32 join_flags
+ [in] NetJoinFlags join_flags
);
/*******************************************/
@@ -46,7 +61,7 @@ interface libnetapi
[in,unique] string *server_name,
[in,unique] string *account,
[in,unique] string *password,
- [in] uint32 unjoin_flags
+ [in] NetJoinFlags unjoin_flags
);
/*******************************************/
@@ -150,6 +165,11 @@ interface libnetapi
string usri0_name;
} USER_INFO_0;
+ /* priv */
+ const int USER_PRIV_GUEST = 0;
+ const int USER_PRIV_USER = 1;
+ const int USER_PRIV_ADMIN = 2;
+
[public] typedef struct {
string usri1_name;
string usri1_password;
@@ -161,6 +181,16 @@ interface libnetapi
string usri1_script_path;
} USER_INFO_1;
+ /* auth_flags in USER_INFO_2 */
+
+ const int AF_OP_PRINT = 0x1;
+ const int AF_OP_COMM = 0x2;
+ const int AF_OP_SERVER = 0x4;
+ const int AF_OP_ACCOUNTS = 0x8;
+ const int AF_SETTABLE_BITS = (AF_OP_PRINT | AF_OP_COMM | AF_OP_SERVER | AF_OP_ACCOUNTS);
+
+ const int USER_MAXSTORAGE_UNLIMITED = (uint32_t)-1L;
+
[public] typedef struct {
string usri2_name;
string usri2_password;
@@ -244,7 +274,7 @@ interface libnetapi
string usri4_logon_server;
uint32 usri4_country_code;
uint32 usri4_code_page;
- dom_sid *usri4_user_sid;
+ domsid *usri4_user_sid;
uint32 usri4_primary_group_id;
string usri4_profile;
string usri4_home_dir_drive;
@@ -289,7 +319,7 @@ interface libnetapi
uint32 usri20_user_id;
} USER_INFO_20;
- const int ENCRYPTED_PWLEN = 256;
+ const int ENCRYPTED_PWLEN = 16;
[public] typedef struct {
uint8 usri21_password[ENCRYPTED_PWLEN];
@@ -436,6 +466,9 @@ interface libnetapi
string usriX_logon_server;
uint32 usriX_country_code;
uint32 usriX_code_page;
+ string usriX_profile;
+ string usriX_home_dir_drive;
+ uint32 usriX_primary_group_id;
} USER_INFO_X;
[nopush,nopull] NET_API_STATUS NetUserAdd(
@@ -510,6 +543,29 @@ interface libnetapi
);
/*******************************************/
+ /* NetUserGetGroups */
+ /*******************************************/
+
+ [public] typedef struct {
+ string grui0_name;
+ } GROUP_USERS_INFO_0;
+
+ [public] typedef struct {
+ string grui1_name;
+ uint32 grui1_attributes;
+ } GROUP_USERS_INFO_1;
+
+ [nopush,nopull] NET_API_STATUS NetUserGetGroups(
+ [in] string server_name,
+ [in] string user_name,
+ [in] uint32 level,
+ [out] uint8 **buffer,
+ [in] uint32 prefmaxlen,
+ [out,ref] uint32 *entries_read,
+ [out,ref] uint32 *total_entries
+ );
+
+ /*******************************************/
/* NetUserModalsGet */
/*******************************************/
@@ -735,15 +791,6 @@ interface libnetapi
/* NetGroupGetUsers */
/*******************************************/
- [public] typedef struct {
- string grui0_name;
- } GROUP_USERS_INFO_0;
-
- [public] typedef struct {
- string grui1_name;
- uint32 grui1_attributes;
- } GROUP_USERS_INFO_1;
-
[nopush,nopull] NET_API_STATUS NetGroupGetUsers(
[in] string server_name,
[in] string group_name,
@@ -932,4 +979,26 @@ interface libnetapi
[in] string server_name,
[out,ref] uint8 **buffer
);
+
+ /*******************************************/
+ /* NetShareAdd */
+ /*******************************************/
+
+ typedef struct {
+ string shi2_netname;
+ uint32 shi2_type;
+ string shi2_remark;
+ uint32 shi2_permissions;
+ uint32 shi2_max_uses;
+ uint32 shi2_current_uses;
+ string shi2_path;
+ string shi2_passwd;
+ } SHARE_INFO_2;
+
+ [nopush,nopull] NET_API_STATUS NetShareAdd(
+ [in] string server_name,
+ [in] uint32 level,
+ [in] uint8 *buffer,
+ [out] uint32 *parm_err
+ );
}
diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c
index 58bba2bfc7..79a924b9db 100644
--- a/source3/libsmb/async_smb.c
+++ b/source3/libsmb/async_smb.c
@@ -19,8 +19,13 @@
#include "includes.h"
-/*
+static void cli_state_handler(struct event_context *event_ctx,
+ struct fd_event *event, uint16 flags, void *p);
+
+/**
* Fetch an error out of a NBT packet
+ * @param[in] buf The SMB packet
+ * @retval The error, converted to NTSTATUS
*/
NTSTATUS cli_pull_error(char *buf)
@@ -40,8 +45,10 @@ NTSTATUS cli_pull_error(char *buf)
return NT_STATUS_DOS(CVAL(buf, smb_rcls), SVAL(buf,smb_err));
}
-/*
+/**
* Compatibility helper for the sync APIs: Fake NTSTATUS in cli->inbuf
+ * @param[in] cli The client connection that just received an error
+ * @param[in] status The error to set on "cli"
*/
void cli_set_error(struct cli_state *cli, NTSTATUS status)
@@ -61,8 +68,10 @@ void cli_set_error(struct cli_state *cli, NTSTATUS status)
return;
}
-/*
+/**
* Allocate a new mid
+ * @param[in] cli The client connection
+ * @retval The new, unused mid
*/
static uint16_t cli_new_mid(struct cli_state *cli)
@@ -88,10 +97,18 @@ static uint16_t cli_new_mid(struct cli_state *cli)
}
}
+/**
+ * Print an async req that happens to be a cli_request
+ * @param[in] mem_ctx The TALLOC_CTX to put the result on
+ * @param[in] req The request to print
+ * @retval The string representation of "req"
+ */
+
static char *cli_request_print(TALLOC_CTX *mem_ctx, struct async_req *req)
{
char *result = async_req_print(mem_ctx, req);
- struct cli_request *cli_req = cli_request_get(req);
+ struct cli_request *cli_req = talloc_get_type_abort(
+ req->private_data, struct cli_request);
if (result == NULL) {
return NULL;
@@ -101,79 +118,560 @@ static char *cli_request_print(TALLOC_CTX *mem_ctx, struct async_req *req)
result, "mid=%d\n", cli_req->mid);
}
+/**
+ * Destroy a cli_request
+ * @param[in] req The cli_request to kill
+ * @retval Can't fail
+ */
+
static int cli_request_destructor(struct cli_request *req)
{
if (req->enc_state != NULL) {
common_free_enc_buffer(req->enc_state, req->outbuf);
}
DLIST_REMOVE(req->cli->outstanding_requests, req);
+ if (req->cli->outstanding_requests == NULL) {
+ TALLOC_FREE(req->cli->fd_event);
+ }
return 0;
}
-/*
- * Create a fresh async smb request
+/**
+ * Is the SMB command able to hold an AND_X successor
+ * @param[in] cmd The SMB command in question
+ * @retval Can we add a chained request after "cmd"?
*/
-struct async_req *cli_request_new(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli,
- uint8_t num_words, size_t num_bytes,
- struct cli_request **preq)
+static bool is_andx_req(uint8_t cmd)
{
- struct async_req *result;
- struct cli_request *cli_req;
- size_t bufsize = smb_size + num_words * 2 + num_bytes;
+ switch (cmd) {
+ case SMBtconX:
+ case SMBlockingX:
+ case SMBopenX:
+ case SMBreadX:
+ case SMBwriteX:
+ case SMBsesssetupX:
+ case SMBulogoffX:
+ case SMBntcreateX:
+ return true;
+ break;
+ default:
+ break;
+ }
- result = async_req_new(mem_ctx, ev);
- if (result == NULL) {
+ return false;
+}
+
+/**
+ * @brief Find the smb_cmd offset of the last command pushed
+ * @param[in] buf The buffer we're building up
+ * @retval Where can we put our next andx cmd?
+ *
+ * While chaining requests, the "next" request we're looking at needs to put
+ * its SMB_Command before the data the previous request already built up added
+ * to the chain. Find the offset to the place where we have to put our cmd.
+ */
+
+static bool find_andx_cmd_ofs(char *buf, size_t *pofs)
+{
+ uint8_t cmd;
+ size_t ofs;
+
+ cmd = CVAL(buf, smb_com);
+
+ SMB_ASSERT(is_andx_req(cmd));
+
+ ofs = smb_vwv0;
+
+ while (CVAL(buf, ofs) != 0xff) {
+
+ if (!is_andx_req(CVAL(buf, ofs))) {
+ return false;
+ }
+
+ /*
+ * ofs is from start of smb header, so add the 4 length
+ * bytes. The next cmd is right after the wct field.
+ */
+ ofs = SVAL(buf, ofs+2) + 4 + 1;
+
+ SMB_ASSERT(ofs+4 < talloc_get_size(buf));
+ }
+
+ *pofs = ofs;
+ return true;
+}
+
+/**
+ * @brief Destroy an async_req that is the visible part of a cli_request
+ * @param[in] req The request to kill
+ * @retval Return 0 to make talloc happy
+ *
+ * This destructor is a bit tricky: Because a cli_request can host more than
+ * one async_req for chained requests, we need to make sure that the
+ * "cli_request" that we were part of is correctly destroyed at the right
+ * time. This is done by NULLing out ourself from the "async" member of our
+ * "cli_request". If there is none left, then also TALLOC_FREE() the
+ * cli_request, which was a talloc child of the client connection cli_state.
+ */
+
+static int cli_async_req_destructor(struct async_req *req)
+{
+ struct cli_request *cli_req = talloc_get_type_abort(
+ req->private_data, struct cli_request);
+ int i, pending;
+ bool found = false;
+
+ pending = 0;
+
+ for (i=0; i<cli_req->num_async; i++) {
+ if (cli_req->async[i] == req) {
+ cli_req->async[i] = NULL;
+ found = true;
+ }
+ if (cli_req->async[i] != NULL) {
+ pending += 1;
+ }
+ }
+
+ SMB_ASSERT(found);
+
+ if (pending == 0) {
+ TALLOC_FREE(cli_req);
+ }
+
+ return 0;
+}
+
+/**
+ * @brief Chain up a request
+ * @param[in] mem_ctx The TALLOC_CTX for the result
+ * @param[in] ev The event context that will call us back
+ * @param[in] cli The cli_state we queue the request up for
+ * @param[in] smb_command The command that we want to issue
+ * @param[in] additional_flags open_and_x wants to add oplock header flags
+ * @param[in] wct How many words?
+ * @param[in] vwv The words, already in network order
+ * @param[in] num_bytes How many bytes?
+ * @param[in] bytes The data the request ships
+ *
+ * cli_request_chain() is the core of the SMB request marshalling routine. It
+ * will create a new async_req structure in the cli->chain_accumulator->async
+ * array and marshall the smb_cmd, the vwv array and the bytes into
+ * cli->chain_accumulator->outbuf.
+ */
+
+static struct async_req *cli_request_chain(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ uint8_t smb_command,
+ uint8_t additional_flags,
+ uint8_t wct, const uint16_t *vwv,
+ uint16_t num_bytes,
+ const uint8_t *bytes)
+{
+ struct async_req **tmp_reqs;
+ char *tmp_buf;
+ struct cli_request *req;
+ size_t old_size, new_size;
+ size_t ofs;
+
+ req = cli->chain_accumulator;
+
+ tmp_reqs = TALLOC_REALLOC_ARRAY(req, req->async, struct async_req *,
+ req->num_async + 1);
+ if (tmp_reqs == NULL) {
+ DEBUG(0, ("talloc failed\n"));
return NULL;
}
+ req->async = tmp_reqs;
+ req->num_async += 1;
- cli_req = (struct cli_request *)talloc_size(
- result, sizeof(*cli_req) + bufsize);
- if (cli_req == NULL) {
- TALLOC_FREE(result);
+ req->async[req->num_async-1] = async_req_new(mem_ctx, ev);
+ if (req->async[req->num_async-1] == NULL) {
+ DEBUG(0, ("async_req_new failed\n"));
+ req->num_async -= 1;
return NULL;
}
- talloc_set_name_const(cli_req, "struct cli_request");
- result->private_data = cli_req;
- result->print = cli_request_print;
+ req->async[req->num_async-1]->private_data = req;
+ req->async[req->num_async-1]->print = cli_request_print;
+ talloc_set_destructor(req->async[req->num_async-1],
+ cli_async_req_destructor);
- cli_req->async = result;
- cli_req->cli = cli;
- cli_req->outbuf = ((char *)cli_req + sizeof(*cli_req));
- cli_req->sent = 0;
- cli_req->mid = cli_new_mid(cli);
- cli_req->inbuf = NULL;
- cli_req->enc_state = NULL;
+ old_size = talloc_get_size(req->outbuf);
- SCVAL(cli_req->outbuf, smb_wct, num_words);
- SSVAL(cli_req->outbuf, smb_vwv + num_words * 2, num_bytes);
+ /*
+ * We need space for the wct field, the words, the byte count field
+ * and the bytes themselves.
+ */
+ new_size = old_size + 1 + wct * sizeof(uint16_t) + 2 + num_bytes;
- DLIST_ADD_END(cli->outstanding_requests, cli_req,
- struct cli_request *);
- talloc_set_destructor(cli_req, cli_request_destructor);
+ if (new_size > 0xffff) {
+ DEBUG(1, ("cli_request_chain: %u bytes won't fit\n",
+ (unsigned)new_size));
+ goto fail;
+ }
- DEBUG(10, ("cli_request_new: mid=%d\n", cli_req->mid));
+ tmp_buf = TALLOC_REALLOC_ARRAY(NULL, req->outbuf, char, new_size);
+ if (tmp_buf == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ goto fail;
+ }
+ req->outbuf = tmp_buf;
+
+ if (old_size == smb_wct) {
+ SCVAL(req->outbuf, smb_com, smb_command);
+ } else {
+ size_t andx_cmd_ofs;
+ if (!find_andx_cmd_ofs(req->outbuf, &andx_cmd_ofs)) {
+ DEBUG(1, ("invalid command chain\n"));
+ goto fail;
+ }
+ SCVAL(req->outbuf, andx_cmd_ofs, smb_command);
+ SSVAL(req->outbuf, andx_cmd_ofs + 2, old_size - 4);
+ }
- *preq = cli_req;
- return result;
+ ofs = old_size;
+
+ SCVAL(req->outbuf, ofs, wct);
+ ofs += 1;
+
+ memcpy(req->outbuf + ofs, vwv, sizeof(uint16_t) * wct);
+ ofs += sizeof(uint16_t) * wct;
+
+ SSVAL(req->outbuf, ofs, num_bytes);
+ ofs += sizeof(uint16_t);
+
+ memcpy(req->outbuf + ofs, bytes, num_bytes);
+
+ return req->async[req->num_async-1];
+
+ fail:
+ TALLOC_FREE(req->async[req->num_async-1]);
+ req->num_async -= 1;
+ return NULL;
}
-/*
- * Convenience function to get the SMB part out of an async_req
+/**
+ * @brief prepare a cli_state to accept a chain of requests
+ * @param[in] cli The cli_state we want to queue up in
+ * @param[in] ev The event_context that will call us back for the socket
+ * @param[in] size_hint How many bytes are expected, just an optimization
+ * @retval Did we have enough memory?
+ *
+ * cli_chain_cork() sets up a new cli_request in cli->chain_accumulator. If
+ * cli is used in an async fashion, i.e. if we have outstanding requests, then
+ * we do not have to create a fd event. If cli is used only with the sync
+ * helpers, we need to create the fd_event here.
+ *
+ * If you want to issue a chained request to the server, do a
+ * cli_chain_cork(), then do you cli_open_send(), cli_read_and_x_send(),
+ * cli_close_send() and so on. The async requests that come out of
+ * cli_xxx_send() are normal async requests with the difference that they
+ * won't be shipped individually. But the event_context will still trigger the
+ * req->async.fn to be called on every single request.
+ *
+ * You have to take care yourself that you only issue chainable requests in
+ * the middle of the chain.
*/
-struct cli_request *cli_request_get(struct async_req *req)
+bool cli_chain_cork(struct cli_state *cli, struct event_context *ev,
+ size_t size_hint)
{
+ struct cli_request *req = NULL;
+
+ SMB_ASSERT(cli->chain_accumulator == NULL);
+
+ if (cli->fd_event == NULL) {
+ SMB_ASSERT(cli->outstanding_requests == NULL);
+ cli->fd_event = event_add_fd(ev, cli, cli->fd,
+ EVENT_FD_READ,
+ cli_state_handler, cli);
+ if (cli->fd_event == NULL) {
+ return false;
+ }
+ }
+
+ req = talloc(cli, struct cli_request);
if (req == NULL) {
- return NULL;
+ goto fail;
+ }
+ req->cli = cli;
+
+ if (size_hint == 0) {
+ size_hint = 100;
+ }
+ req->outbuf = talloc_array(req, char, smb_wct + size_hint);
+ if (req->outbuf == NULL) {
+ goto fail;
+ }
+ req->outbuf = TALLOC_REALLOC_ARRAY(NULL, req->outbuf, char, smb_wct);
+
+ req->num_async = 0;
+ req->async = NULL;
+
+ req->enc_state = NULL;
+ req->recv_helper.fn = NULL;
+
+ SSVAL(req->outbuf, smb_tid, cli->cnum);
+ cli_setup_packet_buf(cli, req->outbuf);
+
+ req->mid = cli_new_mid(cli);
+ SSVAL(req->outbuf, smb_mid, req->mid);
+
+ cli->chain_accumulator = req;
+
+ DEBUG(10, ("cli_chain_cork: mid=%d\n", req->mid));
+
+ return true;
+ fail:
+ TALLOC_FREE(req);
+ if (cli->outstanding_requests == NULL) {
+ TALLOC_FREE(cli->fd_event);
}
- return talloc_get_type_abort(req->private_data, struct cli_request);
+ return false;
}
-/*
+/**
+ * Ship a request queued up via cli_request_chain()
+ * @param[in] cl The connection
+ */
+
+void cli_chain_uncork(struct cli_state *cli)
+{
+ struct cli_request *req = cli->chain_accumulator;
+
+ SMB_ASSERT(req != NULL);
+
+ DLIST_ADD_END(cli->outstanding_requests, req, struct cli_request *);
+ talloc_set_destructor(req, cli_request_destructor);
+
+ cli->chain_accumulator = NULL;
+
+ smb_setlen(req->outbuf, talloc_get_size(req->outbuf) - 4);
+
+ cli_calculate_sign_mac(cli, req->outbuf);
+
+ if (cli_encryption_on(cli)) {
+ NTSTATUS status;
+ char *enc_buf;
+
+ status = cli_encrypt_message(cli, req->outbuf, &enc_buf);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Error in encrypting client message. "
+ "Error %s\n", nt_errstr(status)));
+ TALLOC_FREE(req);
+ return;
+ }
+ req->outbuf = enc_buf;
+ req->enc_state = cli->trans_enc_state;
+ }
+
+ req->sent = 0;
+
+ event_fd_set_writeable(cli->fd_event);
+}
+
+/**
+ * @brief Send a request to the server
+ * @param[in] mem_ctx The TALLOC_CTX for the result
+ * @param[in] ev The event context that will call us back
+ * @param[in] cli The cli_state we queue the request up for
+ * @param[in] smb_command The command that we want to issue
+ * @param[in] additional_flags open_and_x wants to add oplock header flags
+ * @param[in] wct How many words?
+ * @param[in] vwv The words, already in network order
+ * @param[in] num_bytes How many bytes?
+ * @param[in] bytes The data the request ships
+ *
+ * This is the generic routine to be used by the cli_xxx_send routines.
+ */
+
+struct async_req *cli_request_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ uint8_t smb_command,
+ uint8_t additional_flags,
+ uint8_t wct, const uint16_t *vwv,
+ uint16_t num_bytes, const uint8_t *bytes)
+{
+ struct async_req *result;
+ bool uncork = false;
+
+ if (cli->chain_accumulator == NULL) {
+ if (!cli_chain_cork(cli, ev,
+ wct * sizeof(uint16_t) + num_bytes + 3)) {
+ DEBUG(1, ("cli_chain_cork failed\n"));
+ return NULL;
+ }
+ uncork = true;
+ }
+
+ result = cli_request_chain(mem_ctx, ev, cli, smb_command,
+ additional_flags, wct, vwv,
+ num_bytes, bytes);
+
+ if (result == NULL) {
+ DEBUG(1, ("cli_request_chain failed\n"));
+ }
+
+ if (uncork) {
+ cli_chain_uncork(cli);
+ }
+
+ return result;
+}
+
+/**
+ * Figure out if there is an andx command behind the current one
+ * @param[in] buf The smb buffer to look at
+ * @param[in] ofs The offset to the wct field that is followed by the cmd
+ * @retval Is there a command following?
+ */
+
+static bool have_andx_command(const char *buf, uint16_t ofs)
+{
+ uint8_t wct;
+ size_t buflen = talloc_get_size(buf);
+
+ if ((ofs == buflen-1) || (ofs == buflen)) {
+ return false;
+ }
+
+ wct = CVAL(buf, ofs);
+ if (wct < 2) {
+ /*
+ * Not enough space for the command and a following pointer
+ */
+ return false;
+ }
+ return (CVAL(buf, ofs+1) != 0xff);
+}
+
+/**
+ * @brief Pull reply data out of a request
+ * @param[in] req The request that we just received a reply for
+ * @param[out] pwct How many words did the server send?
+ * @param[out] pvwv The words themselves
+ * @param[out] pnum_bytes How many bytes did the server send?
+ * @param[out] pbytes The bytes themselves
+ * @retval Was the reply formally correct?
+ */
+
+NTSTATUS cli_pull_reply(struct async_req *req,
+ uint8_t *pwct, uint16_t **pvwv,
+ uint16_t *pnum_bytes, uint8_t **pbytes)
+{
+ struct cli_request *cli_req = talloc_get_type_abort(
+ req->private_data, struct cli_request);
+ uint8_t wct, cmd;
+ uint16_t num_bytes;
+ size_t wct_ofs, bytes_offset;
+ int i, j;
+ NTSTATUS status;
+
+ for (i = 0; i < cli_req->num_async; i++) {
+ if (req == cli_req->async[i]) {
+ break;
+ }
+ }
+
+ if (i == cli_req->num_async) {
+ cli_set_error(cli_req->cli, NT_STATUS_INVALID_PARAMETER);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /**
+ * The status we pull here is only relevant for the last reply in the
+ * chain.
+ */
+
+ status = cli_pull_error(cli_req->inbuf);
+
+ if (i == 0) {
+ if (NT_STATUS_IS_ERR(status)
+ && !have_andx_command(cli_req->inbuf, smb_wct)) {
+ cli_set_error(cli_req->cli, status);
+ return status;
+ }
+ wct_ofs = smb_wct;
+ goto done;
+ }
+
+ cmd = CVAL(cli_req->inbuf, smb_com);
+ wct_ofs = smb_wct;
+
+ for (j = 0; j < i; j++) {
+ if (j < i-1) {
+ if (cmd == 0xff) {
+ return NT_STATUS_REQUEST_ABORTED;
+ }
+ if (!is_andx_req(cmd)) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+ }
+
+ if (!have_andx_command(cli_req->inbuf, wct_ofs)) {
+ /*
+ * This request was not completed because a previous
+ * request in the chain had received an error.
+ */
+ return NT_STATUS_REQUEST_ABORTED;
+ }
+
+ wct_ofs = SVAL(cli_req->inbuf, wct_ofs + 3);
+
+ /*
+ * Skip the all-present length field. No overflow, we've just
+ * put a 16-bit value into a size_t.
+ */
+ wct_ofs += 4;
+
+ if (wct_ofs+2 > talloc_get_size(cli_req->inbuf)) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
+ cmd = CVAL(cli_req->inbuf, wct_ofs + 1);
+ }
+
+ if (!have_andx_command(cli_req->inbuf, wct_ofs)
+ && NT_STATUS_IS_ERR(status)) {
+ /*
+ * The last command takes the error code. All further commands
+ * down the requested chain will get a
+ * NT_STATUS_REQUEST_ABORTED.
+ */
+ return status;
+ }
+
+ done:
+ wct = CVAL(cli_req->inbuf, wct_ofs);
+
+ bytes_offset = wct_ofs + 1 + wct * sizeof(uint16_t);
+ num_bytes = SVAL(cli_req->inbuf, bytes_offset);
+
+ /*
+ * wct_ofs is a 16-bit value plus 4, wct is a 8-bit value, num_bytes
+ * is a 16-bit value. So bytes_offset being size_t should be far from
+ * wrapping.
+ */
+
+ if ((bytes_offset + 2 > talloc_get_size(cli_req->inbuf))
+ || (bytes_offset > 0xffff)) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
+ *pwct = wct;
+ *pvwv = (uint16_t *)(cli_req->inbuf + wct_ofs + 1);
+ *pnum_bytes = num_bytes;
+ *pbytes = (uint8_t *)cli_req->inbuf + bytes_offset + 2;
+
+ return NT_STATUS_OK;
+}
+
+/**
* A PDU has arrived on cli->evt_inbuf
+ * @param[in] cli The cli_state that received something
*/
static void handle_incoming_pdu(struct cli_state *cli)
@@ -182,8 +680,11 @@ static void handle_incoming_pdu(struct cli_state *cli)
uint16_t mid;
size_t raw_pdu_len, buf_len, pdu_len, rest_len;
char *pdu;
+ int i;
NTSTATUS status;
+ int num_async;
+
/*
* The encrypted PDU len might differ from the unencrypted one
*/
@@ -296,7 +797,28 @@ static void handle_incoming_pdu(struct cli_state *cli)
req->inbuf = talloc_move(req, &pdu);
- async_req_done(req->async);
+ /*
+ * Freeing the last async_req will free the req (see
+ * cli_async_req_destructor). So make a copy of req->num_async, we
+ * can't reference it in the last round.
+ */
+
+ num_async = req->num_async;
+
+ for (i=0; i<num_async; i++) {
+ /**
+ * A request might have been talloc_free()'ed before we arrive
+ * here. It will have removed itself from req->async via its
+ * destructor cli_async_req_destructor().
+ */
+ if (req->async[i] != NULL) {
+ if (req->recv_helper.fn != NULL) {
+ req->recv_helper.fn(req->async[i]);
+ } else {
+ async_req_done(req->async[i]);
+ }
+ }
+ }
return;
invalidate_requests:
@@ -305,13 +827,17 @@ static void handle_incoming_pdu(struct cli_state *cli)
nt_errstr(status)));
for (req = cli->outstanding_requests; req; req = req->next) {
- async_req_error(req->async, status);
+ async_req_error(req->async[0], status);
}
return;
}
-/*
+/**
* fd event callback. This is the basic connection to the socket
+ * @param[in] event_ctx The event context that called us
+ * @param[in] event The event that fired
+ * @param[in] flags EVENT_FD_READ | EVENT_FD_WRITE
+ * @param[in] p private_data, in this case the cli_state
*/
static void cli_state_handler(struct event_context *event_ctx,
@@ -394,7 +920,9 @@ static void cli_state_handler(struct event_context *event_ctx,
}
if (req == NULL) {
- event_fd_set_not_writeable(event);
+ if (cli->fd_event != NULL) {
+ event_fd_set_not_writeable(cli->fd_event);
+ }
return;
}
@@ -415,76 +943,13 @@ static void cli_state_handler(struct event_context *event_ctx,
sock_error:
for (req = cli->outstanding_requests; req; req = req->next) {
- req->async->state = ASYNC_REQ_ERROR;
- req->async->status = map_nt_error_from_unix(errno);
+ int i;
+ for (i=0; i<req->num_async; i++) {
+ req->async[i]->state = ASYNC_REQ_ERROR;
+ req->async[i]->status = map_nt_error_from_unix(errno);
+ }
}
TALLOC_FREE(cli->fd_event);
close(cli->fd);
cli->fd = -1;
}
-
-/*
- * Holder for a talloc_destructor, we need to zero out the pointers in cli
- * when deleting
- */
-struct cli_tmp_event {
- struct cli_state *cli;
-};
-
-static int cli_tmp_event_destructor(struct cli_tmp_event *e)
-{
- TALLOC_FREE(e->cli->fd_event);
- TALLOC_FREE(e->cli->event_ctx);
- return 0;
-}
-
-/*
- * Create a temporary event context for use in the sync helper functions
- */
-
-struct cli_tmp_event *cli_tmp_event_ctx(TALLOC_CTX *mem_ctx,
- struct cli_state *cli)
-{
- struct cli_tmp_event *state;
-
- if (cli->event_ctx != NULL) {
- return NULL;
- }
-
- state = talloc(mem_ctx, struct cli_tmp_event);
- if (state == NULL) {
- return NULL;
- }
- state->cli = cli;
- talloc_set_destructor(state, cli_tmp_event_destructor);
-
- cli->event_ctx = event_context_init(state);
- if (cli->event_ctx == NULL) {
- TALLOC_FREE(state);
- return NULL;
- }
-
- cli->fd_event = event_add_fd(cli->event_ctx, state, cli->fd,
- EVENT_FD_READ, cli_state_handler, cli);
- if (cli->fd_event == NULL) {
- TALLOC_FREE(state);
- return NULL;
- }
- return state;
-}
-
-/*
- * Attach an event context permanently to a cli_struct
- */
-
-NTSTATUS cli_add_event_ctx(struct cli_state *cli,
- struct event_context *event_ctx)
-{
- cli->event_ctx = event_ctx;
- cli->fd_event = event_add_fd(event_ctx, cli, cli->fd, EVENT_FD_READ,
- cli_state_handler, cli);
- if (cli->fd_event == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- return NT_STATUS_OK;
-}
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 2c0950de03..9d65fb4e94 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -637,41 +637,153 @@ bool cli_send_keepalive(struct cli_state *cli)
return true;
}
-/****************************************************************************
- Send/receive a SMBecho command: ping the server
-****************************************************************************/
+/**
+ * @brief: Collect a echo reply
+ * @param[in] req The corresponding async request
+ *
+ * There might be more than one echo reply. This helper pulls the reply out of
+ * the data stream. If all expected replies have arrived, declare the
+ * async_req done.
+ */
+
+static void cli_echo_recv_helper(struct async_req *req)
+{
+ struct cli_request *cli_req;
+ uint8_t wct;
+ uint16_t *vwv;
+ uint16_t num_bytes;
+ uint8_t *bytes;
+ NTSTATUS status;
+
+ status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
+ if (!NT_STATUS_IS_OK(status)) {
+ async_req_error(req, status);
+ return;
+ }
+
+ cli_req = talloc_get_type_abort(req->private_data, struct cli_request);
+
+ if ((num_bytes != cli_req->data.echo.data.length)
+ || (memcmp(cli_req->data.echo.data.data, bytes,
+ num_bytes) != 0)) {
+ async_req_error(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
+ }
+
+ cli_req->data.echo.num_echos -= 1;
-bool cli_echo(struct cli_state *cli, uint16 num_echos,
- unsigned char *data, size_t length)
+ if (cli_req->data.echo.num_echos == 0) {
+ client_set_trans_sign_state_off(cli_req->cli, cli_req->mid);
+ async_req_done(req);
+ return;
+ }
+
+ return;
+}
+
+/**
+ * @brief Send SMBEcho requests
+ * @param[in] mem_ctx The memory context to put the async_req on
+ * @param[in] ev The event context that will call us back
+ * @param[in] cli The connection to send the echo to
+ * @param[in] num_echos How many times do we want to get the reply?
+ * @param[in] data The data we want to get back
+ * @retval The async request
+ */
+
+struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli, uint16_t num_echos,
+ DATA_BLOB data)
{
- char *p;
- int i;
+ uint16_t vwv[1];
+ uint8_t *data_copy;
+ struct async_req *result;
+ struct cli_request *req;
- SMB_ASSERT(length < 1024);
+ SSVAL(vwv, 0, num_echos);
- memset(cli->outbuf,'\0',smb_size);
- cli_set_message(cli->outbuf,1,length,true);
- SCVAL(cli->outbuf,smb_com,SMBecho);
- SSVAL(cli->outbuf,smb_tid,65535);
- SSVAL(cli->outbuf,smb_vwv0,num_echos);
- cli_setup_packet(cli);
- p = smb_buf(cli->outbuf);
- memcpy(p, data, length);
- p += length;
+ data_copy = (uint8_t *)talloc_memdup(mem_ctx, data.data, data.length);
+ if (data_copy == NULL) {
+ return NULL;
+ }
- cli_setup_bcc(cli, p);
+ result = cli_request_send(mem_ctx, ev, cli, SMBecho, 0, 1, vwv,
+ data.length, data.data);
+ if (result == NULL) {
+ TALLOC_FREE(data_copy);
+ return NULL;
+ }
+ req = talloc_get_type_abort(result->private_data, struct cli_request);
- cli_send_smb(cli);
+ client_set_trans_sign_state_on(cli, req->mid);
- for (i=0; i<num_echos; i++) {
- if (!cli_receive_smb(cli)) {
- return false;
- }
+ req->data.echo.num_echos = num_echos;
+ req->data.echo.data.data = talloc_move(req, &data_copy);
+ req->data.echo.data.length = data.length;
- if (cli_is_error(cli)) {
- return false;
- }
+ req->recv_helper.fn = cli_echo_recv_helper;
+
+ return result;
+}
+
+/**
+ * Get the result out from an echo request
+ * @param[in] req The async_req from cli_echo_send
+ * @retval Did the server reply correctly?
+ */
+
+NTSTATUS cli_echo_recv(struct async_req *req)
+{
+ SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
+ if (req->state == ASYNC_REQ_ERROR) {
+ return req->status;
}
- return true;
+ return NT_STATUS_OK;
+}
+
+/**
+ * @brief Send/Receive SMBEcho requests
+ * @param[in] mem_ctx The memory context to put the async_req on
+ * @param[in] ev The event context that will call us back
+ * @param[in] cli The connection to send the echo to
+ * @param[in] num_echos How many times do we want to get the reply?
+ * @param[in] data The data we want to get back
+ * @retval Did the server reply correctly?
+ */
+
+NTSTATUS cli_echo(struct cli_state *cli, uint16_t num_echos, DATA_BLOB data)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct event_context *ev;
+ struct async_req *req;
+ NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+ if (cli->fd_event != NULL) {
+ /*
+ * Can't use sync call while an async call is in flight
+ */
+ cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
+ goto fail;
+ }
+
+ ev = event_context_init(frame);
+ if (ev == NULL) {
+ goto fail;
+ }
+
+ req = cli_echo_send(frame, ev, cli, num_echos, data);
+ if (req == NULL) {
+ goto fail;
+ }
+
+ while (req->state < ASYNC_REQ_DONE) {
+ event_loop_once(ev);
+ }
+
+ status = cli_echo_recv(req);
+
+ fail:
+ TALLOC_FREE(frame);
+ return status;
}
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 12b10ba0a0..a8b3440513 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -781,19 +781,62 @@ int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess
FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0);
}
+static uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str)
+{
+ size_t buflen = talloc_get_size(buf);
+ char *converted;
+ size_t converted_size;
+
+ /*
+ * We're pushing into an SMB buffer, align odd
+ */
+ if (ucs2 && (buflen % 2 == 0)) {
+ buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t, buflen + 1);
+ if (buf == NULL) {
+ return NULL;
+ }
+ buf[buflen] = '\0';
+ buflen += 1;
+ }
+
+ if (!convert_string_allocate(talloc_tos(), CH_UNIX,
+ ucs2 ? CH_UTF16LE : CH_DOS,
+ str, strlen(str)+1, &converted,
+ &converted_size, true)) {
+ return NULL;
+ }
+
+ buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t,
+ buflen + converted_size);
+ if (buf == NULL) {
+ return NULL;
+ }
+
+ memcpy(buf + buflen, converted, converted_size);
+
+ TALLOC_FREE(converted);
+ return buf;
+}
+
/****************************************************************************
Open a file
WARNING: if you open with O_WRONLY then getattrE won't work!
****************************************************************************/
-int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode)
+struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli,
+ const char *fname, int flags, int share_mode)
{
- char *p;
- unsigned openfn=0;
- unsigned accessmode=0;
+ unsigned openfn = 0;
+ unsigned accessmode = 0;
+ uint8_t additional_flags = 0;
+ uint8_t *bytes;
+ uint16_t vwv[15];
+ struct async_req *result;
- if (flags & O_CREAT)
+ if (flags & O_CREAT) {
openfn |= (1<<4);
+ }
if (!(flags & O_EXCL)) {
if (flags & O_TRUNC)
openfn |= (1<<1);
@@ -819,74 +862,172 @@ int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode
accessmode = 0xFF;
}
- memset(cli->outbuf,'\0',smb_size);
- memset(cli->inbuf,'\0',smb_size);
-
- cli_set_message(cli->outbuf,15,0, true);
-
- SCVAL(cli->outbuf,smb_com,SMBopenX);
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
-
- SSVAL(cli->outbuf,smb_vwv0,0xFF);
- SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
- SSVAL(cli->outbuf,smb_vwv3,accessmode);
- SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
- SSVAL(cli->outbuf,smb_vwv5,0);
- SSVAL(cli->outbuf,smb_vwv8,openfn);
+ SCVAL(vwv + 0, 0, 0xFF);
+ SCVAL(vwv + 0, 1, 0);
+ SSVAL(vwv + 1, 0, 0);
+ SSVAL(vwv + 2, 0, 0); /* no additional info */
+ SSVAL(vwv + 3, 0, accessmode);
+ SSVAL(vwv + 4, 0, aSYSTEM | aHIDDEN);
+ SSVAL(vwv + 5, 0, 0);
+ SIVAL(vwv + 6, 0, 0);
+ SSVAL(vwv + 8, 0, openfn);
+ SIVAL(vwv + 9, 0, 0);
+ SIVAL(vwv + 11, 0, 0);
+ SIVAL(vwv + 13, 0, 0);
if (cli->use_oplocks) {
/* if using oplocks then ask for a batch oplock via
core and extended methods */
- SCVAL(cli->outbuf,smb_flg, CVAL(cli->outbuf,smb_flg)|
- FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK);
- SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6);
+ additional_flags =
+ FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
+ SSVAL(vwv+2, 0, SVAL(vwv+2, 0) | 6);
}
- p = smb_buf(cli->outbuf);
- p += clistr_push(cli, p, fname,
- cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE);
+ bytes = talloc_array(talloc_tos(), uint8_t, 0);
+ if (bytes == NULL) {
+ return NULL;
+ }
- cli_setup_bcc(cli, p);
+ bytes = smb_bytes_push_str(
+ bytes, (cli->capabilities & CAP_UNICODE) != 0, fname);
+ if (bytes == NULL) {
+ return NULL;
+ }
- cli_send_smb(cli);
- if (!cli_receive_smb(cli)) {
- return -1;
+ result = cli_request_send(mem_ctx, ev, cli, SMBopenX, additional_flags,
+ 15, vwv, talloc_get_size(bytes), bytes);
+ TALLOC_FREE(bytes);
+ return result;
+}
+
+NTSTATUS cli_open_recv(struct async_req *req, int *fnum)
+{
+ uint8_t wct;
+ uint16_t *vwv;
+ uint16_t num_bytes;
+ uint8_t *bytes;
+ NTSTATUS status;
+
+ SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
+ if (req->state == ASYNC_REQ_ERROR) {
+ return req->status;
}
- if (cli_is_error(cli)) {
- return -1;
+ status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (wct < 3) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
- return SVAL(cli->inbuf,smb_vwv2);
+ *fnum = SVAL(vwv+2, 0);
+
+ return NT_STATUS_OK;
+}
+
+int cli_open(struct cli_state *cli, const char *fname, int flags,
+ int share_mode)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct event_context *ev;
+ struct async_req *req;
+ int result = -1;
+
+ if (cli->fd_event != NULL) {
+ /*
+ * Can't use sync call while an async call is in flight
+ */
+ cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
+ goto fail;
+ }
+
+ ev = event_context_init(frame);
+ if (ev == NULL) {
+ goto fail;
+ }
+
+ req = cli_open_send(frame, ev, cli, fname, flags, share_mode);
+ if (req == NULL) {
+ goto fail;
+ }
+
+ while (req->state < ASYNC_REQ_DONE) {
+ event_loop_once(ev);
+ }
+
+ cli_open_recv(req, &result);
+ fail:
+ TALLOC_FREE(frame);
+ return result;
}
/****************************************************************************
Close a file.
****************************************************************************/
-bool cli_close(struct cli_state *cli, int fnum)
+struct async_req *cli_close_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli, int fnum)
{
- memset(cli->outbuf,'\0',smb_size);
- memset(cli->inbuf,'\0',smb_size);
+ uint16_t vwv[3];
- cli_set_message(cli->outbuf,3,0,True);
+ SSVAL(vwv+0, 0, fnum);
+ SIVALS(vwv+1, 0, -1);
- SCVAL(cli->outbuf,smb_com,SMBclose);
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
+ return cli_request_send(mem_ctx, ev, cli, SMBclose, 0, 3, vwv,
+ 0, NULL);
+}
- SSVAL(cli->outbuf,smb_vwv0,fnum);
- SIVALS(cli->outbuf,smb_vwv1,-1);
+NTSTATUS cli_close_recv(struct async_req *req)
+{
+ uint8_t wct;
+ uint16_t *vwv;
+ uint16_t num_bytes;
+ uint8_t *bytes;
- cli_send_smb(cli);
- if (!cli_receive_smb(cli)) {
- return False;
+ SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
+ if (req->state == ASYNC_REQ_ERROR) {
+ return req->status;
}
- return !cli_is_error(cli);
+ return cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
}
+bool cli_close(struct cli_state *cli, int fnum)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct event_context *ev;
+ struct async_req *req;
+ bool result = false;
+
+ if (cli->fd_event != NULL) {
+ /*
+ * Can't use sync call while an async call is in flight
+ */
+ cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
+ goto fail;
+ }
+
+ ev = event_context_init(frame);
+ if (ev == NULL) {
+ goto fail;
+ }
+
+ req = cli_close_send(frame, ev, cli, fnum);
+ if (req == NULL) {
+ goto fail;
+ }
+
+ while (req->state < ASYNC_REQ_DONE) {
+ event_loop_once(ev);
+ }
+
+ result = NT_STATUS_IS_OK(cli_close_recv(req));
+ fail:
+ TALLOC_FREE(frame);
+ return result;
+}
/****************************************************************************
Truncate a file to a specified size
@@ -1751,7 +1892,7 @@ bool cli_set_ea_fnum(struct cli_state *cli, int fnum, const char *ea_name, const
}
/*********************************************************
- Get an extended attribute list tility fn.
+ Get an extended attribute list utility fn.
*********************************************************/
static bool cli_get_ea_list(struct cli_state *cli,
diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c
index fa21ad3467..f940081072 100644
--- a/source3/libsmb/clikrb5.c
+++ b/source3/libsmb/clikrb5.c
@@ -27,18 +27,6 @@
#ifdef HAVE_KRB5
-#ifdef HAVE_KRB5_KEYBLOCK_KEYVALUE /* Heimdal */
-#define KRB5_KEY_TYPE(k) ((k)->keytype)
-#define KRB5_KEY_LENGTH(k) ((k)->keyvalue.length)
-#define KRB5_KEY_DATA(k) ((k)->keyvalue.data)
-#define KRB5_KEY_DATA_CAST void
-#else /* MIT */
-#define KRB5_KEY_TYPE(k) ((k)->enctype)
-#define KRB5_KEY_LENGTH(k) ((k)->length)
-#define KRB5_KEY_DATA(k) ((k)->contents)
-#define KRB5_KEY_DATA_CAST krb5_octet
-#endif /* HAVE_KRB5_KEYBLOCK_KEYVALUE */
-
#define GSSAPI_CHECKSUM 0x8003 /* Checksum type value for Kerberos */
#define GSSAPI_BNDLENGTH 16 /* Bind Length (rfc-1964 pg.3) */
#define GSSAPI_CHECKSUM_SIZE (12+GSSAPI_BNDLENGTH)
@@ -761,16 +749,10 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
ccache,
&in_data );
if (retval) {
- DEBUG( 1, ("ads_krb5_get_fwd_ticket failed (%s)\n", error_message( retval ) ) );
- goto cleanup_creds;
- }
-
- if (retval) {
- DEBUG( 1, ("krb5_auth_con_set_req_cksumtype failed (%s)\n",
- error_message( retval ) ) );
+ DEBUG( 1, ("ads_krb5_get_fwd_ticket failed (%s)\n",
+ error_message( retval ) ) );
goto cleanup_creds;
}
-
}
#endif
@@ -1057,6 +1039,7 @@ get_key_from_keytab(krb5_context context,
krb5_error_code ret;
krb5_keytab keytab;
char *name = NULL;
+ krb5_keyblock *keyp;
/* We have to open a new keytab handle here, as MIT does
an implicit open/getnext/close on krb5_kt_get_entry. We
@@ -1089,14 +1072,9 @@ get_key_from_keytab(krb5_context context,
goto out;
}
-#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */
- ret = krb5_copy_keyblock(context, &entry.keyblock, out_key);
-#elif defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) /* MIT */
- ret = krb5_copy_keyblock(context, &entry.key, out_key);
-#else
-#error UNKNOWN_KRB5_KEYTAB_ENTRY_FORMAT
-#endif
+ keyp = KRB5_KT_KEY(&entry);
+ ret = krb5_copy_keyblock(context, keyp, out_key);
if (ret) {
DEBUG(0,("get_key_from_keytab: failed to copy key: %s\n", error_message(ret)));
goto out;
@@ -1584,15 +1562,9 @@ done:
#endif /* HAVE_KRB5_GET_INIT_CREDS_OPT_FREE */
}
- krb5_enctype smb_get_enctype_from_kt_entry(const krb5_keytab_entry *kt_entry)
+ krb5_enctype smb_get_enctype_from_kt_entry(krb5_keytab_entry *kt_entry)
{
-#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEY /* MIT */
- return kt_entry->key.enctype;
-#elif defined(HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK) /* Heimdal */
- return kt_entry->keyblock.keytype;
-#else
-#error UNKNOWN_KRB5_KEYTAB_ENTRY_KEYBLOCK_FORMAT
-#endif
+ return KRB5_KEY_TYPE(KRB5_KT_KEY(kt_entry));
}
diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c
index a57f1e0785..ec63281630 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/libsmb/clireadwrite.c
@@ -41,13 +41,16 @@ static size_t cli_read_max_bufsize(struct cli_state *cli)
*/
struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
struct cli_state *cli, int fnum,
off_t offset, size_t size)
{
struct async_req *result;
struct cli_request *req;
bool bigoffset = False;
- char *enc_buf;
+
+ uint16_t vwv[12];
+ uint8_t wct = 10;
if (size > cli_read_max_bufsize(cli)) {
DEBUG(0, ("cli_read_andx_send got size=%d, can only handle "
@@ -56,60 +59,37 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx,
return NULL;
}
- result = cli_request_new(mem_ctx, cli->event_ctx, cli, 12, 0, &req);
+ SCVAL(vwv + 0, 0, 0xFF);
+ SCVAL(vwv + 0, 1, 0);
+ SSVAL(vwv + 1, 0, 0);
+ SSVAL(vwv + 2, 0, fnum);
+ SIVAL(vwv + 3, 0, offset);
+ SSVAL(vwv + 5, 0, size);
+ SSVAL(vwv + 6, 0, size);
+ SSVAL(vwv + 7, 0, (size >> 16));
+ SSVAL(vwv + 8, 0, 0);
+ SSVAL(vwv + 9, 0, 0);
+
+ if ((SMB_BIG_UINT)offset >> 32) {
+ bigoffset = True;
+ SIVAL(vwv + 10, 0,
+ (((SMB_BIG_UINT)offset)>>32) & 0xffffffff);
+ wct += 2;
+ }
+
+ result = cli_request_send(mem_ctx, ev, cli, SMBreadX, 0, wct, vwv,
+ 0, NULL);
if (result == NULL) {
- DEBUG(0, ("cli_request_new failed\n"));
return NULL;
}
+ req = talloc_get_type_abort(result->private_data, struct cli_request);
+
req->data.read.ofs = offset;
req->data.read.size = size;
req->data.read.received = 0;
req->data.read.rcvbuf = NULL;
- if ((SMB_BIG_UINT)offset >> 32)
- bigoffset = True;
-
- cli_set_message(req->outbuf, bigoffset ? 12 : 10, 0, False);
-
- SCVAL(req->outbuf,smb_com,SMBreadX);
- SSVAL(req->outbuf,smb_tid,cli->cnum);
- cli_setup_packet_buf(cli, req->outbuf);
-
- SCVAL(req->outbuf,smb_vwv0,0xFF);
- SCVAL(req->outbuf,smb_vwv0+1,0);
- SSVAL(req->outbuf,smb_vwv1,0);
- SSVAL(req->outbuf,smb_vwv2,fnum);
- SIVAL(req->outbuf,smb_vwv3,offset);
- SSVAL(req->outbuf,smb_vwv5,size);
- SSVAL(req->outbuf,smb_vwv6,size);
- SSVAL(req->outbuf,smb_vwv7,(size >> 16));
- SSVAL(req->outbuf,smb_vwv8,0);
- SSVAL(req->outbuf,smb_vwv9,0);
- SSVAL(req->outbuf,smb_mid,req->mid);
-
- if (bigoffset) {
- SIVAL(req->outbuf, smb_vwv10,
- (((SMB_BIG_UINT)offset)>>32) & 0xffffffff);
- }
-
- cli_calculate_sign_mac(cli, req->outbuf);
-
- event_fd_set_writeable(cli->fd_event);
-
- if (cli_encryption_on(cli)) {
- NTSTATUS status;
- status = cli_encrypt_message(cli, req->outbuf, &enc_buf);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("Error in encrypting client message. "
- "Error %s\n", nt_errstr(status)));
- TALLOC_FREE(req);
- return NULL;
- }
- req->outbuf = enc_buf;
- req->enc_state = cli->trans_enc_state;
- }
-
return result;
}
@@ -123,7 +103,12 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx,
NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received,
uint8_t **rcvbuf)
{
- struct cli_request *cli_req = cli_request_get(req);
+ struct cli_request *cli_req = talloc_get_type_abort(
+ req->private_data, struct cli_request);
+ uint8_t wct;
+ uint16_t *vwv;
+ uint16_t num_bytes;
+ uint8_t *bytes;
NTSTATUS status;
size_t size;
@@ -132,24 +117,27 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received,
return req->status;
}
- status = cli_pull_error(cli_req->inbuf);
+ status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
if (NT_STATUS_IS_ERR(status)) {
return status;
}
+ if (wct < 12) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
/* size is the number of bytes the server returned.
* Might be zero. */
- size = SVAL(cli_req->inbuf, smb_vwv5);
- size |= (((unsigned int)(SVAL(cli_req->inbuf, smb_vwv7))) << 16);
+ size = SVAL(vwv + 5, 0);
+ size |= (((unsigned int)SVAL(vwv + 7, 0)) << 16);
if (size > cli_req->data.read.size) {
DEBUG(5,("server returned more than we wanted!\n"));
return NT_STATUS_UNEXPECTED_IO_ERROR;
}
- *rcvbuf = (uint8_t *)
- (smb_base(cli_req->inbuf) + SVAL(cli_req->inbuf, smb_vwv6));
+ *rcvbuf = (uint8_t *)(smb_base(cli_req->inbuf) + SVAL(vwv + 6, 0));
*received = size;
return NT_STATUS_OK;
}
@@ -165,6 +153,7 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received,
struct cli_pull_state {
struct async_req *req;
+ struct event_context *ev;
struct cli_state *cli;
uint16_t fnum;
off_t start_offset;
@@ -223,7 +212,9 @@ static void cli_pull_read_done(struct async_req *read_req);
* Prepare an async pull request
*/
-struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli,
+struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
uint16_t fnum, off_t start_offset,
SMB_OFF_T size, size_t window_size,
NTSTATUS (*sink)(char *buf, size_t n,
@@ -234,7 +225,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli,
struct cli_pull_state *state;
int i;
- result = async_req_new(mem_ctx, cli->event_ctx);
+ result = async_req_new(mem_ctx, ev);
if (result == NULL) {
goto failed;
}
@@ -247,6 +238,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli,
state->req = result;
state->cli = cli;
+ state->ev = ev;
state->fnum = fnum;
state->start_offset = start_offset;
state->size = size;
@@ -289,7 +281,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli,
request_thistime = MIN(size_left, state->chunk_size);
state->reqs[i] = cli_read_andx_send(
- state->reqs, cli, fnum,
+ state->reqs, ev, cli, fnum,
state->start_offset + state->requested,
request_thistime);
@@ -320,7 +312,8 @@ static void cli_pull_read_done(struct async_req *read_req)
read_req->async.priv, struct async_req);
struct cli_pull_state *state = talloc_get_type_abort(
pull_req->private_data, struct cli_pull_state);
- struct cli_request *read_state = cli_request_get(read_req);
+ struct cli_request *read_state = talloc_get_type_abort(
+ read_req->private_data, struct cli_request);
NTSTATUS status;
status = cli_read_andx_recv(read_req, &read_state->data.read.received,
@@ -351,7 +344,9 @@ static void cli_pull_read_done(struct async_req *read_req)
return;
}
- top_read = cli_request_get(state->reqs[state->top_req]);
+ top_read = talloc_get_type_abort(
+ state->reqs[state->top_req]->private_data,
+ struct cli_request);
DEBUG(10, ("cli_pull_read_done: Pushing %d bytes, %d already "
"pushed\n", (int)top_read->data.read.received,
@@ -384,7 +379,8 @@ static void cli_pull_read_done(struct async_req *read_req)
state->top_req));
new_req = cli_read_andx_send(
- state->reqs, state->cli, state->fnum,
+ state->reqs, state->ev, state->cli,
+ state->fnum,
state->start_offset + state->requested,
request_thistime);
@@ -424,21 +420,30 @@ NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum,
void *priv, SMB_OFF_T *received)
{
TALLOC_CTX *frame = talloc_stackframe();
+ struct event_context *ev;
struct async_req *req;
NTSTATUS result = NT_STATUS_NO_MEMORY;
- if (cli_tmp_event_ctx(frame, cli) == NULL) {
+ if (cli->fd_event != NULL) {
+ /*
+ * Can't use sync call while an async call is in flight
+ */
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ev = event_context_init(frame);
+ if (ev == NULL) {
goto nomem;
}
- req = cli_pull_send(frame, cli, fnum, start_offset, size, window_size,
- sink, priv);
+ req = cli_pull_send(frame, ev, cli, fnum, start_offset, size,
+ window_size, sink, priv);
if (req == NULL) {
goto nomem;
}
while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(cli->event_ctx);
+ event_loop_once(ev);
}
result = cli_pull_recv(req, received);
diff --git a/source3/libsmb/doserr.c b/source3/libsmb/doserr.c
index 50b5b2238c..c62918e214 100644
--- a/source3/libsmb/doserr.c
+++ b/source3/libsmb/doserr.c
@@ -91,6 +91,7 @@ werror_code_struct dos_errs[] =
{ "WERR_DEFAULT_JOIN_REQUIRED", WERR_DEFAULT_JOIN_REQUIRED },
{ "WERR_DEVICE_NOT_AVAILABLE", WERR_DEVICE_NOT_AVAILABLE },
{ "WERR_LOGON_FAILURE", WERR_LOGON_FAILURE },
+ { "WERR_WRONG_PASSWORD", WERR_WRONG_PASSWORD },
{ "WERR_PASSWORD_RESTRICTION", WERR_PASSWORD_RESTRICTION },
{ "WERR_NO_SUCH_DOMAIN", WERR_NO_SUCH_DOMAIN },
{ "WERR_NONE_MAPPED", WERR_NONE_MAPPED },
@@ -150,6 +151,7 @@ werror_str_struct dos_err_strs[] = {
{ WERR_GROUP_EXISTS, "Group already exists" },
{ WERR_DS_DRA_BAD_DN, "An invalid distinguished name was specified for this replication" },
{ WERR_DS_DRA_BAD_NC, "An invalid naming context was specified for this replication operation" },
+ { WERR_WRONG_PASSWORD, "The current password is incorrect" }
};
/*****************************************************************************
diff --git a/source3/libsmb/passchange.c b/source3/libsmb/passchange.c
index c8a4406949..4c76234e0c 100644
--- a/source3/libsmb/passchange.c
+++ b/source3/libsmb/passchange.c
@@ -42,7 +42,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
"%s.\n", remote_machine);
return NT_STATUS_UNSUCCESSFUL;
}
-
+
cli = cli_initialise();
if (!cli) {
return NT_STATUS_NO_MEMORY;
@@ -56,10 +56,10 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
cli_shutdown(cli);
return result;
}
-
+
make_nmb_name(&calling, global_myname() , 0x0);
make_nmb_name(&called , remote_machine, 0x20);
-
+
if (!cli_session_request(cli, &calling, &called)) {
asprintf(err_str, "machine %s rejected the session setup. "
"Error was : %s.\n",
@@ -68,7 +68,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
cli_shutdown(cli);
return result;
}
-
+
cli->protocol = PROTOCOL_NT1;
if (!cli_negprot(cli)) {
@@ -79,7 +79,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
cli_shutdown(cli);
return result;
}
-
+
/* Given things like SMB signing, restrict anonymous and the like,
try an authenticated connection first */
result = cli_session_setup(cli, user_name,
@@ -188,7 +188,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
} else if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)
|| NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) {
/* it failed, but for reasons such as wrong password, too short etc ... */
-
+
asprintf(err_str, "machine %s rejected the password change: "
"Error was : %s.\n",
remote_machine, get_friendly_nt_error_msg(result));
@@ -198,12 +198,12 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
/* OK, that failed, so try again... */
TALLOC_FREE(pipe_hnd);
-
+
/* Try anonymous NTLMSSP... */
cli_init_creds(cli, "", "", NULL);
-
+
result = NT_STATUS_UNSUCCESSFUL;
-
+
/* OK, this is ugly, but... try an anonymous pipe. */
result = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
&pipe_hnd);
@@ -227,10 +227,10 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
cli_shutdown(cli);
return result;
}
-
+
/* We have failed to change the user's password, and we think the server
just might not support SAMR password changes, so fall back */
-
+
if (lp_client_lanman_auth()) {
/* Use the old RAP method. */
if (cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) {
diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c
index 2d2588f70c..4abe5bb6de 100644
--- a/source3/libsmb/samlogon_cache.c
+++ b/source3/libsmb/samlogon_cache.c
@@ -59,48 +59,30 @@ bool netsamlogon_cache_shutdown(void)
Clear cache getpwnam and getgroups entries from the winbindd cache
***********************************************************************/
-void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, struct netr_SamInfo3 *info3)
+void netsamlogon_clear_cached_user(struct netr_SamInfo3 *info3)
{
- bool got_tdb = false;
- DOM_SID sid;
- fstring key_str, sid_string;
-
- /* We may need to call this function from smbd which will not have
- winbindd_cache.tdb open. Open the tdb if a NULL is passed. */
-
- if (!tdb) {
- tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
- WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
- TDB_DEFAULT, O_RDWR, 0600);
- if (!tdb) {
- DEBUG(5, ("netsamlogon_clear_cached_user: failed to open cache\n"));
- return;
- }
- got_tdb = true;
- }
-
- sid_copy(&sid, info3->base.domain_sid);
- sid_append_rid(&sid, info3->base.rid);
-
- /* Clear U/SID cache entry */
-
- fstr_sprintf(key_str, "U/%s", sid_to_fstring(sid_string, &sid));
-
- DEBUG(10, ("netsamlogon_clear_cached_user: clearing %s\n", key_str));
-
- tdb_delete(tdb, string_tdb_data(key_str));
+ DOM_SID user_sid;
+ fstring keystr, tmp;
- /* Clear UG/SID cache entry */
+ if (!info3) {
+ return;
+ }
- fstr_sprintf(key_str, "UG/%s", sid_to_fstring(sid_string, &sid));
+ if (!netsamlogon_cache_init()) {
+ DEBUG(0,("netsamlogon_clear_cached_user: cannot open "
+ "%s for write!\n",
+ NETSAMLOGON_TDB));
+ return;
+ }
+ sid_copy(&user_sid, info3->base.domain_sid);
+ sid_append_rid(&user_sid, info3->base.rid);
- DEBUG(10, ("netsamlogon_clear_cached_user: clearing %s\n", key_str));
+ /* Prepare key as DOMAIN-SID/USER-RID string */
+ slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, &user_sid));
- tdb_delete(tdb, string_tdb_data(key_str));
+ DEBUG(10,("netsamlogon_clear_cached_user: SID [%s]\n", keystr));
- if (got_tdb) {
- tdb_close(tdb);
- }
+ tdb_delete_bystring(netsamlogon_tdb, keystr);
}
/***********************************************************************
diff --git a/source3/nsswitch/libwbclient/wbc_pam.c b/source3/nsswitch/libwbclient/wbc_pam.c
index 293f71c347..20b42b6efb 100644
--- a/source3/nsswitch/libwbclient/wbc_pam.c
+++ b/source3/nsswitch/libwbclient/wbc_pam.c
@@ -236,6 +236,30 @@ done:
return wbc_status;
}
+static wbcErr wbc_create_password_policy_info(TALLOC_CTX *mem_ctx,
+ const struct winbindd_response *resp,
+ struct wbcUserPasswordPolicyInfo **_i)
+{
+ wbcErr wbc_status = WBC_ERR_SUCCESS;
+ struct wbcUserPasswordPolicyInfo *i;
+
+ i = talloc(mem_ctx, struct wbcUserPasswordPolicyInfo);
+ BAIL_ON_PTR_ERROR(i, wbc_status);
+
+ i->min_passwordage = resp->data.auth.policy.min_passwordage;
+ i->min_length_password = resp->data.auth.policy.min_length_password;
+ i->password_history = resp->data.auth.policy.password_history;
+ i->password_properties = resp->data.auth.policy.password_properties;
+ i->expire = resp->data.auth.policy.expire;
+
+ *_i = i;
+ i = NULL;
+
+done:
+ talloc_free(i);
+ return wbc_status;
+}
+
/** @brief Authenticate with more detailed information
*
* @param params Input parameters, WBC_AUTH_USER_LEVEL_HASH
@@ -523,3 +547,250 @@ wbcErr wbcLogoffUser(const char *username,
done:
return wbc_status;
}
+
+/** @brief Change a password for a user with more detailed information upon
+ * failure
+ * @param params Input parameters
+ * @param error User output details on WBC_ERR_PWD_CHANGE_FAILED
+ * @param reject_reason New password reject reason on WBC_ERR_PWD_CHANGE_FAILED
+ * @param policy Password policy output details on WBC_ERR_PWD_CHANGE_FAILED
+ *
+ * @return #wbcErr
+ **/
+
+wbcErr wbcChangeUserPasswordEx(const struct wbcChangePasswordParams *params,
+ struct wbcAuthErrorInfo **error,
+ enum wbcPasswordChangeRejectReason *reject_reason,
+ struct wbcUserPasswordPolicyInfo **policy)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ int cmd = 0;
+
+ /* validate input */
+
+ if (!params->account_name) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ if (error) {
+ *error = NULL;
+ }
+
+ if (policy) {
+ *policy = NULL;
+ }
+
+ if (reject_reason) {
+ *reject_reason = -1;
+ }
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ switch (params->level) {
+ case WBC_CHANGE_PASSWORD_LEVEL_PLAIN:
+ cmd = WINBINDD_PAM_CHAUTHTOK;
+
+ if (!params->account_name) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ strncpy(request.data.chauthtok.user, params->account_name,
+ sizeof(request.data.chauthtok.user) - 1);
+
+ if (params->old_password.plaintext) {
+ strncpy(request.data.chauthtok.oldpass,
+ params->old_password.plaintext,
+ sizeof(request.data.chauthtok.oldpass) - 1);
+ }
+
+ if (params->new_password.plaintext) {
+ strncpy(request.data.chauthtok.newpass,
+ params->new_password.plaintext,
+ sizeof(request.data.chauthtok.newpass) - 1);
+ }
+ break;
+
+ case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE:
+ cmd = WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP;
+
+ if (!params->account_name || !params->domain_name) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ if (params->old_password.response.old_lm_hash_enc_length &&
+ !params->old_password.response.old_lm_hash_enc_data) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ if (params->old_password.response.old_lm_hash_enc_length == 0 &&
+ params->old_password.response.old_lm_hash_enc_data) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ if (params->old_password.response.old_nt_hash_enc_length &&
+ !params->old_password.response.old_nt_hash_enc_data) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ if (params->old_password.response.old_nt_hash_enc_length == 0 &&
+ params->old_password.response.old_nt_hash_enc_data) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ if (params->new_password.response.lm_length &&
+ !params->new_password.response.lm_data) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ if (params->new_password.response.lm_length == 0 &&
+ params->new_password.response.lm_data) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ if (params->new_password.response.nt_length &&
+ !params->new_password.response.nt_data) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ if (params->new_password.response.nt_length == 0 &&
+ params->new_password.response.nt_data) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ strncpy(request.data.chng_pswd_auth_crap.user,
+ params->account_name,
+ sizeof(request.data.chng_pswd_auth_crap.user) - 1);
+
+ strncpy(request.data.chng_pswd_auth_crap.domain,
+ params->domain_name,
+ sizeof(request.data.chng_pswd_auth_crap.domain) - 1);
+
+ if (params->new_password.response.nt_data) {
+ memcpy(request.data.chng_pswd_auth_crap.new_nt_pswd,
+ params->new_password.response.nt_data,
+ request.data.chng_pswd_auth_crap.new_nt_pswd_len);
+ request.data.chng_pswd_auth_crap.new_nt_pswd_len =
+ params->new_password.response.nt_length;
+ }
+
+ if (params->new_password.response.lm_data) {
+ memcpy(request.data.chng_pswd_auth_crap.new_lm_pswd,
+ params->new_password.response.lm_data,
+ request.data.chng_pswd_auth_crap.new_lm_pswd_len);
+ request.data.chng_pswd_auth_crap.new_lm_pswd_len =
+ params->new_password.response.lm_length;
+ }
+
+ if (params->old_password.response.old_nt_hash_enc_data) {
+ memcpy(request.data.chng_pswd_auth_crap.old_nt_hash_enc,
+ params->old_password.response.old_nt_hash_enc_data,
+ request.data.chng_pswd_auth_crap.old_nt_hash_enc_len);
+ request.data.chng_pswd_auth_crap.old_nt_hash_enc_len =
+ params->old_password.response.old_nt_hash_enc_length;
+ }
+
+ if (params->old_password.response.old_lm_hash_enc_data) {
+ memcpy(request.data.chng_pswd_auth_crap.old_lm_hash_enc,
+ params->old_password.response.old_lm_hash_enc_data,
+ request.data.chng_pswd_auth_crap.old_lm_hash_enc_len);
+ request.data.chng_pswd_auth_crap.old_lm_hash_enc_len =
+ params->old_password.response.old_lm_hash_enc_length;
+ }
+
+ break;
+ default:
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ break;
+ }
+
+ if (cmd == 0) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ /* Send request */
+
+ wbc_status = wbcRequestResponse(cmd,
+ &request,
+ &response);
+ if (WBC_ERROR_IS_OK(wbc_status)) {
+ goto done;
+ }
+
+ /* Take the response above and return it to the caller */
+
+ if (response.data.auth.nt_status != 0) {
+ if (error) {
+ wbc_status = wbc_create_error_info(NULL,
+ &response,
+ error);
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ }
+
+ if (policy) {
+ wbc_status = wbc_create_password_policy_info(NULL,
+ &response,
+ policy);
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ if (reject_reason) {
+ *reject_reason = response.data.auth.reject_reason;
+ }
+
+ wbc_status = WBC_ERR_PWD_CHANGE_FAILED;
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ done:
+ return wbc_status;
+}
+
+/** @brief Change a password for a user
+ *
+ * @param username Name of user to authenticate
+ * @param old_password Old clear text password of user
+ * @param new_password New clear text password of user
+ *
+ * @return #wbcErr
+ **/
+
+wbcErr wbcChangeUserPassword(const char *username,
+ const char *old_password,
+ const char *new_password)
+{
+ wbcErr wbc_status = WBC_ERR_SUCCESS;
+ struct wbcChangePasswordParams params;
+
+ ZERO_STRUCT(params);
+
+ params.account_name = username;
+ params.level = WBC_CHANGE_PASSWORD_LEVEL_PLAIN;
+ params.old_password.plaintext = old_password;
+ params.new_password.plaintext = new_password;
+
+ wbc_status = wbcChangeUserPasswordEx(&params,
+ NULL,
+ NULL,
+ NULL);
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+done:
+ return wbc_status;
+}
diff --git a/source3/nsswitch/libwbclient/wbc_sid.c b/source3/nsswitch/libwbclient/wbc_sid.c
index 324a19bd56..f4ffa4e5ca 100644
--- a/source3/nsswitch/libwbclient/wbc_sid.c
+++ b/source3/nsswitch/libwbclient/wbc_sid.c
@@ -294,9 +294,18 @@ wbcErr wbcLookupSid(const struct wbcDomainSid *sid,
}
}
else {
+#if 0
+ /*
+ * Found by Coverity: In this particular routine we can't end
+ * up here with a non-NULL name. Further up there are just two
+ * exit paths that lead here, neither of which leave an
+ * allocated name. If you add more paths up there, re-activate
+ * this.
+ */
if (name != NULL) {
talloc_free(name);
}
+#endif
if (domain != NULL) {
talloc_free(domain);
}
diff --git a/source3/nsswitch/libwbclient/wbclient.c b/source3/nsswitch/libwbclient/wbclient.c
index 82decc2f78..bdde562a93 100644
--- a/source3/nsswitch/libwbclient/wbclient.c
+++ b/source3/nsswitch/libwbclient/wbclient.c
@@ -116,6 +116,8 @@ const char *wbcErrorString(wbcErr error)
return "WBC_ERR_UNKNOWN_GROUP";
case WBC_ERR_AUTH_ERROR:
return "WBC_ERR_AUTH_ERROR";
+ case WBC_ERR_PWD_CHANGE_FAILED:
+ return "WBC_ERR_PWD_CHANGE_FAILED";
}
return "unknown wbcErr value";
diff --git a/source3/nsswitch/libwbclient/wbclient.h b/source3/nsswitch/libwbclient/wbclient.h
index 2fefe0c072..cae3feec5b 100644
--- a/source3/nsswitch/libwbclient/wbclient.h
+++ b/source3/nsswitch/libwbclient/wbclient.h
@@ -44,7 +44,8 @@ enum _wbcErrType {
WBC_ERR_NSS_ERROR, /**< NSS_STATUS error **/
WBC_ERR_AUTH_ERROR, /**< Authentication failed **/
WBC_ERR_UNKNOWN_USER, /**< User account cannot be found */
- WBC_ERR_UNKNOWN_GROUP /**< Group account cannot be found */
+ WBC_ERR_UNKNOWN_GROUP, /**< Group account cannot be found */
+ WBC_ERR_PWD_CHANGE_FAILED /**< Password Change has failed */
};
typedef enum _wbcErrType wbcErr;
@@ -204,6 +205,41 @@ struct wbcAuthUserParams {
} password;
};
+/**
+ * @brief ChangePassword Parameters
+ **/
+
+struct wbcChangePasswordParams {
+ const char *account_name;
+ const char *domain_name;
+
+ uint32_t flags;
+
+ enum wbcChangePasswordLevel {
+ WBC_CHANGE_PASSWORD_LEVEL_PLAIN = 1,
+ WBC_CHANGE_PASSWORD_LEVEL_RESPONSE = 2
+ } level;
+
+ union {
+ const char *plaintext;
+ struct {
+ uint32_t old_nt_hash_enc_length;
+ uint8_t *old_nt_hash_enc_data;
+ uint32_t old_lm_hash_enc_length;
+ uint8_t *old_lm_hash_enc_data;
+ } response;
+ } old_password;
+ union {
+ const char *plaintext;
+ struct {
+ uint32_t nt_length;
+ uint8_t *nt_data;
+ uint32_t lm_length;
+ uint8_t *lm_data;
+ } response;
+ } new_password;
+};
+
/* wbcAuthUserParams->parameter_control */
#define WBC_MSV1_0_CLEARTEXT_PASSWORD_ALLOWED 0x00000002
@@ -304,6 +340,38 @@ struct wbcAuthErrorInfo {
char *display_string;
};
+/**
+ * @brief User Password Policy Information
+ **/
+
+/* wbcUserPasswordPolicyInfo->password_properties */
+
+#define WBC_DOMAIN_PASSWORD_COMPLEX 0x00000001
+#define WBC_DOMAIN_PASSWORD_NO_ANON_CHANGE 0x00000002
+#define WBC_DOMAIN_PASSWORD_NO_CLEAR_CHANGE 0x00000004
+#define WBC_DOMAIN_PASSWORD_LOCKOUT_ADMINS 0x00000008
+#define WBC_DOMAIN_PASSWORD_STORE_CLEARTEXT 0x00000010
+#define WBC_DOMAIN_REFUSE_PASSWORD_CHANGE 0x00000020
+
+struct wbcUserPasswordPolicyInfo {
+ uint32_t min_length_password;
+ uint32_t password_history;
+ uint32_t password_properties;
+ uint64_t expire;
+ uint64_t min_passwordage;
+};
+
+/**
+ * @brief Change Password Reject Reason
+ **/
+
+enum wbcPasswordChangeRejectReason {
+ WBC_PWD_CHANGE_REJECT_OTHER=0,
+ WBC_PWD_CHANGE_REJECT_TOO_SHORT=1,
+ WBC_PWD_CHANGE_REJECT_IN_HISTORY=2,
+ WBC_PWD_CHANGE_REJECT_COMPLEXITY=5
+};
+
/*
* DomainControllerInfo struct
*/
@@ -478,6 +546,14 @@ wbcErr wbcLogoffUser(const char *username,
uid_t uid,
const char *ccfilename);
+wbcErr wbcChangeUserPassword(const char *username,
+ const char *old_password,
+ const char *new_password);
+
+wbcErr wbcChangeUserPasswordEx(const struct wbcChangePasswordParams *params,
+ struct wbcAuthErrorInfo **error,
+ enum wbcPasswordChangeRejectReason *reject_reason,
+ struct wbcUserPasswordPolicyInfo **policy);
/*
* Resolve functions
diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c
index 463d9233d0..60524d1d1b 100644
--- a/source3/nsswitch/wbinfo.c
+++ b/source3/nsswitch/wbinfo.c
@@ -1341,6 +1341,28 @@ static bool wbinfo_ping(void)
return WBC_ERROR_IS_OK(wbc_status);
}
+static bool wbinfo_change_user_password(const char *username)
+{
+ wbcErr wbc_status;
+ char *old_password = NULL;
+ char *new_password = NULL;
+
+ old_password = wbinfo_prompt_pass("old", username);
+ new_password = wbinfo_prompt_pass("new", username);
+
+ wbc_status = wbcChangeUserPassword(username, old_password, new_password);
+
+ /* Display response */
+
+ d_printf("Password change for user %s %s\n", username,
+ WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
+
+ SAFE_FREE(old_password);
+ SAFE_FREE(new_password);
+
+ return WBC_ERROR_IS_OK(wbc_status);
+}
+
/* Main program */
enum {
@@ -1360,7 +1382,8 @@ enum {
OPT_UID_INFO,
OPT_GROUP_INFO,
OPT_VERBOSE,
- OPT_ONLINESTATUS
+ OPT_ONLINESTATUS,
+ OPT_CHANGE_USER_PASSWORD
};
int main(int argc, char **argv, char **envp)
@@ -1427,6 +1450,7 @@ int main(int argc, char **argv, char **envp)
#endif
{ "separator", 0, POPT_ARG_NONE, 0, OPT_SEPARATOR, "Get the active winbind separator", NULL },
{ "verbose", 0, POPT_ARG_NONE, 0, OPT_VERBOSE, "Print additional information per command", NULL },
+ { "change-user-password", 0, POPT_ARG_STRING, &string_arg, OPT_CHANGE_USER_PASSWORD, "Change the password for a user", NULL },
POPT_COMMON_CONFIGFILE
POPT_COMMON_VERSION
POPT_TABLEEND
@@ -1707,6 +1731,14 @@ int main(int argc, char **argv, char **envp)
goto done;
}
break;
+ case OPT_CHANGE_USER_PASSWORD:
+ if (!wbinfo_change_user_password(string_arg)) {
+ d_fprintf(stderr, "Could not change user password "
+ "for user %s\n", string_arg);
+ goto done;
+ }
+ break;
+
/* generic configuration options */
case OPT_DOMAIN_NAME:
break;
diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c
index 706df48923..9813101bc1 100644
--- a/source3/passdb/lookup_sid.c
+++ b/source3/passdb/lookup_sid.c
@@ -1311,7 +1311,16 @@ void uid_to_sid(DOM_SID *psid, uid_t uid)
/* Check the winbindd cache directly. */
ret = idmap_cache_find_uid2sid(uid, psid, &expired);
- if (!ret || expired || (ret && is_null_sid(psid))) {
+ if (ret && !expired && is_null_sid(psid)) {
+ /*
+ * Negative cache entry, we already asked.
+ * do legacy.
+ */
+ legacy_uid_to_sid(psid, uid);
+ return;
+ }
+
+ if (!ret || expired) {
/* Not in cache. Ask winbindd. */
if (!winbind_uid_to_sid(psid, uid)) {
if (!winbind_ping()) {
@@ -1348,7 +1357,16 @@ void gid_to_sid(DOM_SID *psid, gid_t gid)
/* Check the winbindd cache directly. */
ret = idmap_cache_find_gid2sid(gid, psid, &expired);
- if (!ret || expired || (ret && is_null_sid(psid))) {
+ if (ret && !expired && is_null_sid(psid)) {
+ /*
+ * Negative cache entry, we already asked.
+ * do legacy.
+ */
+ legacy_gid_to_sid(psid, gid);
+ return;
+ }
+
+ if (!ret || expired) {
/* Not in cache. Ask winbindd. */
if (!winbind_gid_to_sid(psid, gid)) {
if (!winbind_ping()) {
@@ -1402,7 +1420,15 @@ bool sid_to_uid(const DOM_SID *psid, uid_t *puid)
/* Check the winbindd cache directly. */
ret = idmap_cache_find_sid2uid(psid, puid, &expired);
- if (!ret || expired || (ret && (*puid == (uid_t)-1))) {
+ if (ret && !expired && (*puid == (uid_t)-1)) {
+ /*
+ * Negative cache entry, we already asked.
+ * do legacy.
+ */
+ return legacy_sid_to_uid(psid, puid);
+ }
+
+ if (!ret || expired) {
/* Not in cache. Ask winbindd. */
if (!winbind_sid_to_uid(puid, psid)) {
if (!winbind_ping()) {
@@ -1458,7 +1484,15 @@ bool sid_to_gid(const DOM_SID *psid, gid_t *pgid)
/* Check the winbindd cache directly. */
ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
- if (!ret || expired || (ret && (*pgid == (gid_t)-1))) {
+ if (ret && !expired && (*pgid == (gid_t)-1)) {
+ /*
+ * Negative cache entry, we already asked.
+ * do legacy.
+ */
+ return legacy_sid_to_gid(psid, pgid);
+ }
+
+ if (!ret || expired) {
/* Not in cache or negative. Ask winbindd. */
/* Ask winbindd if it can map this sid to a gid.
* (Idmap will check it is a valid SID and of the right type) */
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index 41dde87c42..f32a33fdb6 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -1637,6 +1637,7 @@ NTSTATUS rpc_api_pipe_req(struct rpc_pipe_client *cli,
uint16 frag_len = 0;
uint8 flags = 0;
uint32 ss_padding = 0;
+ ssize_t num_written;
data_sent_thistime = calculate_data_len_tosend(cli, data_left,
&frag_len, &auth_len, &ss_padding);
@@ -1724,43 +1725,39 @@ NTSTATUS rpc_api_pipe_req(struct rpc_pipe_client *cli,
}
return ret;
- } else {
- /* More packets to come - write and continue. */
- ssize_t num_written;
-
- switch (cli->transport_type) {
- case NCACN_NP:
- num_written = cli_write(cli->trans.np.cli,
- cli->trans.np.fnum,
- 8, /* 8 means message mode. */
- prs_data_p(&outgoing_pdu),
- (off_t)0,
- (size_t)hdr.frag_len);
-
- if (num_written != hdr.frag_len) {
- prs_mem_free(&outgoing_pdu);
- return cli_get_nt_error(
- cli->trans.np.cli);
- }
- break;
- case NCACN_IP_TCP:
- case NCACN_UNIX_STREAM:
- num_written = write_data(
- cli->trans.sock.fd,
- prs_data_p(&outgoing_pdu),
- (size_t)hdr.frag_len);
- if (num_written != hdr.frag_len) {
- NTSTATUS status;
- status = map_nt_error_from_unix(errno);
- prs_mem_free(&outgoing_pdu);
- return status;
- }
- break;
- default:
- DEBUG(0, ("unknown transport type %d\n",
- cli->transport_type));
- return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ switch (cli->transport_type) {
+ case NCACN_NP:
+ num_written = cli_write(cli->trans.np.cli,
+ cli->trans.np.fnum,
+ 8, /* 8 means message mode. */
+ prs_data_p(&outgoing_pdu),
+ (off_t)0,
+ (size_t)hdr.frag_len);
+
+ if (num_written != hdr.frag_len) {
+ prs_mem_free(&outgoing_pdu);
+ return cli_get_nt_error(cli->trans.np.cli);
}
+ break;
+ case NCACN_IP_TCP:
+ case NCACN_UNIX_STREAM:
+ num_written = write_data(
+ cli->trans.sock.fd,
+ prs_data_p(&outgoing_pdu),
+ (size_t)hdr.frag_len);
+ if (num_written != hdr.frag_len) {
+ NTSTATUS status;
+ status = map_nt_error_from_unix(errno);
+ prs_mem_free(&outgoing_pdu);
+ return status;
+ }
+ break;
+ default:
+ DEBUG(0, ("unknown transport type %d\n",
+ cli->transport_type));
+ return NT_STATUS_INTERNAL_ERROR;
}
current_data_offset += data_sent_thistime;
diff --git a/source3/rpc_client/ndr.c b/source3/rpc_client/ndr.c
index c494cce848..72a33137a6 100644
--- a/source3/rpc_client/ndr.c
+++ b/source3/rpc_client/ndr.c
@@ -60,7 +60,7 @@ NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli,
talloc_free(push);
prs_init_empty( &r_ps, mem_ctx, UNMARSHALL );
-
+
status = rpc_api_pipe_req(cli, opnum, &q_ps, &r_ps);
prs_mem_free( &q_ps );
diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c
index 072132f5ac..b3deb80c5d 100644
--- a/source3/rpc_parse/parse_prs.c
+++ b/source3/rpc_parse/parse_prs.c
@@ -395,18 +395,26 @@ bool prs_append_prs_data(prs_struct *dst, prs_struct *src)
Append some data from one parse_struct into another.
********************************************************************/
-bool prs_append_some_prs_data(prs_struct *dst, prs_struct *src, int32 start, uint32 len)
-{
- if (len == 0)
- return True;
+bool prs_append_some_data(prs_struct *dst, void *src_base, uint32_t start,
+ uint32_t len)
+{
+ if (len == 0) {
+ return true;
+ }
- if(!prs_grow(dst, len))
- return False;
-
- memcpy(&dst->data_p[dst->data_offset], src->data_p + start, (size_t)len);
+ if(!prs_grow(dst, len)) {
+ return false;
+ }
+
+ memcpy(&dst->data_p[dst->data_offset], src_base + start, (size_t)len);
dst->data_offset += len;
+ return true;
+}
- return True;
+bool prs_append_some_prs_data(prs_struct *dst, prs_struct *src, int32 start,
+ uint32 len)
+{
+ return prs_append_some_data(dst, src->data_p, start, len);
}
/*******************************************************************
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 332a2e4da3..b2d19e11e3 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -164,7 +164,7 @@ static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
ssize_t toread;
NTSTATUS status;
- memcpy(writeX_header, lenbuf, sizeof(lenbuf));
+ memcpy(writeX_header, lenbuf, 4);
status = read_socket_with_timeout(
fd, writeX_header + 4,
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 06aa835cb0..16f8a5b177 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3264,25 +3264,22 @@ normal_read:
}
TALLOC_FREE(req->outbuf);
return;
- } else {
- reply_outbuf(req, 12, smb_maxcnt);
+ }
- nread = read_file(fsp, smb_buf(req->outbuf), startpos,
- smb_maxcnt);
- if (nread < 0) {
- reply_unixerror(req, ERRDOS, ERRnoaccess);
- return;
- }
+ reply_outbuf(req, 12, smb_maxcnt);
- setup_readX_header((char *)req->outbuf, nread);
+ nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
+ if (nread < 0) {
+ reply_unixerror(req, ERRDOS, ERRnoaccess);
+ return;
+ }
- DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
- fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+ setup_readX_header((char *)req->outbuf, nread);
- chain_reply(req);
+ DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
+ fsp->fnum, (int)smb_maxcnt, (int)nread ) );
- return;
- }
+ chain_reply(req);
}
/****************************************************************************
@@ -7126,6 +7123,7 @@ void reply_getattrE(struct smb_request *req)
SMB_STRUCT_STAT sbuf;
int mode;
files_struct *fsp;
+ struct timespec create_ts;
START_PROFILE(SMBgetattrE);
@@ -7160,9 +7158,9 @@ void reply_getattrE(struct smb_request *req)
reply_outbuf(req, 11, 0);
- srv_put_dos_date2((char *)req->outbuf, smb_vwv0,
- get_create_time(&sbuf,
- lp_fake_dir_create_times(SNUM(conn))));
+ create_ts = get_create_timespec(&sbuf,
+ lp_fake_dir_create_times(SNUM(conn)));
+ srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
/* Should we check pending modtime here ? JRA */
srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 75a5b30e30..d8942e42b9 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -4897,6 +4897,117 @@ static bool subst_test(const char *str, const char *user, const char *domain,
return result;
}
+static void chain1_open_completion(struct async_req *req)
+{
+ int fnum;
+ NTSTATUS status;
+
+ status = cli_open_recv(req, &fnum);
+ TALLOC_FREE(req);
+
+ d_printf("cli_open_recv returned %s: %d\n",
+ nt_errstr(status),
+ NT_STATUS_IS_OK(status) ? fnum : -1);
+}
+
+static void chain1_read_completion(struct async_req *req)
+{
+ NTSTATUS status;
+ ssize_t received;
+ uint8_t *rcvbuf;
+
+ status = cli_read_andx_recv(req, &received, &rcvbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(req);
+ d_printf("cli_read_andx_recv returned %s\n",
+ nt_errstr(status));
+ return;
+ }
+
+ d_printf("got %d bytes: %.*s\n", (int)received, (int)received,
+ (char *)rcvbuf);
+ TALLOC_FREE(req);
+}
+
+static void chain1_close_completion(struct async_req *req)
+{
+ NTSTATUS status;
+
+ status = cli_close_recv(req);
+ *((bool *)(req->async.priv)) = true;
+
+ TALLOC_FREE(req);
+
+ d_printf("cli_close returned %s\n", nt_errstr(status));
+}
+
+static bool run_chain1(int dummy)
+{
+ struct cli_state *cli1;
+ struct event_context *evt = event_context_init(NULL);
+ struct async_req *reqs[4];
+ bool done = false;
+
+ printf("starting chain1 test\n");
+ if (!torture_open_connection(&cli1, 0)) {
+ return False;
+ }
+
+ cli_sockopt(cli1, sockops);
+
+ cli_chain_cork(cli1, evt, 0);
+ reqs[0] = cli_open_send(talloc_tos(), evt, cli1, "\\test",
+ O_CREAT|O_RDWR, 0);
+ reqs[0]->async.fn = chain1_open_completion;
+ reqs[1] = cli_read_andx_send(talloc_tos(), evt, cli1, 0, 0, 10);
+ reqs[1]->async.fn = chain1_read_completion;
+ reqs[2] = cli_read_andx_send(talloc_tos(), evt, cli1, 0, 1, 10);
+ reqs[2]->async.fn = chain1_read_completion;
+ reqs[3] = cli_close_send(talloc_tos(), evt, cli1, 0);
+ reqs[3]->async.fn = chain1_close_completion;
+ reqs[3]->async.priv = (void *)&done;
+ cli_chain_uncork(cli1);
+
+ while (!done) {
+ event_loop_once(evt);
+ }
+
+ torture_close_connection(cli1);
+ return True;
+}
+
+static bool run_cli_echo(int dummy)
+{
+ struct cli_state *cli;
+ struct event_context *ev = event_context_init(NULL);
+ struct async_req *req;
+ NTSTATUS status;
+
+ printf("starting chain1 test\n");
+ if (!torture_open_connection(&cli, 0)) {
+ return false;
+ }
+ cli_sockopt(cli, sockops);
+
+ req = cli_echo_send(ev, ev, cli, 5, data_blob_const("hello", 5));
+ if (req == NULL) {
+ d_printf("cli_echo_send failed\n");
+ return false;
+ }
+
+ while (req->state < ASYNC_REQ_DONE) {
+ event_loop_once(ev);
+ }
+
+ status = cli_echo_recv(req);
+ d_printf("cli_echo returned %s\n", nt_errstr(status));
+
+ TALLOC_FREE(req);
+
+ torture_close_connection(cli);
+ return NT_STATUS_IS_OK(status);
+}
+
static bool run_local_substitute(int dummy)
{
bool ok = true;
@@ -5394,6 +5505,8 @@ static struct {
{"FDSESS", run_fdsesstest, 0},
{ "EATEST", run_eatest, 0},
{ "SESSSETUP_BENCH", run_sesssetup_bench, 0},
+ { "CHAIN1", run_chain1, 0},
+ { "CLI_ECHO", run_cli_echo, 0},
{ "LOCAL-SUBSTITUTE", run_local_substitute, 0},
{ "LOCAL-GENCACHE", run_local_gencache, 0},
{ "LOCAL-RBTREE", run_local_rbtree, 0},
diff --git a/source3/utils/net_dom.c b/source3/utils/net_dom.c
index f13b9c23d0..5544cf8a2d 100644
--- a/source3/utils/net_dom.c
+++ b/source3/utils/net_dom.c
@@ -37,8 +37,8 @@ static int net_dom_unjoin(struct net_context *c, int argc, const char **argv)
const char *server_name = NULL;
const char *account = NULL;
const char *password = NULL;
- uint32_t unjoin_flags = WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE |
- WKSSVC_JOIN_FLAGS_JOIN_TYPE;
+ uint32_t unjoin_flags = NETSETUP_ACCT_DELETE |
+ NETSETUP_JOIN_DOMAIN;
struct cli_state *cli = NULL;
bool do_reboot = false;
NTSTATUS ntstatus;
@@ -125,8 +125,8 @@ static int net_dom_join(struct net_context *c, int argc, const char **argv)
const char *account_ou = NULL;
const char *Account = NULL;
const char *password = NULL;
- uint32_t join_flags = WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
- WKSSVC_JOIN_FLAGS_JOIN_TYPE;
+ uint32_t join_flags = NETSETUP_ACCT_CREATE |
+ NETSETUP_JOIN_DOMAIN;
struct cli_state *cli = NULL;
bool do_reboot = false;
NTSTATUS ntstatus;
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
index 347ddd039f..6db5bc753b 100644
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -658,135 +658,37 @@ static int rpc_user_add(struct net_context *c, int argc, const char **argv)
/**
* Rename a user on a remote RPC server.
*
- * All parameters are provided by the run_rpc_command function, except for
- * argc, argv which are passed through.
- *
- * @param domain_sid The domain sid acquired from the remote server.
- * @param cli A cli_state connected to the server.
- * @param mem_ctx Talloc context, destroyed on completion of the function.
* @param argc Standard main() style argc.
* @param argv Standard main() style argv. Initial components are already
* stripped.
*
- * @return Normal NTSTATUS return.
+ * @return A shell status integer (0 for success).
**/
-static NTSTATUS rpc_user_rename_internals(struct net_context *c,
- const DOM_SID *domain_sid,
- const char *domain_name,
- struct cli_state *cli,
- struct rpc_pipe_client *pipe_hnd,
- TALLOC_CTX *mem_ctx,
- int argc,
- const char **argv)
+static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
{
- POLICY_HND connect_pol, domain_pol, user_pol;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- uint32 info_level = 7;
- const char *old_name, *new_name;
- struct samr_Ids user_rids, name_types;
- struct lsa_String lsa_acct_name;
- union samr_UserInfo *info = NULL;
+ NET_API_STATUS status;
+ struct USER_INFO_0 u0;
+ uint32_t parm_err = 0;
if (argc != 2 || c->display_usage) {
rpc_user_usage(c, argc, argv);
- return NT_STATUS_OK;
- }
-
- old_name = argv[0];
- new_name = argv[1];
-
- /* Get sam policy handle */
-
- result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
- pipe_hnd->desthost,
- MAXIMUM_ALLOWED_ACCESS,
- &connect_pol);
-
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
-
- /* Get domain policy handle */
-
- result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
- &connect_pol,
- MAXIMUM_ALLOWED_ACCESS,
- CONST_DISCARD(struct dom_sid2 *, domain_sid),
- &domain_pol);
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
-
- init_lsa_String(&lsa_acct_name, old_name);
-
- result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
- &domain_pol,
- 1,
- &lsa_acct_name,
- &user_rids,
- &name_types);
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
-
- /* Open domain user */
- result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
- &domain_pol,
- MAXIMUM_ALLOWED_ACCESS,
- user_rids.ids[0],
- &user_pol);
-
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
-
- /* Query user info */
- result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
- &user_pol,
- info_level,
- &info);
-
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
+ return 0;
}
- init_samr_user_info7(&info->info7, new_name);
+ u0.usri0_name = argv[1];
- /* Set new name */
- result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
- &user_pol,
- info_level,
- info);
-
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
-
- done:
- if (!NT_STATUS_IS_OK(result)) {
- d_fprintf(stderr, "Failed to rename user from %s to %s - %s\n", old_name, new_name,
- nt_errstr(result));
+ status = NetUserSetInfo(c->opt_host, argv[0],
+ 0, (uint8_t *)&u0, &parm_err);
+ if (status) {
+ d_fprintf(stderr, "Failed to rename user from %s to %s - %s\n",
+ argv[0], argv[1],
+ libnetapi_get_error_string(c->netapi_ctx, status));
} else {
- d_printf("Renamed user from %s to %s\n", old_name, new_name);
+ d_printf("Renamed user from %s to %s\n", argv[0], argv[1]);
}
- return result;
-}
-/**
- * Rename a user on a remote RPC server.
- *
- * @param argc Standard main() style argc.
- * @param argv Standard main() style argv. Initial components are already
- * stripped.
- *
- * @return A shell status integer (0 for success).
- **/
-
-static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
-{
- return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
- rpc_user_rename_internals, argc, argv);
+ return status;
}
/**
@@ -823,271 +725,93 @@ static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
}
/**
- * Set a password for a user on a remote RPC server.
- *
- * All parameters are provided by the run_rpc_command function, except for
- * argc, argv which are passed through.
+ * Set a user's password on a remote RPC server.
*
- * @param domain_sid The domain sid acquired from the remote server.
- * @param cli A cli_state connected to the server.
- * @param mem_ctx Talloc context, destroyed on completion of the function.
* @param argc Standard main() style argc.
* @param argv Standard main() style argv. Initial components are already
* stripped.
*
- * @return Normal NTSTATUS return.
+ * @return A shell status integer (0 for success).
**/
-static NTSTATUS rpc_user_password_internals(struct net_context *c,
- const DOM_SID *domain_sid,
- const char *domain_name,
- struct cli_state *cli,
- struct rpc_pipe_client *pipe_hnd,
- TALLOC_CTX *mem_ctx,
- int argc,
- const char **argv)
+static int rpc_user_password(struct net_context *c, int argc, const char **argv)
{
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- POLICY_HND connect_pol, domain_pol, user_pol;
- const char *user;
- const char *new_password;
+ NET_API_STATUS status;
char *prompt = NULL;
- union samr_UserInfo info;
- struct samr_CryptPassword crypt_pwd;
+ struct USER_INFO_1003 u1003;
+ uint32_t parm_err = 0;
if (argc < 1 || c->display_usage) {
rpc_user_usage(c, argc, argv);
- return NT_STATUS_OK;
+ return 0;
}
- user = argv[0];
-
if (argv[1]) {
- new_password = argv[1];
+ u1003.usri1003_password = argv[1];
} else {
- asprintf(&prompt, "Enter new password for %s:", user);
- new_password = getpass(prompt);
+ asprintf(&prompt, "Enter new password for %s:", argv[0]);
+ u1003.usri1003_password = getpass(prompt);
SAFE_FREE(prompt);
}
- /* Get sam policy and domain handles */
-
- result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
- pipe_hnd->desthost,
- MAXIMUM_ALLOWED_ACCESS,
- &connect_pol);
-
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
-
- result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
- &connect_pol,
- MAXIMUM_ALLOWED_ACCESS,
- CONST_DISCARD(struct dom_sid2 *, domain_sid),
- &domain_pol);
-
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
-
- /* Get handle on user */
-
- {
- struct samr_Ids user_rids, name_types;
- struct lsa_String lsa_acct_name;
-
- init_lsa_String(&lsa_acct_name, user);
-
- result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
- &domain_pol,
- 1,
- &lsa_acct_name,
- &user_rids,
- &name_types);
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
-
- result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
- &domain_pol,
- MAXIMUM_ALLOWED_ACCESS,
- user_rids.ids[0],
- &user_pol);
-
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
- }
-
- /* Set password on account */
-
- init_samr_CryptPassword(new_password,
- &cli->user_session_key,
- &crypt_pwd);
-
- init_samr_user_info24(&info.info24, crypt_pwd.data, 24);
-
- result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
- &user_pol,
- 24,
- &info);
-
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
+ status = NetUserSetInfo(c->opt_host, argv[0], 1003, (uint8_t *)&u1003, &parm_err);
/* Display results */
+ if (status != 0) {
+ d_fprintf(stderr, "Failed to set password for '%s' with: %s.\n",
+ argv[0], libnetapi_get_error_string(c->netapi_ctx,
+ status));
+ return -1;
+ }
- done:
- return result;
-
+ return 0;
}
/**
- * Set a user's password on a remote RPC server.
+ * List a user's groups from a remote RPC server.
*
* @param argc Standard main() style argc.
* @param argv Standard main() style argv. Initial components are already
* stripped.
*
- * @return A shell status integer (0 for success).
+ * @return A shell status integer (0 for success)
**/
-static int rpc_user_password(struct net_context *c, int argc, const char **argv)
-{
- return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
- rpc_user_password_internals, argc, argv);
-}
-
-/**
- * List user's groups on a remote RPC server.
- *
- * All parameters are provided by the run_rpc_command function, except for
- * argc, argv which are passed through.
- *
- * @param domain_sid The domain sid acquired from the remote server.
- * @param cli A cli_state connected to the server.
- * @param mem_ctx Talloc context, destroyed on completion of the function.
- * @param argc Standard main() style argc.
- * @param argv Standard main() style argv. Initial components are already
- * stripped.
- *
- * @return Normal NTSTATUS return.
- **/
+static int rpc_user_info(struct net_context *c, int argc, const char **argv)
-static NTSTATUS rpc_user_info_internals(struct net_context *c,
- const DOM_SID *domain_sid,
- const char *domain_name,
- struct cli_state *cli,
- struct rpc_pipe_client *pipe_hnd,
- TALLOC_CTX *mem_ctx,
- int argc,
- const char **argv)
{
- POLICY_HND connect_pol, domain_pol, user_pol;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ NET_API_STATUS status;
+ struct GROUP_USERS_INFO_0 *u0 = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
int i;
- struct samr_RidWithAttributeArray *rid_array = NULL;
- struct lsa_Strings names;
- struct samr_Ids types;
- uint32_t *lrids = NULL;
- struct samr_Ids rids, name_types;
- struct lsa_String lsa_acct_name;
if (argc < 1 || c->display_usage) {
rpc_user_usage(c, argc, argv);
- return NT_STATUS_OK;
+ return 0;
}
- /* Get sam policy handle */
-
- result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
- pipe_hnd->desthost,
- MAXIMUM_ALLOWED_ACCESS,
- &connect_pol);
- if (!NT_STATUS_IS_OK(result)) goto done;
-
- /* Get domain policy handle */
-
- result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
- &connect_pol,
- MAXIMUM_ALLOWED_ACCESS,
- CONST_DISCARD(struct dom_sid2 *, domain_sid),
- &domain_pol);
- if (!NT_STATUS_IS_OK(result)) goto done;
-
- /* Get handle on user */
-
- init_lsa_String(&lsa_acct_name, argv[0]);
-
- result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
- &domain_pol,
- 1,
- &lsa_acct_name,
- &rids,
- &name_types);
-
- if (!NT_STATUS_IS_OK(result)) goto done;
-
- result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
- &domain_pol,
- MAXIMUM_ALLOWED_ACCESS,
- rids.ids[0],
- &user_pol);
- if (!NT_STATUS_IS_OK(result)) goto done;
-
- result = rpccli_samr_GetGroupsForUser(pipe_hnd, mem_ctx,
- &user_pol,
- &rid_array);
-
- if (!NT_STATUS_IS_OK(result)) goto done;
-
- /* Look up rids */
-
- if (rid_array->count) {
- if ((lrids = TALLOC_ARRAY(mem_ctx, uint32, rid_array->count)) == NULL) {
- result = NT_STATUS_NO_MEMORY;
- goto done;
- }
-
- for (i = 0; i < rid_array->count; i++)
- lrids[i] = rid_array->rids[i].rid;
-
- result = rpccli_samr_LookupRids(pipe_hnd, mem_ctx,
- &domain_pol,
- rid_array->count,
- lrids,
- &names,
- &types);
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
-
- /* Display results */
-
- for (i = 0; i < names.count; i++)
- printf("%s\n", names.names[i].string);
+ status = NetUserGetGroups(c->opt_host,
+ argv[0],
+ 0,
+ (uint8_t **)&u0,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries);
+ if (status != 0) {
+ d_fprintf(stderr, "Failed to get groups for '%s' with: %s.\n",
+ argv[0], libnetapi_get_error_string(c->netapi_ctx,
+ status));
+ return -1;
}
- done:
- return result;
-}
-/**
- * List a user's groups from a remote RPC server.
- *
- * @param argc Standard main() style argc.
- * @param argv Standard main() style argv. Initial components are already
- * stripped.
- *
- * @return A shell status integer (0 for success)
- **/
+ for (i=0; i < entries_read; i++) {
+ printf("%s\n", u0->grui0_name);
+ u0++;
+ }
-static int rpc_user_info(struct net_context *c, int argc, const char **argv)
-{
- return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
- rpc_user_info_internals, argc, argv);
+ return 0;
}
/**
@@ -1106,80 +830,54 @@ static int rpc_user_info(struct net_context *c, int argc, const char **argv)
* @return Normal NTSTATUS return.
**/
-static NTSTATUS rpc_user_list_internals(struct net_context *c,
- const DOM_SID *domain_sid,
- const char *domain_name,
- struct cli_state *cli,
- struct rpc_pipe_client *pipe_hnd,
- TALLOC_CTX *mem_ctx,
- int argc,
- const char **argv)
+static int rpc_user_list(struct net_context *c, int argc, const char **argv)
{
- POLICY_HND connect_pol, domain_pol;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- uint32 start_idx=0, num_entries, i, loop_count = 0;
-
- /* Get sam policy handle */
-
- result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
- pipe_hnd->desthost,
- MAXIMUM_ALLOWED_ACCESS,
- &connect_pol);
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
-
- /* Get domain policy handle */
-
- result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
- &connect_pol,
- MAXIMUM_ALLOWED_ACCESS,
- CONST_DISCARD(struct dom_sid2 *, domain_sid),
- &domain_pol);
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
+ NET_API_STATUS status;
+ uint32_t start_idx=0, num_entries, i, loop_count = 0;
+ struct NET_DISPLAY_USER *info = NULL;
+ void *buffer = NULL;
/* Query domain users */
if (c->opt_long_list_entries)
d_printf("\nUser name Comment"
"\n-----------------------------\n");
do {
- const char *user = NULL;
- const char *desc = NULL;
- uint32 max_entries, max_size;
- uint32_t total_size, returned_size;
- union samr_DispInfo info;
+ uint32_t max_entries, max_size;
get_query_dispinfo_params(
loop_count, &max_entries, &max_size);
- result = rpccli_samr_QueryDisplayInfo(pipe_hnd, mem_ctx,
- &domain_pol,
- 1,
- start_idx,
- max_entries,
- max_size,
- &total_size,
- &returned_size,
- &info);
- loop_count++;
- start_idx += info.info1.count;
- num_entries = info.info1.count;
+ status = NetQueryDisplayInformation(c->opt_host,
+ 1,
+ start_idx,
+ max_entries,
+ max_size,
+ &num_entries,
+ &buffer);
+ if (status != 0 && status != ERROR_MORE_DATA) {
+ return status;
+ }
+
+ info = (struct NET_DISPLAY_USER *)buffer;
for (i = 0; i < num_entries; i++) {
- user = info.info1.entries[i].account_name.string;
- if (c->opt_long_list_entries)
- desc = info.info1.entries[i].description.string;
+
if (c->opt_long_list_entries)
- printf("%-21.21s %s\n", user, desc);
+ printf("%-21.21s %s\n", info->usri1_name,
+ info->usri1_comment);
else
- printf("%s\n", user);
+ printf("%s\n", info->usri1_name);
+ info++;
}
- } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
- done:
- return result;
+ NetApiBufferFree(buffer);
+
+ loop_count++;
+ start_idx += num_entries;
+
+ } while (status == ERROR_MORE_DATA);
+
+ return status;
}
/**
@@ -1256,9 +954,7 @@ int net_rpc_user(struct net_context *c, int argc, const char **argv)
return 0;
}
- return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
- rpc_user_list_internals,
- argc, argv);
+ return rpc_user_list(c, argc, argv);
}
return net_run_function(c, argc, argv, "net rpc user", func);
@@ -1270,9 +966,7 @@ static NTSTATUS rpc_sh_user_list(struct net_context *c,
struct rpc_pipe_client *pipe_hnd,
int argc, const char **argv)
{
- return rpc_user_list_internals(c, ctx->domain_sid, ctx->domain_name,
- ctx->cli, pipe_hnd, mem_ctx,
- argc, argv);
+ return werror_to_ntstatus(W_ERROR(rpc_user_list(c, argc, argv)));
}
static NTSTATUS rpc_sh_user_info(struct net_context *c,
@@ -1281,9 +975,7 @@ static NTSTATUS rpc_sh_user_info(struct net_context *c,
struct rpc_pipe_client *pipe_hnd,
int argc, const char **argv)
{
- return rpc_user_info_internals(c, ctx->domain_sid, ctx->domain_name,
- ctx->cli, pipe_hnd, mem_ctx,
- argc, argv);
+ return werror_to_ntstatus(W_ERROR(rpc_user_info(c, argc, argv)));
}
static NTSTATUS rpc_sh_handle_user(struct net_context *c,
diff --git a/source3/utils/net_rpc_shell.c b/source3/utils/net_rpc_shell.c
index c6051dc976..3aaed1ed18 100644
--- a/source3/utils/net_rpc_shell.c
+++ b/source3/utils/net_rpc_shell.c
@@ -217,6 +217,15 @@ int net_rpc_shell(struct net_context *c, int argc, const char **argv)
return -1;
}
+ if (libnetapi_init(&c->netapi_ctx) != 0) {
+ return -1;
+ }
+ libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
+ libnetapi_set_password(c->netapi_ctx, c->opt_password);
+ if (c->opt_kerberos) {
+ libnetapi_set_use_kerberos(c->netapi_ctx);
+ }
+
ctx = TALLOC_P(NULL, struct rpc_sh_ctx);
if (ctx == NULL) {
d_fprintf(stderr, "talloc failed\n");
diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c
index 493a249bea..600fe52f0d 100644
--- a/source3/utils/smbpasswd.c
+++ b/source3/utils/smbpasswd.c
@@ -210,7 +210,7 @@ static char *prompt_for_new_password(bool stdin_get)
fstring new_pw;
ZERO_ARRAY(new_pw);
-
+
p = get_pass("New SMB password:", stdin_get);
fstrcpy(new_pw, p);
@@ -254,7 +254,7 @@ static NTSTATUS password_change(const char *remote_mach, char *username,
SAFE_FREE(err_str);
return ret;
}
-
+
ret = local_password_change(username, local_flags, new_pw,
&err_str, &msg_str);
@@ -278,7 +278,7 @@ static bool store_ldap_admin_pw (char* pw)
if (!secrets_init())
return False;
-
+
return secrets_store_ldap_pw(lp_ldap_admin_dn(), pw);
}
@@ -316,7 +316,7 @@ static int process_root(int local_flags)
DEBUG(0, ("Failed to open passdb!\n"));
exit(1);
}
-
+
/* Ensure we have a SAM sid. */
get_global_sam_sid();
@@ -330,7 +330,7 @@ static int process_root(int local_flags)
(remote_machine != NULL))) {
usage();
}
-
+
/* Only load interfaces if we are doing network operations. */
if (remote_machine) {
@@ -386,19 +386,19 @@ static int process_root(int local_flags)
exit(1);
}
}
-
+
/* prepare uppercased and '$' terminated username */
slprintf(buf, sizeof(buf) - 1, "%s$", user_name);
fstrcpy(user_name, buf);
-
+
} else {
-
+
if (remote_machine != NULL) {
old_passwd = get_pass("Old SMB password:",stdin_passwd_get);
}
-
+
if (!(local_flags & LOCAL_SET_PASSWORD)) {
-
+
/*
* If we are trying to enable a user, first we need to find out
* if they are using a modern version of the smbpasswd file that
@@ -407,10 +407,10 @@ static int process_root(int local_flags)
* password. If not (ie. they have a no stored password in the
* smbpasswd file) then we need to prompt for a new password.
*/
-
+
if(local_flags & LOCAL_ENABLE_USER) {
struct samu *sampass = NULL;
-
+
sampass = samu_new( NULL );
if (!sampass) {
fprintf(stderr, "talloc fail for struct samu.\n");
@@ -428,10 +428,10 @@ static int process_root(int local_flags)
TALLOC_FREE(sampass);
}
}
-
+
if((local_flags & LOCAL_SET_PASSWORD) && (new_passwd == NULL)) {
new_passwd = prompt_for_new_password(stdin_passwd_get);
-
+
if(!new_passwd) {
fprintf(stderr, "Unable to get new password.\n");
exit(1);
@@ -451,7 +451,7 @@ static int process_root(int local_flags)
printf("Password changed for user %s on %s.\n", user_name, remote_machine );
} else if(!(local_flags & (LOCAL_ADD_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|LOCAL_DELETE_USER|LOCAL_SET_NO_PASSWORD|LOCAL_SET_PASSWORD))) {
struct samu *sampass = NULL;
-
+
sampass = samu_new( NULL );
if (!sampass) {
fprintf(stderr, "talloc fail for struct samu.\n");
@@ -507,7 +507,7 @@ static int process_nonroot(int local_flags)
exit(1);
}
}
-
+
/*
* A non-root user is always setting a password
* via a remote machine (even if that machine is
@@ -523,13 +523,13 @@ static int process_nonroot(int local_flags)
if (remote_machine != NULL) {
old_pw = get_pass("Old SMB password:",stdin_passwd_get);
}
-
+
if (!new_passwd) {
new_pw = prompt_for_new_password(stdin_passwd_get);
}
else
new_pw = smb_xstrdup(new_passwd);
-
+
if (!new_pw) {
fprintf(stderr, "Unable to get new password.\n");
exit(1);
@@ -561,7 +561,7 @@ int main(int argc, char **argv)
TALLOC_CTX *frame = talloc_stackframe();
int local_flags = 0;
int ret;
-
+
AllowDebugChange = False;
#if defined(HAVE_SET_AUTH_PARAMETERS)
@@ -577,12 +577,12 @@ int main(int argc, char **argv)
local_flags = process_options(argc, argv, local_flags);
setup_logging("smbpasswd", True);
-
+
/*
* Set the machine NETBIOS name if not already
* set from the config file.
*/
-
+
if (!init_names())
return 1;
diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c
index 097fa3907d..94e3bad7b2 100644
--- a/source3/winbindd/winbindd_ads.c
+++ b/source3/winbindd/winbindd_ads.c
@@ -1239,8 +1239,11 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
continue;
}
- (*names)[ret_count] = CONST_DISCARD(char *, trusts.array[i].netbios_name);
- (*alt_names)[ret_count] = CONST_DISCARD(char *, trusts.array[i].dns_name);
+ (*names)[ret_count] = talloc_strdup(mem_ctx, trusts.array[i].netbios_name);
+ (*alt_names)[ret_count] = talloc_strdup(mem_ctx, trusts.array[i].dns_name);
+ if ((*names)[ret_count] == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
if (trusts.array[i].sid) {
sid_copy(&(*dom_sids)[ret_count], trusts.array[i].sid);
} else {
@@ -1254,7 +1257,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
if (trusts.array[i].sid) {
sid_copy( &d.sid, trusts.array[i].sid);
} else {
- sid_copy(&(*dom_sids)[ret_count], &global_sid_NULL);
+ sid_copy(&d.sid, &global_sid_NULL);
}
if ( domain->primary ) {
diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c
index c9d857c2ec..2fbb01b623 100644
--- a/source3/winbindd/winbindd_cache.c
+++ b/source3/winbindd/winbindd_cache.c
@@ -2259,6 +2259,8 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
void wcache_invalidate_samlogon(struct winbindd_domain *domain,
struct netr_SamInfo3 *info3)
{
+ DOM_SID sid;
+ fstring key_str, sid_string;
struct winbind_cache *cache;
/* dont clear cached U/SID and UG/SID entries when we want to logon
@@ -2272,7 +2274,26 @@ void wcache_invalidate_samlogon(struct winbindd_domain *domain,
return;
cache = get_cache(domain);
- netsamlogon_clear_cached_user(cache->tdb, info3);
+
+ if (!cache->tdb) {
+ return;
+ }
+
+ sid_copy(&sid, info3->base.domain_sid);
+ sid_append_rid(&sid, info3->base.rid);
+
+ /* Clear U/SID cache entry */
+ fstr_sprintf(key_str, "U/%s", sid_to_fstring(sid_string, &sid));
+ DEBUG(10, ("wcache_invalidate_samlogon: clearing %s\n", key_str));
+ tdb_delete(cache->tdb, string_tdb_data(key_str));
+
+ /* Clear UG/SID cache entry */
+ fstr_sprintf(key_str, "UG/%s", sid_to_fstring(sid_string, &sid));
+ DEBUG(10, ("wcache_invalidate_samlogon: clearing %s\n", key_str));
+ tdb_delete(cache->tdb, string_tdb_data(key_str));
+
+ /* Samba/winbindd never needs this. */
+ netsamlogon_clear_cached_user(info3);
}
bool wcache_invalidate_cache(void)
diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c
index 916e8c07c7..63ce0e8d7f 100644
--- a/source3/winbindd/winbindd_dual.c
+++ b/source3/winbindd/winbindd_dual.c
@@ -1212,6 +1212,10 @@ static bool fork_domain_child(struct winbindd_child *child)
}
}
+ if (primary_domain == NULL) {
+ smb_panic("no primary domain found");
+ }
+
/* Ensure we're not handling an event inherited from
our parent. */
diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index a7911f60aa..d4a2e3ed79 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1595,8 +1595,8 @@ process_result:
goto done;
}
- netsamlogon_cache_store(name_user, info3);
wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3);
+ netsamlogon_cache_store(name_user, info3);
/* save name_to_sid info as early as possible (only if
this is our primary domain so we don't invalidate
@@ -1921,8 +1921,8 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
if (NT_STATUS_IS_OK(result)) {
- netsamlogon_cache_store(name_user, info3);
wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3);
+ netsamlogon_cache_store(name_user, info3);
/* Check if the user is in the right group */