From 299fc6d67c6e755450c3a1e8cf0ba046eb7fa8b7 Mon Sep 17 00:00:00 2001 From: Bian Naimeng Date: Thu, 18 Jun 2015 08:36:52 +0800 Subject: [PATCH] samba: upgrade to 4.1.12 Signed-off-by: Bian Naimeng --- .../bug_221618_precise-64bit-prototype.patch | 20 - ...mention-kerberos-in-smbspool-manpage.patch | 34 - ...9-nss_wins-dont-clobber-daemons-logs.patch | 47 - .../bug_601406_fix-perl-path-in-example.patch | 15 - ..._upstream_7826_drop-using-samba-link.patch | 21 - ...4768_upstream_7826_fix-WHATSNEW-link.patch | 18 - ...ure-disable-core_pattern-cross-check.patch | 20 - .../configure-disable-getaddrinfo-cross.patch | 11 - .../samba-3.6.25/configure-libunwind.patch | 82 - .../samba/samba-3.6.25/documentation.patch | 302 - .../samba/samba-3.6.25/documentation2.patch | 314 - .../dont-build-VFS-examples.patch | 31 - .../samba/samba-3.6.25/fhs-filespaths.patch | 65 - .../samba/samba-3.6.25/installswat.sh.patch | 23 - .../libutil_drop_AI_ADDRCONFIG.patch | 54 - .../only_export_public_symbols.patch | 21 - .../samba/samba-3.6.25/pam-examples.patch | 17 - .../samba-3.6.25/shadow_copy2_backport.patch | 2101 -- .../samba/samba-3.6.25/smbclient-pager.patch | 18 - .../samba/samba-3.6.25/smbtar-bashism.patch | 19 - .../samba-3.6.25/smbtorture-manpage.patch | 94 - .../samba-3.6.25/undefined-symbols.patch | 24 - .../samba/samba-3.6.25/usershare.patch | 38 - .../samba/samba-3.6.25/waf-as-source.patch | 18534 ---------- .../00-fix-typos-in-man-pages.patch | 108 + .../01-fix-force-user-sec-ads.patch | 1448 + .../samba/samba-4.1.12/02-fix-ipv6-join.patch | 266 + .../03-net-ads-kerberos-pac.patch | 962 + .../samba-4.1.12/04-ipv6-workaround.patch | 211 + .../05-fix-gecos-field-with-samlogon.patch | 29894 ++++++++++++++++ .../06-fix-nmbd-systemd-status-update.patch | 97 + ...7-fix-idmap-ad-getgroups-without-gid.patch | 42 + ...ix-idmap-ad-sfu-with-trusted-domains.patch | 44 + .../09-fix-smbclient-echo-cmd-segfault.patch | 35 + ...ve-service-principal-guessing-in-net.patch | 180 + ...rwriting-of-spns-during-net-ads-join.patch | 329 + ...pns-from-AD-during-keytab-generation.patch | 159 + .../samba-4.1.12/13-fix-aes-enctype.patch | 988 + .../samba/samba-4.1.12/14-fix-dnsupdate.patch | 51 + .../15-fix-netbios-name-truncation.patch | 154 + .../16-do-not-check-xsltproc-manpages.patch | 52 + .../17-execute-prog-by-qemu.patch | 22 + ...8-avoid-get-config-by-native-ncurses.patch | 22 + ...md-daemon-is-contained-by-libsystemd.patch | 42 + ...ot-import-target-module-in-configure.patch | 28 + .../samba/samba-basic.inc | 71 - meta-oe/recipes-connectivity/samba/samba.inc | 161 - ...g-linemarkers-in-preprocessor-output.patch | 68 - .../samba/samba/Managing-Samba.txt | 40 - .../samba/samba/cifs.patch | 10 - .../samba/samba/config-h.patch | 12 - .../samba/samba/config-lfs.patch | 47 - .../samba/samba/configure-3.3.0.patch | 85 - .../samba/samba/init.samba | 58 - .../samba/samba/init.winbind | 38 - .../samba/samba/mtab.patch | 11 - .../samba/samba/nmb.service | 12 - .../samba/samba/quota.patch | 11 - .../recipes-connectivity/samba/samba/smb.conf | 266 - .../samba/samba/smb.service | 13 - .../recipes-connectivity/samba/samba/tdb.pc | 11 - .../samba/samba/tdbheaderfix.patch | 14 - .../samba/samba/volatiles.03_samba | 2 - .../samba/samba/winbind.service | 12 - .../samba/samba_3.6.25.bb | 67 - .../samba/samba_4.1.12.bb | 155 + 66 files changed, 35289 insertions(+), 22932 deletions(-) delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_221618_precise-64bit-prototype.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_387266_upstream_4104_mention-kerberos-in-smbspool-manpage.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_598313_upstream_7499-nss_wins-dont-clobber-daemons-logs.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_601406_fix-perl-path-in-example.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_604768_upstream_7826_drop-using-samba-link.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_604768_upstream_7826_fix-WHATSNEW-link.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/configure-disable-core_pattern-cross-check.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/configure-disable-getaddrinfo-cross.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/configure-libunwind.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/documentation.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/documentation2.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/dont-build-VFS-examples.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/fhs-filespaths.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/installswat.sh.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/libutil_drop_AI_ADDRCONFIG.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/only_export_public_symbols.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/pam-examples.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/shadow_copy2_backport.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/smbclient-pager.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/smbtar-bashism.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/smbtorture-manpage.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/undefined-symbols.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/usershare.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-3.6.25/waf-as-source.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/00-fix-typos-in-man-pages.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/01-fix-force-user-sec-ads.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/02-fix-ipv6-join.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/03-net-ads-kerberos-pac.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/04-ipv6-workaround.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/05-fix-gecos-field-with-samlogon.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/06-fix-nmbd-systemd-status-update.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/07-fix-idmap-ad-getgroups-without-gid.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/08-fix-idmap-ad-sfu-with-trusted-domains.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/09-fix-smbclient-echo-cmd-segfault.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/10-improve-service-principal-guessing-in-net.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/11-fix-overwriting-of-spns-during-net-ads-join.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/12-add-precreated-spns-from-AD-during-keytab-generation.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/13-fix-aes-enctype.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/14-fix-dnsupdate.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/15-fix-netbios-name-truncation.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/16-do-not-check-xsltproc-manpages.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/17-execute-prog-by-qemu.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/18-avoid-get-config-by-native-ncurses.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/19-systemd-daemon-is-contained-by-libsystemd.patch create mode 100644 meta-oe/recipes-connectivity/samba/samba-4.1.12/20-do-not-import-target-module-in-configure.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba-basic.inc delete mode 100644 meta-oe/recipes-connectivity/samba/samba.inc delete mode 100644 meta-oe/recipes-connectivity/samba/samba/0001-PIDL-fix-parsing-linemarkers-in-preprocessor-output.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba/Managing-Samba.txt delete mode 100644 meta-oe/recipes-connectivity/samba/samba/cifs.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba/config-h.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba/config-lfs.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba/configure-3.3.0.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba/init.samba delete mode 100644 meta-oe/recipes-connectivity/samba/samba/init.winbind delete mode 100644 meta-oe/recipes-connectivity/samba/samba/mtab.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba/nmb.service delete mode 100644 meta-oe/recipes-connectivity/samba/samba/quota.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba/smb.conf delete mode 100644 meta-oe/recipes-connectivity/samba/samba/smb.service delete mode 100644 meta-oe/recipes-connectivity/samba/samba/tdb.pc delete mode 100644 meta-oe/recipes-connectivity/samba/samba/tdbheaderfix.patch delete mode 100644 meta-oe/recipes-connectivity/samba/samba/volatiles.03_samba delete mode 100644 meta-oe/recipes-connectivity/samba/samba/winbind.service delete mode 100644 meta-oe/recipes-connectivity/samba/samba_3.6.25.bb create mode 100644 meta-oe/recipes-connectivity/samba/samba_4.1.12.bb diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_221618_precise-64bit-prototype.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_221618_precise-64bit-prototype.patch deleted file mode 100644 index 31108f2e..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_221618_precise-64bit-prototype.patch +++ /dev/null @@ -1,20 +0,0 @@ -Description: 64 bit fix for libsmbclient -Author: Christian Perrier -Bug-Debian: http://bugs.debian.org/221618 -Forwarded: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=221618#27 - -Index: samba/source3/include/libsmbclient.h -=================================================================== ---- samba.orig/source3/include/libsmbclient.h -+++ samba/source3/include/libsmbclient.h -@@ -79,6 +79,10 @@ - #include - #include - -+ /* Debian bug #221618 */ -+#define _LARGEFILE64_SOURCE -+#define _FILE_OFFSET_BITS 64 -+ - #define SMBC_BASE_FD 10000 /* smallest file descriptor returned */ - - #define SMBC_WORKGROUP 1 diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_387266_upstream_4104_mention-kerberos-in-smbspool-manpage.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_387266_upstream_4104_mention-kerberos-in-smbspool-manpage.patch deleted file mode 100644 index d9cc633d..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_387266_upstream_4104_mention-kerberos-in-smbspool-manpage.patch +++ /dev/null @@ -1,34 +0,0 @@ -Description: Add mention about some user for user information in smbspool manpage -Author: Christian Perrier -Bug-Debian: http://bugs.debian.org/387266 -Forwarded: yes -Bug: https://bugzilla.samba.org/show_bug.cgi?id=4104 - -Index: samba/docs-xml/manpages-3/smbspool.8.xml -=================================================================== ---- samba.orig/docs-xml/manpages-3/smbspool.8.xml -+++ samba/docs-xml/manpages-3/smbspool.8.xml -@@ -73,7 +73,9 @@ - - - The user argument (argv[2]) contains the -- print user's name and is presently not used by smbspool. -+ print user's name and is presently not used by smbspool -+ except in Kerberos environments to access the user's -+ ticket cache. - - - The title argument (argv[3]) contains the -Index: samba/docs/manpages/smbspool.8 -=================================================================== ---- samba.orig/docs/manpages/smbspool.8 -+++ samba/docs/manpages/smbspool.8 -@@ -114,7 +114,7 @@ - .sp -1 - .IP \(bu 2.3 - .\} --The user argument (argv[2]) contains the print user\*(Aqs name and is presently not used by smbspool\&. -+The user argument (argv[2]) contains the print user\*(Aqs name and is presently not used by smbspool except in Kerberos environments to access the user\'s ticket cache\&. - .RE - .sp - .RS 4 diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_598313_upstream_7499-nss_wins-dont-clobber-daemons-logs.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_598313_upstream_7499-nss_wins-dont-clobber-daemons-logs.patch deleted file mode 100644 index dcd94e42..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_598313_upstream_7499-nss_wins-dont-clobber-daemons-logs.patch +++ /dev/null @@ -1,47 +0,0 @@ -Description: nss_wins stop clobbering other daemon's log -Author: Christian Perrier ,Buchan Milne -Bug-Debian: http://bugs.debian.org/598313 -Forwarded: yes -Bug: https://bugzilla.samba.org/show_bug.cgi?id=7499 - -Index: samba/lib/util/debug.c -=================================================================== ---- samba.orig/lib/util/debug.c -+++ samba/lib/util/debug.c -@@ -474,15 +474,17 @@ - - if (state.logtype == DEBUG_FILE) { - #ifdef WITH_SYSLOG -- const char *p = strrchr_m( prog_name,'/' ); -- if (p) -- prog_name = p + 1; -+ if (prog_name) { -+ const char *p = strrchr_m( prog_name,'/' ); -+ if (p) -+ prog_name = p + 1; - #ifdef LOG_DAEMON -- openlog( prog_name, LOG_PID, SYSLOG_FACILITY ); -+ openlog( prog_name, LOG_PID, SYSLOG_FACILITY ); - #else -- /* for old systems that have no facility codes. */ -- openlog( prog_name, LOG_PID ); -+ /* for old systems that have no facility codes. */ -+ openlog( prog_name, LOG_PID ); - #endif -+ } - #endif - } - } -Index: samba/nsswitch/wins.c -=================================================================== ---- samba.orig/nsswitch/wins.c -+++ samba/nsswitch/wins.c -@@ -52,7 +52,7 @@ - lp_set_cmdline("log level", "0"); - - TimeInit(); -- setup_logging("nss_wins",False); -+ setup_logging(NULL,False); - lp_load(get_dyn_CONFIGFILE(),True,False,False,True); - load_interfaces(); - } diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_601406_fix-perl-path-in-example.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_601406_fix-perl-path-in-example.patch deleted file mode 100644 index ba8b1f42..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_601406_fix-perl-path-in-example.patch +++ /dev/null @@ -1,15 +0,0 @@ -Description: Fix path to perl binary in example file -Author: Christian Perrier -Bug-Debian: http://bugs.debian.org/601406 -Forwarded: not-needed - -Index: samba/examples/misc/wall.perl -=================================================================== ---- samba.orig/examples/misc/wall.perl -+++ samba/examples/misc/wall.perl -@@ -1,4 +1,4 @@ --#!/usr/local/bin/perl -+#!/usr/bin/perl - # - #@(#) smb-wall.pl Description: - #@(#) A perl script which allows you to announce whatever you choose to diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_604768_upstream_7826_drop-using-samba-link.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_604768_upstream_7826_drop-using-samba-link.patch deleted file mode 100644 index 0c54b6b0..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_604768_upstream_7826_drop-using-samba-link.patch +++ /dev/null @@ -1,21 +0,0 @@ -Description: Drop Using Samba link in HTML documentation summary -Author: Christian Perrier -Bug-Debian: http://bugs.debian.org/604768 -Forwarded: yes -Bug: https://bugzilla.samba.org/show_bug.cgi?id=7826 - -Index: samba/docs/htmldocs/index.html -=================================================================== ---- samba.orig/docs/htmldocs/index.html -+++ samba/docs/htmldocs/index.html -@@ -23,10 +23,6 @@ - This book provides example configurations, it documents key aspects of Microsoft Windows networking, provides in-depth insight into the important configuration of Samba-3, and helps to put all of these into a useful framework. - - -- Using Samba, 2nd Edition -- Using Samba, Second Edition is a comprehensive guide to Samba administration. It covers all versions of Samba from 2.0 to 2.2, including selected features from an alpha version of 3.0, as well as the SWAT graphical configuration tool. Updated for Windows 2000, ME, and XP, the book also explores Samba's new role as a primary domain controller and domain member server, its support for the use of Windows NT/2000/XP authentication and filesystem security on the host Unix system, and accessing shared files and printers from Unix clients. -- -- - Man pages - The Samba man pages in HTML. - diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_604768_upstream_7826_fix-WHATSNEW-link.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_604768_upstream_7826_fix-WHATSNEW-link.patch deleted file mode 100644 index c7dd043f..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/bug_604768_upstream_7826_fix-WHATSNEW-link.patch +++ /dev/null @@ -1,18 +0,0 @@ -Description: Fix WHATSNEW.txt link in HTML documentation summary to fit Debian files organization -Author: Christian Perrier -Bug-Debian: http://bugs.debian.org/604768 -Forwarded: not-needed - -Index: samba/docs/htmldocs/index.html -=================================================================== ---- samba.orig/docs/htmldocs/index.html -+++ samba/docs/htmldocs/index.html -@@ -27,7 +27,7 @@ - The Samba man pages in HTML. - - -- WHATSNEW -+ WHATSNEW - Samba Release Notes. - - diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/configure-disable-core_pattern-cross-check.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/configure-disable-core_pattern-cross-check.patch deleted file mode 100644 index 2d961897..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/configure-disable-core_pattern-cross-check.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- samba-3.6.8/source3/configure.orig 2012-10-01 16:28:17.559074996 -0300 -+++ samba-3.6.8/source3/configure 2012-10-01 16:39:07.747700087 -0300 -@@ -16718,7 +16718,7 @@ - ################################################# - # Check to see if core dump directory is defined in linux - # with /proc/sys/kernel/core_pattern -- -+if false; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /proc/sys/kernel/core_pattern" >&5 - $as_echo_n "checking for /proc/sys/kernel/core_pattern... " >&6; } - if ${ac_cv_file__proc_sys_kernel_core_pattern+:} false; then : -@@ -16739,7 +16739,7 @@ - $as_echo "#define HAVE_SYS_KERNEL_PROC_CORE_PATTERN 1" >>confdefs.h - - fi -- -+fi - - ############################# - # check if building with gpfs diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/configure-disable-getaddrinfo-cross.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/configure-disable-getaddrinfo-cross.patch deleted file mode 100644 index 84ecd498..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/configure-disable-getaddrinfo-cross.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- samba-3.6.6/source3/configure.orig 2012-10-01 15:50:15.371574883 -0300 -+++ samba-3.6.6/source3/configure 2012-10-01 15:50:35.563699659 -0300 -@@ -13302,7 +13302,7 @@ - # getaddrinfo is broken on some AIX systems - # see bug 5910, use our replacements if we detect - # a broken system. -- if test "$cross_compiling" = yes; then : -+ if test "$cross_compiling" = foo; then : - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 - $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} - as_fn_error "cannot run test program while cross compiling diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/configure-libunwind.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/configure-libunwind.patch deleted file mode 100644 index 9a2cb00e..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/configure-libunwind.patch +++ /dev/null @@ -1,82 +0,0 @@ -samba: add --enable-libunwind option - -Upstream-Status: Pending - -This let the end user explicitly enable/disable libunwind support. ---- - configure | 28 ++++++++++++++++++++++++++-- - 1 file changed, 26 insertions(+), 2 deletions(-) - -diff -urpN a/source3/configure b/source3/configure ---- a/source3/configure -+++ b/source3/configure -@@ -1007,6 +1007,7 @@ with_included_iniparser - with_static_modules - with_shared_modules - enable_dmalloc -+enable_libunwind - ' - ac_precious_vars='build_alias - host_alias -@@ -1670,6 +1671,7 @@ Optional Features: - --enable-avahi Enable Avahi support (default=auto) - --enable-pthreadpool Enable pthreads pool helper support (default=no) - --enable-dmalloc Enable heap debugging [default=no] -+ --enable-libunwind Enable libunwind support if available (default=no) - - Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] -@@ -16458,7 +16460,7 @@ done - - - # Find a method of generating a stack trace --for ac_header in execinfo.h libexc.h libunwind.h -+for ac_header in execinfo.h libexc.h - do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` - ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -@@ -16684,6 +16686,13 @@ fi - - LIBS="$save_LIBS" - -+# Check whether --enable-libunwind was given. -+if test "${enable_libunwind+set}" = set; then : -+ enableval=$enable_libunwind; -+fi -+ -+if test "x$enable_libunwind" != xno -+then - # Note that all the libunwind symbols in the API are defined to internal - # platform-specific version, so we must include libunwind.h before checking - # any of them. -@@ -16691,6 +16700,21 @@ LIBS="$save_LIBS" - $as_echo_n "checking for libunwind... " >&6; } - save_LIBS=$LIBS - -+# Check for libunwind.h present -+for ac_header in libunwind.h -+do : -+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -+eval as_val=\$$as_ac_Header -+ if test "x$as_val" = x""yes; then : -+ cat >>confdefs.h <<_ACEOF -+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -+_ACEOF -+ -+fi -+ -+done -+ - UNWIND_ARCH="unknown" - if test x"$UNAME_I" != x"unknown"; then - UNWIND_ARCH="$UNAME_I" -@@ -16877,7 +16901,7 @@ fi - rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - fi -- -+fi - - - for ac_func in _dup _dup2 _opendir _readdir _seekdir _telldir _closedir diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/documentation.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/documentation.patch deleted file mode 100644 index 73111fed..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/documentation.patch +++ /dev/null @@ -1,302 +0,0 @@ -Description: Remove documentation parts that do not apply to Debian -Author: Christian Perrier -Forwarded: not-needed - -Index: experimental/docs/manpages/swat.8 -=================================================================== ---- experimental.orig/docs/manpages/swat.8 -+++ experimental/docs/manpages/swat.8 -@@ -120,86 +120,6 @@ - .RS 4 - Print a summary of command line options\&. - .RE --.SH "INSTALLATION" --.PP --Swat is included as binary package with most distributions\&. The package manager in this case takes care of the installation and configuration\&. This section is only for those who have compiled swat from scratch\&. --.PP --After you compile SWAT you need to run --make install --to install the --swat --binary and the various help files and images\&. A default install would put these in: --.sp --.RS 4 --.ie n \{\ --\h'-04'\(bu\h'+03'\c --.\} --.el \{\ --.sp -1 --.IP \(bu 2.3 --.\} --/usr/local/samba/sbin/swat --.RE --.sp --.RS 4 --.ie n \{\ --\h'-04'\(bu\h'+03'\c --.\} --.el \{\ --.sp -1 --.IP \(bu 2.3 --.\} --/usr/local/samba/swat/images/* --.RE --.sp --.RS 4 --.ie n \{\ --\h'-04'\(bu\h'+03'\c --.\} --.el \{\ --.sp -1 --.IP \(bu 2.3 --.\} --/usr/local/samba/swat/help/* --.RE --.sp --.RE --.SS "Inetd Installation" --.PP --You need to edit your --/etc/inetd\&.conf --and --/etc/services --to enable SWAT to be launched via --inetd\&. --.PP --In --/etc/services --you need to add a line like this: --.PP --swat 901/tcp --.PP --Note for NIS/YP and LDAP users \- you may need to rebuild the NIS service maps rather than alter your local --/etc/services --file\&. --.PP --the choice of port number isn\*(Aqt really important except that it should be less than 1024 and not currently used (using a number above 1024 presents an obscure security hole depending on the implementation details of your --inetd --daemon)\&. --.PP --In --/etc/inetd\&.conf --you should add a line like this: --.PP --swat stream tcp nowait\&.400 root /usr/local/samba/sbin/swat swat --.PP --Once you have edited --/etc/services --and --/etc/inetd\&.conf --you need to send a HUP signal to inetd\&. To do this use --kill \-1 PID --where PID is the process ID of the inetd daemon\&. - .SH "LAUNCHING" - .PP - To launch SWAT just run your favorite web browser and point it at "http://localhost:901/"\&. -@@ -217,14 +137,11 @@ - This file must contain a mapping of service name (e\&.g\&., swat) to service port (e\&.g\&., 901) and protocol type (e\&.g\&., tcp)\&. - .RE - .PP --/usr/local/samba/lib/smb\&.conf -+/etc/samba/smb\&.conf - .RS 4 - This is the default location of the - \fBsmb.conf\fR(5) --server configuration file that swat edits\&. Other common places that systems install this file are --/usr/samba/lib/smb\&.conf --and --/etc/smb\&.conf\&. This file describes all the services the server is to make available to clients\&. -+server configuration file that swat edits\&. This file describes all the services the server is to make available to clients\&. - .RE - .SH "WARNINGS" - .PP -Index: experimental/docs/manpages/nmbd.8 -=================================================================== ---- experimental.orig/docs/manpages/nmbd.8 -+++ experimental/docs/manpages/nmbd.8 -@@ -115,10 +115,7 @@ - to answer any name queries\&. Adding a line to this file affects name NetBIOS resolution from this host - \fIONLY\fR\&. - .sp --The default path to this file is compiled into Samba as part of the build process\&. Common defaults are --/usr/local/samba/lib/lmhosts, --/usr/samba/lib/lmhosts --or -+The default path to this file is - /etc/samba/lmhosts\&. See the - \fBlmhosts\fR(5) - man page for details on the contents of this file\&. -@@ -187,14 +184,11 @@ - inetd, this file must contain a mapping of service name (e\&.g\&., netbios\-ssn) to service port (e\&.g\&., 139) and protocol type (e\&.g\&., tcp)\&. - .RE - .PP --/usr/local/samba/lib/smb\&.conf -+/etc/samba/smb\&.conf - .RS 4 - This is the default location of the - \fBsmb.conf\fR(5) --server configuration file\&. Other common places that systems install this file are --/usr/samba/lib/smb\&.conf --and --/etc/samba/smb\&.conf\&. -+server configuration file\&. - .sp - When run as a WINS server (see the - \m[blue]\fBwins support\fR\m[] -@@ -238,10 +232,8 @@ - will accept SIGHUP, which will cause it to dump out its namelists into the file - namelist\&.debug - in the --/usr/local/samba/var/locks --directory (or the --var/locks --directory configured under wherever Samba was configured to install itself)\&. This will also cause -+/var/run/samba -+directory\&. This will also cause - nmbd - to dump out its server database in the - log\&.nmb -Index: experimental/docs/manpages/smbd.8 -=================================================================== ---- experimental.orig/docs/manpages/smbd.8 -+++ experimental/docs/manpages/smbd.8 -@@ -169,14 +169,11 @@ - inetd, this file must contain a mapping of service name (e\&.g\&., netbios\-ssn) to service port (e\&.g\&., 139) and protocol type (e\&.g\&., tcp)\&. - .RE - .PP --/usr/local/samba/lib/smb\&.conf -+/etc/samba/smb\&.conf - .RS 4 - This is the default location of the - \fBsmb.conf\fR(5) --server configuration file\&. Other common places that systems install this file are --/usr/samba/lib/smb\&.conf --and --/etc/samba/smb\&.conf\&. -+server configuration file\&. - .sp - This file describes all the services the server is to make available to clients\&. See - \fBsmb.conf\fR(5) -Index: experimental/docs/manpages/lmhosts.5 -=================================================================== ---- experimental.orig/docs/manpages/lmhosts.5 -+++ experimental/docs/manpages/lmhosts.5 -@@ -96,10 +96,8 @@ - file\&. - .SH "FILES" - .PP --lmhosts is loaded from the configuration directory\&. This is usually --/etc/samba --or --/usr/local/samba/lib\&. -+lmhosts is loaded from the configuration directory\&. This is -+/etc/samba\&. - .SH "VERSION" - .PP - This man page is correct for version 3 of the Samba suite\&. -Index: experimental/docs/manpages/ntlm_auth.1 -=================================================================== ---- experimental.orig/docs/manpages/ntlm_auth.1 -+++ experimental/docs/manpages/ntlm_auth.1 -@@ -43,7 +43,7 @@ - Some of these commands also require access to the directory - winbindd_privileged - in --$LOCKDIR\&. This should be done either by running this command as root or providing group access to the -+/var/run/samba\F[]\&. This should be done either by running this command as root or providing group access to the - winbindd_privileged - directory\&. For security reasons, this directory should not be world\-accessable\&. - .SH "OPTIONS" -@@ -69,7 +69,7 @@ - Requires access to the directory - winbindd_privileged - in --$LOCKDIR\&. The protocol used is described here: -+/var/run/samba\&. The protocol used is described here: - http://devel\&.squid\-cache\&.org/ntlm/squid_helper_protocol\&.html\&. This protocol has been extended to allow the NTLMSSP Negotiate packet to be included as an argument to the - YR - command\&. (Thus avoiding loss of information in the protocol exchange)\&. -@@ -92,7 +92,7 @@ - Requires access to the directory - winbindd_privileged - in --$LOCKDIR\&. -+/var/run/samba\&. - .RE - .PP - gss\-spnego\-client -Index: experimental/docs/manpages/tdbbackup.8 -=================================================================== ---- experimental.orig/docs/manpages/tdbbackup.8 -+++ experimental/docs/manpages/tdbbackup.8 -@@ -77,7 +77,7 @@ - .\} - - secrets\&.tdb --\- usual location is in the /usr/local/samba/private directory, or on some systems in /etc/samba\&. -+\- usual location is in the /var/lib/samba directory\&. - .RE - .sp - .RS 4 -@@ -90,7 +90,7 @@ - .\} - - passdb\&.tdb --\- usual location is in the /usr/local/samba/private directory, or on some systems in /etc/samba\&. -+\- usual location is in the /var/lib/samba directory\&. - .RE - .sp - .RS 4 -@@ -103,7 +103,7 @@ - .\} - - *\&.tdb --located in the /usr/local/samba/var directory or on some systems in the /var/cache or /var/lib/samba directories\&. -+located in the /var/lib/samba and /var/run/samba directories\&. - .RE - .SH "VERSION" - .PP -Index: experimental/docs/manpages/winbindd.8 -=================================================================== ---- experimental.orig/docs/manpages/winbindd.8 -+++ experimental/docs/manpages/winbindd.8 -@@ -539,16 +539,16 @@ - file are owned by root\&. - .RE - .PP --$LOCKDIR/winbindd_privileged/pipe -+/var/run/samba/winbindd_privileged/pipe - .RS 4 - The UNIX pipe over which \*(Aqprivileged\*(Aq clients communicate with the - winbindd - program\&. For security reasons, access to some winbindd functions \- like those needed by the - ntlm_auth --utility \- is restricted\&. By default, only users in the \*(Aqroot\*(Aq group will get this access, however the administrator may change the group permissions on $LOCKDIR/winbindd_privileged to allow programs like \*(Aqsquid\*(Aq to use ntlm_auth\&. Note that the winbind client will only attempt to connect to the winbindd daemon if both the --$LOCKDIR/winbindd_privileged -+utility \- is restricted\&. By default, only users in the \'root\' group will get this access, however the administrator may change the group permissions on /var/run/samba/winbindd_privileged to allow programs like \'squid\' to use ntlm_auth\&. Note that the winbind client will only attempt to connect to the winbindd daemon if both the -+/var/run/samba/winbindd_privileged - directory and --$LOCKDIR/winbindd_privileged/pipe -+/var/run/samba/winbindd_privileged/pipe - file are owned by root\&. - .RE - .PP -@@ -557,15 +557,12 @@ - Implementation of name service switch library\&. - .RE - .PP --$LOCKDIR/winbindd_idmap\&.tdb -+/var/run/samba/winbindd_idmap\&.tdb - .RS 4 --Storage for the Windows NT rid to UNIX user/group id mapping\&. The lock directory is specified when Samba is initially compiled using the --\fI\-\-with\-lockdir\fR --option\&. This directory is by default --/usr/local/samba/var/locks\&. -+Storage for the Windows NT rid to UNIX user/group id mapping\&. - .RE - .PP --$LOCKDIR/winbindd_cache\&.tdb -+/var/run/samba/winbindd_cache\&.tdb - .RS 4 - Storage for cached user and group information\&. - .RE diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/documentation2.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/documentation2.patch deleted file mode 100644 index af8da32d..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/documentation2.patch +++ /dev/null @@ -1,314 +0,0 @@ -Description: Remove documentation parts that do not apply to Debian -Author: Christian Perrier -Bug: https://bugzilla.samba.org/show_bug.cgi?id=8789 -Forwarded: yes - -Index: samba/docs-xml/manpages-3/nmbd.8.xml -=================================================================== ---- samba.orig/docs-xml/manpages-3/nmbd.8.xml -+++ samba/docs-xml/manpages-3/nmbd.8.xml -@@ -266,7 +266,6 @@ - 8, smb.conf - 5, smbclient - 1, testparm -- 1, testprns - 1, and the Internet - RFC's rfc1001.txt, rfc1002.txt. - In addition the CIFS (formerly SMB) specification is available -Index: samba/docs-xml/manpages-3/samba.7.xml -=================================================================== ---- samba.orig/docs-xml/manpages-3/samba.7.xml -+++ samba/docs-xml/manpages-3/samba.7.xml -@@ -76,16 +76,6 @@ - - - -- testprns -- 1 -- The testprns -- utility supports testing printer names defined -- in your printcap file used -- by Samba. -- -- -- -- - smbstatus - 1 - The smbstatus -@@ -125,7 +115,8 @@ - 1 - The smbsh command is - a program that allows you to run a unix shell with -- with an overloaded VFS. -+ with an overloaded VFS. Note that, it is not installed by -+ the current samba package. - - - -Index: samba/docs-xml/manpages-3/smb.conf.5.xml -=================================================================== ---- samba.orig/docs-xml/manpages-3/smb.conf.5.xml -+++ samba/docs-xml/manpages-3/smb.conf.5.xml -@@ -856,7 +856,6 @@ - 8, smbclient - 1, nmblookup - 1, testparm -- 1, testprns - 1. - - -Index: samba/docs-xml/manpages-3/smbd.8.xml -=================================================================== ---- samba.orig/docs-xml/manpages-3/smbd.8.xml -+++ samba/docs-xml/manpages-3/smbd.8.xml -@@ -417,7 +417,6 @@ - 8, smb.conf - 5, smbclient - 1, testparm -- 1, testprns - 1, and the - Internet RFC's rfc1001.txt, rfc1002.txt. - In addition the CIFS (formerly SMB) specification is available -Index: samba/docs-xml/using_samba/appd.xml -=================================================================== ---- samba.orig/docs-xml/using_samba/appd.xml -+++ samba/docs-xml/using_samba/appd.xml -@@ -296,7 +296,7 @@ - - - The smbsh --smbsh program program lets you use a remote Windows share on your Samba server as if the share was a regular Unix directory. When it's run, it provides an extra directory tree under /smb. Subdirectories of /smb are servers, and subdirectories of the servers are their individual disk and printer shares. Commands run by smbsh treat the /smb filesystem as if it were local to Unix. This means that you don't need smbmount in your kernel to mount Windows filesystems the way you mount with NFS filesystems. However, you do need to configure Samba with the --with-smbwrappers option to enable smbsh. -+smbsh program program (not available in this samba package) lets you use a remote Windows share on your Samba server as if the share was a regular Unix directory. When it's run, it provides an extra directory tree under /smb. Subdirectories of /smb are servers, and subdirectories of the servers are their individual disk and printer shares. Commands run by smbsh treat the /smb filesystem as if it were local to Unix. This means that you don't need smbmount in your kernel to mount Windows filesystems the way you mount with NFS filesystems. However, you do need to configure Samba with the --with-smbwrappers option to enable smbsh. - - - -@@ -1320,24 +1320,6 @@ - - - -- -- -- -- --testprns -- -- --Thetestprns program --printersnameschecking testprns program checks a specified printer name against the system printer capabilities (printcap) file. Its command line is: -- -- --testprns printername [printcapname] -- -- --If the printcapname isn't specified, Samba attempts to use one located in the smb.conf file. If one isn't specified there, Samba will try /etc/printcap. If that fails, the program will generate an error. -- -- -- - - - -Index: samba/docs-xml/using_samba/ch01.xml -=================================================================== ---- samba.orig/docs-xml/using_samba/ch01.xml -+++ samba/docs-xml/using_samba/ch01.xml -@@ -1375,12 +1375,6 @@ - - - --testprns --A program that tests whether various printers are recognized by the smbd daemon -- -- -- -- - Each significant release of Samba goes through a significant exposure test before it's announced. In addition, it is quickly updated afterward if problems or unwanted side-effects are found. The latest stable distribution as of this writing is Samba 2.0.5, the long-awaited production version of Samba 2.0. This book focuses on the functionality supported in Samba 2.0, as opposed to the older 1.9.x versions of Samba, which are now obsolete. - - -Index: samba/docs-xml/using_samba/ch07.xml -=================================================================== ---- samba.orig/docs-xml/using_samba/ch07.xml -+++ samba/docs-xml/using_samba/ch07.xml -@@ -306,7 +306,7 @@ - public: true - - --Second, try the command testprns printername. This is a simple program that verifies that the specified printer is available in your printcap file. If your printcap file is not in the usual place, you can specify its full pathname as the second argument to the testprns command: -+Second, try the command testprns printername. Note: This command is not available in this package. This is a simple program that verifies that the specified printer is available in your printcap file. If your printcap file is not in the usual place, you can specify its full pathname as the second argument to the testprns command: - - - # testprns lp /etc/printcap -Index: samba/docs/htmldocs/manpages/nmbd.8.html -=================================================================== ---- samba.orig/docs/htmldocs/manpages/nmbd.8.html -+++ samba/docs/htmldocs/manpages/nmbd.8.html -@@ -131,7 +131,7 @@ - transient problems to be diagnosed, whilst still running - at a normally low log level.

VERSION

This man page is correct for version 3 of - the Samba suite.

SEE ALSO

-- inetd(8), smbd(8), smb.conf(5), smbclient(1), testparm(1), testprns(1), and the Internet -+ inetd(8), smbd(8), smb.conf(5), smbclient(1), testparm(1), and the Internet - RFC's rfc1001.txt, rfc1002.txt. - In addition the CIFS (formerly SMB) specification is available - as a link from the Web page -Index: samba/docs/htmldocs/manpages/samba.7.html -=================================================================== ---- samba.orig/docs/htmldocs/manpages/samba.7.html -+++ samba/docs/htmldocs/manpages/samba.7.html -@@ -17,10 +17,7 @@ - servers (such as Windows NT), and can also be used - to allow a UNIX box to print to a printer attached to - any SMB server (such as a PC running Windows NT).

testparm(1)

The testparm -- utility is a simple syntax checker for Samba's smb.conf(5) configuration file.

testprns(1)

The testprns -- utility supports testing printer names defined -- in your printcap file used -- by Samba.

smbstatus(1)

The smbstatus -+ utility is a simple syntax checker for Samba's smb.conf(5) configuration file.

smbstatus(1)

The smbstatus - tool provides access to information about the - current connections to smbd.

nmblookup(1)

The nmblookup - tools allows NetBIOS name queries to be made -@@ -29,7 +26,8 @@ - password hashes on Samba and Windows NT servers.

smbcacls(1)

The smbcacls command is - a tool to set ACL's on remote CIFS servers.

smbsh(1)

The smbsh command is - a program that allows you to run a unix shell with -- with an overloaded VFS.

smbtree(1)

The smbtree command -+ with an overloaded VFS. Note that, it is not installed by -+ the current samba package.

smbtree(1)

The smbtree command - is a text-based network neighborhood tool.

smbtar(1)

The smbtar can make - backups of data on CIFS/SMB servers.

smbspool(8)

smbspool is a - helper utility for printing on printers connected -Index: samba/docs/htmldocs/manpages/smb.conf.5.html -=================================================================== ---- samba.orig/docs/htmldocs/manpages/smb.conf.5.html -+++ samba/docs/htmldocs/manpages/smb.conf.5.html -@@ -6964,7 +6964,7 @@ - care when designing these sections. In particular, ensure that the permissions on spool directories are - correct. -

VERSION

This man page is correct for version 3 of the Samba suite.

AUTHOR

- The original Samba software and related utilities were created by Andrew Tridgell. Samba is now developed - by the Samba Team as an Open Source project similar to the way the Linux kernel is developed. -

-Index: samba/docs/htmldocs/manpages/smbd.8.html -=================================================================== ---- samba.orig/docs/htmldocs/manpages/smbd.8.html -+++ samba/docs/htmldocs/manpages/smbd.8.html -@@ -147,7 +147,7 @@ - smbd is in a state of waiting for an incoming SMB before - issuing them. It is possible to make the signal handlers safe - by un-blocking the signals before the select call and re-blocking -- them after, however this would affect performance.

SEE ALSO

hosts_access(5), inetd(8), nmbd(8), smb.conf(5), smbclient(1), testparm(1), testprns(1), and the -+ them after, however this would affect performance.

SEE ALSO

hosts_access(5), inetd(8), nmbd(8), smb.conf(5), smbclient(1), testparm(1), and the - Internet RFC's rfc1001.txt, rfc1002.txt. - In addition the CIFS (formerly SMB) specification is available - as a link from the Web page -Index: samba/docs/manpages/nmbd.8 -=================================================================== ---- samba.orig/docs/manpages/nmbd.8 -+++ samba/docs/manpages/nmbd.8 -@@ -252,8 +252,7 @@ - \fBsmbd\fR(8), - \fBsmb.conf\fR(5), - \fBsmbclient\fR(1), --\fBtestparm\fR(1), --\fBtestprns\fR(1), and the Internet RFC\*(Aqs -+\fBtestparm\fR(1), and the Internet RFC\*(Aqs - rfc1001\&.txt, - rfc1002\&.txt\&. In addition the CIFS (formerly SMB) specification is available as a link from the Web page - http://samba\&.org/cifs/\&. -Index: samba/docs/manpages/samba.7 -=================================================================== ---- samba.orig/docs/manpages/samba.7 -+++ samba/docs/manpages/samba.7 -@@ -60,15 +60,6 @@ - configuration file\&. - .RE - .PP --\fBtestprns\fR(1) --.RS 4 --The --testprns --utility supports testing printer names defined in your --printcap --file used by Samba\&. --.RE --.PP - \fBsmbstatus\fR(1) - .RS 4 - The -@@ -102,7 +93,7 @@ - .RS 4 - The - smbsh --command is a program that allows you to run a unix shell with with an overloaded VFS\&. -+command is a program that allows you to run a unix shell with with an overloaded VFS. Note that, it is not installed by the current samba package\&. - .RE - .PP - \fBsmbtree\fR(1) -Index: samba/docs/manpages/smb.conf.5 -=================================================================== ---- samba.orig/docs/manpages/smb.conf.5 -+++ samba/docs/manpages/smb.conf.5 -@@ -11021,8 +11021,7 @@ - \fBnmbd\fR(8), - \fBsmbclient\fR(1), - \fBnmblookup\fR(1), --\fBtestparm\fR(1), --\fBtestprns\fR(1)\&. -+\fBtestparm\fR(1)\&. - .SH "AUTHOR" - .PP - The original Samba software and related utilities were created by Andrew Tridgell\&. Samba is now developed by the Samba Team as an Open Source project similar to the way the Linux kernel is developed\&. -Index: samba/docs/manpages/smbd.8 -=================================================================== ---- samba.orig/docs/manpages/smbd.8 -+++ samba/docs/manpages/smbd.8 -@@ -370,8 +370,7 @@ - \fBnmbd\fR(8), - \fBsmb.conf\fR(5), - \fBsmbclient\fR(1), --\fBtestparm\fR(1), --\fBtestprns\fR(1), and the Internet RFC\*(Aqs -+\fBtestparm\fR(1), and the Internet RFC\*(Aqs - rfc1001\&.txt, - rfc1002\&.txt\&. In addition the CIFS (formerly SMB) specification is available as a link from the Web page - http://samba\&.org/cifs/\&. -Index: samba/examples/tridge/smb.conf -=================================================================== ---- samba.orig/examples/tridge/smb.conf -+++ samba/examples/tridge/smb.conf -@@ -31,14 +31,6 @@ - print ok = yes - print command = xmenu -heading "%s" OK& - --[testprn] -- comment = Test printer -- path = /tmp -- user = susan -- print ok = yes -- print command = cp %s /tmp/smb.%U.prn -- lpq command = cat /tmp/xxyz -- - [amd] - comment = amd area - path = /mount -Index: samba/swat/lang/tr/help/welcome.html -=================================================================== ---- samba.orig/swat/lang/tr/help/welcome.html -+++ samba/swat/lang/tr/help/welcome.html -@@ -40,7 +40,6 @@ -

-
  • Kitaplar -@@ -66,4 +65,4 @@ - - Eğer SWAT'ın bu sürümü ile ilgili konuları tartışmak istiyorsanız, lütfen - samba eposta listesine üye olun. -- -\ No newline at end of file -+ diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/dont-build-VFS-examples.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/dont-build-VFS-examples.patch deleted file mode 100644 index beff7db6..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/dont-build-VFS-examples.patch +++ /dev/null @@ -1,31 +0,0 @@ -Description: Do not build VFS examples -Author: Christian Perrier -Forwarded: not-needed - -Index: samba/source3/Makefile.in -=================================================================== ---- samba.orig/source3/Makefile.in -+++ samba/source3/Makefile.in -@@ -1616,8 +1616,7 @@ - - - everything:: all libtalloc libsmbclient libnetapi debug2html smbfilter talloctort replacetort smbconftort modules torture \ -- $(EVERYTHING_PROGS) \ -- vfs_examples -+ $(EVERYTHING_PROGS) - - .SUFFIXES: - .SUFFIXES: .c .o .lo -@@ -3552,12 +3551,3 @@ - bin/ndrdump4: $(BINARY_PREREQS) - $(MAKE) -f Makefile-smbtorture4 bin/ndrdump4 - --.PHONY: vfs_examples -- --vfs_examples: -- ( \ -- cd ../examples/VFS && \ -- ./configure && \ -- make clean && \ -- make \ -- ) diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/fhs-filespaths.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/fhs-filespaths.patch deleted file mode 100644 index e7c6b999..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/fhs-filespaths.patch +++ /dev/null @@ -1,65 +0,0 @@ -Description: Prepare the sources to better respect FHS - This patch was historically very long but most parts have - been integrated upstream. - . - The last remaining bit is the location of "private files - We historically have them in /var/lib/samba while upstream - has them in /etc/samba - . - We need to provide a migraiton path and go back to the "normal" - file layout -Author: Eloy A. Paris -Bug-Debian: http://bugs.debian.org/49011 -Forwarded: not-needed - - -Index: samba/source3/passdb/pdb_tdb.c -=================================================================== ---- samba.orig/source3/passdb/pdb_tdb.c -+++ samba/source3/passdb/pdb_tdb.c -@@ -1260,7 +1260,7 @@ - /* save the path for later */ - - if (!location) { -- if (asprintf(&tdbfile, "%s/%s", lp_private_dir(), -+ if (asprintf(&tdbfile, "%s/%s", lp_statedir(), - PASSDB_FILE_NAME) < 0) { - return NT_STATUS_NO_MEMORY; - } -Index: samba/source3/passdb/secrets.c -=================================================================== ---- samba.orig/source3/passdb/secrets.c -+++ samba/source3/passdb/secrets.c -@@ -64,7 +64,7 @@ - return True; - - fname = talloc_asprintf(talloc_tos(), "%s/secrets.tdb", -- lp_private_dir()); -+ lp_statedir()); - if (fname == NULL) { - return false; - } -Index: samba/docs/manpages/smb.conf.5 -=================================================================== ---- samba.orig/docs/manpages/smb.conf.5 -+++ samba/docs/manpages/smb.conf.5 -@@ -7167,7 +7167,7 @@ - .\} - tdbsam - \- The TDB based password storage backend\&. Takes a path to the TDB as an optional argument (defaults to passdb\&.tdb in the --\m[blue]\fBprivate dir\fR\m[] -+\m[blue]\fBstate directory\fR\m[] - directory\&. - .RE - .sp -@@ -8038,9 +8038,7 @@ - .PP - .RS 4 - This parameters defines the directory smbd will use for storing such files as --smbpasswd --and --secrets\&.tdb\&. -+smbpasswd\&. secrets\&.tdb is stored in state directory on Debian systems\&. - .sp - Default: - \fI\fIprivate dir\fR\fR\fI = \fR\fI${prefix}/private\fR\fI \fR diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/installswat.sh.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/installswat.sh.patch deleted file mode 100644 index 3f08e493..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/installswat.sh.patch +++ /dev/null @@ -1,23 +0,0 @@ -Description: Do not install the Using Samba book when installing SWAT - Using Samba is packaged in samba-doc, however upstream also - installs it in SWAT install dirs -Author: Christian Perrier -Forwarded: not-needed - -Index: experimental/source3/script/installswat.sh -=================================================================== ---- experimental.orig/source3/script/installswat.sh -+++ experimental/source3/script/installswat.sh -@@ -198,7 +198,11 @@ - - # Install/ remove Using Samba book (but only if it is there) - --if [ "x$BOOKDIR" != "x" -a -f $SRCDIR../docs/htmldocs/using_samba/toc.html ]; then -+# Under Debian we don't actually install the book. The book is part of -+# the samba-doc package, so we just provide a symlink that points to -+# where the book is actually installed. The symlink is created in -+# debian/rules. -+if /bin/false; then - - # Create directories - diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/libutil_drop_AI_ADDRCONFIG.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/libutil_drop_AI_ADDRCONFIG.patch deleted file mode 100644 index d3473ea4..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/libutil_drop_AI_ADDRCONFIG.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 185cd4c79492a7de5988f9407d764cdb3a0e2e10 Mon Sep 17 00:00:00 2001 -From: Simo Sorce -Date: Wed, 11 May 2011 17:50:07 -0400 -Subject: [PATCH] libutil: use AI_ADDRCONFIG only when AI_NUMERIC is not defined - -This flag prevents startup w/o ip addresses assigned to any interface. -If AI_NUMERIC is passed it should be safe to avoid it. - -Signed-off-by: Andreas Schneider ---- - lib/util/util_net.c | 16 +++++++++++----- - 1 files changed, 11 insertions(+), 5 deletions(-) - -Index: samba/lib/util/util_net.c -=================================================================== ---- samba.orig/lib/util/util_net.c -+++ samba/lib/util/util_net.c -@@ -64,10 +64,9 @@ - ppres); - - if (ret) { -- DEBUG(3,("interpret_string_addr_internal: getaddrinfo failed " -- "for name %s [%s]\n", -- str, -- gai_strerror(ret) )); -+ DEBUG(3, ("interpret_string_addr_internal: " -+ "getaddrinfo failed for name %s (flags %d) [%s]\n", -+ str, flags, gai_strerror(ret))); - return false; - } - return true; -@@ -88,6 +87,7 @@ - #if defined(HAVE_IPV6) - char addr[INET6_ADDRSTRLEN]; - unsigned int scope_id = 0; -+ int int_flags; - - if (strchr_m(str, ':')) { - char *p = strchr_m(str, '%'); -@@ -108,7 +108,13 @@ - - zero_sockaddr(pss); - -- if (!interpret_string_addr_internal(&res, str, flags|AI_ADDRCONFIG)) { -+ if (flags & AI_NUMERICHOST) { -+ int_flags = flags; -+ } else { -+ int_flags = flags|AI_ADDRCONFIG; -+ } -+ -+ if (!interpret_string_addr_internal(&res, str, int_flags)) { - return false; - } - if (!res) { diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/only_export_public_symbols.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/only_export_public_symbols.patch deleted file mode 100644 index f4fbd56a..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/only_export_public_symbols.patch +++ /dev/null @@ -1,21 +0,0 @@ -Description: only export public symbols - Force usage of the symbols list when linking shared libraries. Otherwise, - private symbols get exported in libsmbclient and libwbclient. -Forwarded: no -Author: Ivo De Decker -Last-Update: 2012-06-27 - ---- samba-3.6.6.orig/source3/Makefile.in -+++ samba-3.6.6/source3/Makefile.in -@@ -28,8 +28,9 @@ SHLD=@SHLD@ - LIB_PATH_VAR=@LIB_PATH_VAR@ - - ## Dynamic shared libraries build settings --DSO_EXPORTS_CMD=-Wl,--version-script,$(srcdir)/exports/`basename $@ | sed 's:\.@SHLIBEXT@[\.0-9]*$$:.@SYMSEXT@:'` --DSO_EXPORTS=@DSO_EXPORTS@ -+# force using syms file -+DSO_EXPORTS=-Wl,--version-script,$(srcdir)/exports/`basename $@ | sed 's:\.@SHLIBEXT@[\.0-9]*$$:.@SYMSEXT@:'` -+#DSO_EXPORTS=@DSO_EXPORTS@ - SHLD_DSO = $(SHLD) $(LDSHFLAGS) $(DSO_EXPORTS) -o $@ - - # The MODULE_EXPORTS variable contains the platform-specific linker flags diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/pam-examples.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/pam-examples.patch deleted file mode 100644 index 9b36e14e..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/pam-examples.patch +++ /dev/null @@ -1,17 +0,0 @@ -Description: Fix examples directory location in pam_smbpass README -Author: Christian Perrier -Forwarded: not-needed - -Index: experimental/source3/pam_smbpass/README -=================================================================== ---- experimental.orig/source3/pam_smbpass/README -+++ experimental/source3/pam_smbpass/README -@@ -37,7 +37,7 @@ - smbconf= - specify an alternate path to the smb.conf - file. - --See the samples/ directory for example PAM configurations using this -+See the examples/ directory for example PAM configurations using this - module. - - Thanks go to the following people: diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/shadow_copy2_backport.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/shadow_copy2_backport.patch deleted file mode 100644 index dbd10489..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/shadow_copy2_backport.patch +++ /dev/null @@ -1,2101 +0,0 @@ -Description: Backport new shadow_copy2 implementation from master - The shadow_copy2 vfs module in samba 3.6 doesn't work if wide links is - disabled. This problem is fixed by a rewrite in the master branch. - This patch is a backport of this new version to samba 3.6. - It is based on these commits in the upstream samba git: - dc461cade5becec21f8d1f2bb74fcf1a977a5ec2 - 617b63658b02957422359a76fd8b8e4748d228ee -Author: Ivo De Decker -Origin: upstream -Bug: https://bugzilla.samba.org/show_bug.cgi?id=7287 -Forwarded: not-needed -Last-Update: 2012-05-27 - ---- samba-3.6.5.orig/source3/modules/vfs_shadow_copy2.c -+++ samba-3.6.5/source3/modules/vfs_shadow_copy2.c -@@ -1,32 +1,29 @@ --/* -- * implementation of an Shadow Copy module - version 2 -+/* -+ * Third attempt at a shadow copy module - * -- * Copyright (C) Andrew Tridgell 2007 -- * Copyright (C) Ed Plese 2009 -+ * Copyright (C) Andrew Tridgell 2007 (portions taken from shadow_copy2) -+ * Copyright (C) Ed Plese 2009 -+ * Copyright (C) Volker Lendecke 2011 -+ * Copyright (C) Christian Ambach 2011 - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - --#include "includes.h" --#include "smbd/smbd.h" --#include "system/filesys.h" --#include "ntioctl.h" -- - /* - -- This is a 2nd implemetation of a shadow copy module for exposing -+ This is a 3rd implemetation of a shadow copy module for exposing - snapshots to windows clients as shadow copies. This version has the - following features: - -@@ -96,243 +93,169 @@ - The following command would generate a correctly formatted directory name - for use with the default parameters: - date -u +@GMT-%Y.%m.%d-%H.%M.%S -- - */ - --static int vfs_shadow_copy2_debug_level = DBGC_VFS; -- --#undef DBGC_CLASS --#define DBGC_CLASS vfs_shadow_copy2_debug_level -+#include "includes.h" -+#include "system/filesys.h" -+#include "include/ntioctl.h" -+#include "smbd/proto.h" -+#include -+#include "util_tdb.h" - - #define GMT_NAME_LEN 24 /* length of a @GMT- name */ --#define SHADOW_COPY2_GMT_FORMAT "@GMT-%Y.%m.%d-%H.%M.%S" -- --#define SHADOW_COPY2_DEFAULT_SORT NULL --#define SHADOW_COPY2_DEFAULT_FORMAT "@GMT-%Y.%m.%d-%H.%M.%S" --#define SHADOW_COPY2_DEFAULT_LOCALTIME false -+#define GMT_FORMAT "@GMT-%Y.%m.%d-%H.%M.%S" - --/* -- make very sure it is one of our special names -- */ --static inline bool shadow_copy2_match_name(const char *name, const char **gmt_start) -+static bool shadow_copy2_find_slashes(TALLOC_CTX *mem_ctx, const char *str, -+ size_t **poffsets, -+ unsigned *pnum_offsets) - { -- unsigned year, month, day, hr, min, sec; -+ unsigned num_offsets; -+ size_t *offsets; - const char *p; -- if (gmt_start) { -- (*gmt_start) = NULL; -- } -- p = strstr_m(name, "@GMT-"); -- if (p == NULL) return false; -- if (p > name && p[-1] != '/') return False; -- if (sscanf(p, "@GMT-%04u.%02u.%02u-%02u.%02u.%02u", &year, &month, -- &day, &hr, &min, &sec) != 6) { -- return False; -- } -- if (p[24] != 0 && p[24] != '/') { -- return False; -- } -- if (gmt_start) { -- (*gmt_start) = p; -- } -- return True; --} - --static char *shadow_copy2_snapshot_to_gmt(TALLOC_CTX *mem_ctx, -- vfs_handle_struct *handle, const char *name) --{ -- struct tm timestamp; -- time_t timestamp_t; -- char gmt[GMT_NAME_LEN + 1]; -- const char *fmt; -+ num_offsets = 0; - -- fmt = lp_parm_const_string(SNUM(handle->conn), "shadow", -- "format", SHADOW_COPY2_DEFAULT_FORMAT); -+ p = str; -+ while ((p = strchr(p, '/')) != NULL) { -+ num_offsets += 1; -+ p += 1; -+ } - -- ZERO_STRUCT(timestamp); -- if (strptime(name, fmt, ×tamp) == NULL) { -- DEBUG(10, ("shadow_copy2_snapshot_to_gmt: no match %s: %s\n", -- fmt, name)); -- return NULL; -+ offsets = talloc_array(mem_ctx, size_t, num_offsets); -+ if (offsets == NULL) { -+ return false; - } - -- DEBUG(10, ("shadow_copy2_snapshot_to_gmt: match %s: %s\n", fmt, name)); -- if (lp_parm_bool(SNUM(handle->conn), "shadow", "localtime", -- SHADOW_COPY2_DEFAULT_LOCALTIME)) -- { -- timestamp.tm_isdst = -1; -- timestamp_t = mktime(×tamp); -- gmtime_r(×tamp_t, ×tamp); -+ p = str; -+ num_offsets = 0; -+ while ((p = strchr(p, '/')) != NULL) { -+ offsets[num_offsets] = p-str; -+ num_offsets += 1; -+ p += 1; - } -- strftime(gmt, sizeof(gmt), SHADOW_COPY2_GMT_FORMAT, ×tamp); - -- return talloc_strdup(mem_ctx, gmt); -+ *poffsets = offsets; -+ *pnum_offsets = num_offsets; -+ return true; - } - --/* -- shadow copy paths can also come into the server in this form: -- -- /foo/bar/@GMT-XXXXX/some/file -- -- This function normalises the filename to be of the form: -- -- @GMT-XXXX/foo/bar/some/file -- */ --static const char *shadow_copy2_normalise_path(TALLOC_CTX *mem_ctx, const char *path, const char *gmt_start) -+static char *shadow_copy2_insert_string(TALLOC_CTX *mem_ctx, -+ struct vfs_handle_struct *handle, -+ time_t snapshot) - { -- char *pcopy; -- char buf[GMT_NAME_LEN]; -- size_t prefix_len; -+ struct tm snap_tm; -+ fstring gmt; -+ size_t gmt_len; - -- if (path == gmt_start) { -- return path; -+ if (localtime_r(&snapshot, &snap_tm) == 0) { -+ DEBUG(10, ("gmtime_r failed\n")); -+ return NULL; - } -- -- prefix_len = gmt_start - path - 1; -- -- DEBUG(10, ("path=%s, gmt_start=%s, prefix_len=%d\n", path, gmt_start, -- (int)prefix_len)); -- -- /* -- * We've got a/b/c/@GMT-YYYY.MM.DD-HH.MM.SS/d/e. convert to -- * @GMT-YYYY.MM.DD-HH.MM.SS/a/b/c/d/e before further -- * processing. As many VFS calls provide a const char *, -- * unfortunately we have to make a copy. -- */ -- -- pcopy = talloc_strdup(talloc_tos(), path); -- if (pcopy == NULL) { -+ gmt_len = strftime(gmt, sizeof(gmt), -+ lp_parm_const_string(SNUM(handle->conn), "shadow", -+ "format", GMT_FORMAT), -+ &snap_tm); -+ if (gmt_len == 0) { -+ DEBUG(10, ("strftime failed\n")); - return NULL; - } -- -- gmt_start = pcopy + prefix_len; -- -- /* -- * Copy away "@GMT-YYYY.MM.DD-HH.MM.SS" -- */ -- memcpy(buf, gmt_start+1, GMT_NAME_LEN); -- -- /* -- * Make space for it including a trailing / -- */ -- memmove(pcopy + GMT_NAME_LEN + 1, pcopy, prefix_len); -- -- /* -- * Move in "@GMT-YYYY.MM.DD-HH.MM.SS/" at the beginning again -- */ -- memcpy(pcopy, buf, GMT_NAME_LEN); -- pcopy[GMT_NAME_LEN] = '/'; -- -- DEBUG(10, ("shadow_copy2_normalise_path: %s -> %s\n", path, pcopy)); -- -- return pcopy; -+ return talloc_asprintf(talloc_tos(), "/%s/%s", -+ lp_parm_const_string( -+ SNUM(handle->conn), "shadow", "snapdir", -+ ".snapshots"), -+ gmt); - } - --/* -- convert a name to the shadow directory -- */ -+static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx, -+ struct vfs_handle_struct *handle, -+ const char *name, -+ time_t *ptimestamp, -+ char **pstripped) -+{ -+ struct tm tm; -+ time_t timestamp; -+ const char *p; -+ char *q; -+ char *stripped; -+ size_t rest_len, dst_len; - --#define _SHADOW2_NEXT(op, args, rtype, eret, extra) do { \ -- const char *name = fname; \ -- const char *gmt_start; \ -- if (shadow_copy2_match_name(fname, &gmt_start)) { \ -- char *name2; \ -- rtype ret; \ -- name2 = convert_shadow2_name(handle, fname, gmt_start); \ -- if (name2 == NULL) { \ -- errno = EINVAL; \ -- return eret; \ -- } \ -- name = name2; \ -- ret = SMB_VFS_NEXT_ ## op args; \ -- talloc_free(name2); \ -- if (ret != eret) extra; \ -- return ret; \ -- } else { \ -- return SMB_VFS_NEXT_ ## op args; \ -- } \ --} while (0) -- --#define _SHADOW2_NEXT_SMB_FNAME(op, args, rtype, eret, extra) do { \ -- const char *gmt_start; \ -- if (shadow_copy2_match_name(smb_fname->base_name, &gmt_start)) { \ -- char *name2; \ -- char *smb_base_name_tmp = NULL; \ -- rtype ret; \ -- name2 = convert_shadow2_name(handle, smb_fname->base_name, gmt_start); \ -- if (name2 == NULL) { \ -- errno = EINVAL; \ -- return eret; \ -- } \ -- smb_base_name_tmp = smb_fname->base_name; \ -- smb_fname->base_name = name2; \ -- ret = SMB_VFS_NEXT_ ## op args; \ -- smb_fname->base_name = smb_base_name_tmp; \ -- talloc_free(name2); \ -- if (ret != eret) extra; \ -- return ret; \ -- } else { \ -- return SMB_VFS_NEXT_ ## op args; \ -- } \ --} while (0) -+ p = strstr_m(name, "@GMT-"); -+ if (p == NULL) { -+ goto no_snapshot; -+ } -+ if ((p > name) && (p[-1] != '/')) { -+ goto no_snapshot; -+ } -+ q = strptime(p, GMT_FORMAT, &tm); -+ if (q == NULL) { -+ goto no_snapshot; -+ } -+ tm.tm_isdst = -1; -+ timestamp = mktime(&tm); -+ if (timestamp == (time_t)-1) { -+ goto no_snapshot; -+ } -+ if ((p == name) && (q[0] == '\0')) { -+ if (pstripped != NULL) { -+ stripped = talloc_strdup(mem_ctx, ""); -+ if (stripped == NULL) { -+ return false; -+ } -+ *pstripped = stripped; -+ } -+ *ptimestamp = timestamp; -+ return true; -+ } -+ if (q[0] != '/') { -+ goto no_snapshot; -+ } -+ q += 1; - --/* -- convert a name to the shadow directory: NTSTATUS-specific handling -- */ -+ rest_len = strlen(q); -+ dst_len = (p-name) + rest_len; -+ -+ if (lp_parm_bool(SNUM(handle->conn), "shadow", "snapdirseverywhere", -+ false)) { -+ char *insert; -+ bool have_insert; -+ insert = shadow_copy2_insert_string(talloc_tos(), handle, -+ timestamp); -+ if (insert == NULL) { -+ errno = ENOMEM; -+ return false; -+ } - --#define _SHADOW2_NTSTATUS_NEXT(op, args, eret, extra) do { \ -- const char *name = fname; \ -- const char *gmt_start; \ -- if (shadow_copy2_match_name(fname, &gmt_start)) { \ -- char *name2; \ -- NTSTATUS ret; \ -- name2 = convert_shadow2_name(handle, fname, gmt_start); \ -- if (name2 == NULL) { \ -- errno = EINVAL; \ -- return eret; \ -- } \ -- name = name2; \ -- ret = SMB_VFS_NEXT_ ## op args; \ -- talloc_free(name2); \ -- if (!NT_STATUS_EQUAL(ret, eret)) extra; \ -- return ret; \ -- } else { \ -- return SMB_VFS_NEXT_ ## op args; \ -- } \ --} while (0) -- --#define SHADOW2_NTSTATUS_NEXT(op, args, eret) _SHADOW2_NTSTATUS_NEXT(op, args, eret, ) -- --#define SHADOW2_NEXT(op, args, rtype, eret) _SHADOW2_NEXT(op, args, rtype, eret, ) -- --#define SHADOW2_NEXT_SMB_FNAME(op, args, rtype, eret) _SHADOW2_NEXT_SMB_FNAME(op, args, rtype, eret, ) -- --#define SHADOW2_NEXT2(op, args) do { \ -- const char *gmt_start1, *gmt_start2; \ -- if (shadow_copy2_match_name(oldname, &gmt_start1) || \ -- shadow_copy2_match_name(newname, &gmt_start2)) { \ -- errno = EROFS; \ -- return -1; \ -- } else { \ -- return SMB_VFS_NEXT_ ## op args; \ -- } \ --} while (0) -- --#define SHADOW2_NEXT2_SMB_FNAME(op, args) do { \ -- const char *gmt_start1, *gmt_start2; \ -- if (shadow_copy2_match_name(smb_fname_src->base_name, &gmt_start1) || \ -- shadow_copy2_match_name(smb_fname_dst->base_name, &gmt_start2)) { \ -- errno = EROFS; \ -- return -1; \ -- } else { \ -- return SMB_VFS_NEXT_ ## op args; \ -- } \ --} while (0) -+ have_insert = (strstr(name, insert+1) != NULL); -+ TALLOC_FREE(insert); -+ if (have_insert) { -+ goto no_snapshot; -+ } -+ } - -+ if (pstripped != NULL) { -+ stripped = talloc_array(mem_ctx, char, dst_len+1); -+ if (stripped == NULL) { -+ errno = ENOMEM; -+ return false; -+ } -+ if (p > name) { -+ memcpy(stripped, name, p-name); -+ } -+ if (rest_len > 0) { -+ memcpy(stripped + (p-name), q, rest_len); -+ } -+ stripped[dst_len] = '\0'; -+ *pstripped = stripped; -+ } -+ *ptimestamp = timestamp; -+ return true; -+no_snapshot: -+ *ptimestamp = 0; -+ return true; -+} - --/* -- find the mount point of a filesystem -- */ --static char *find_mount_point(TALLOC_CTX *mem_ctx, vfs_handle_struct *handle) -+static char *shadow_copy2_find_mount_point(TALLOC_CTX *mem_ctx, -+ vfs_handle_struct *handle) - { - char *path = talloc_strdup(mem_ctx, handle->conn->connectpath); - dev_t dev; -@@ -358,164 +281,152 @@ static char *find_mount_point(TALLOC_CTX - } - } - -- return path; -+ return path; - } - --/* -- work out the location of the snapshot for this share -- */ --static const char *shadow_copy2_find_snapdir(TALLOC_CTX *mem_ctx, vfs_handle_struct *handle) --{ -- const char *snapdir; -- char *mount_point; -- const char *ret; -- -- snapdir = lp_parm_const_string(SNUM(handle->conn), "shadow", "snapdir", NULL); -- if (snapdir == NULL) { -- return NULL; -- } -- /* if its an absolute path, we're done */ -- if (*snapdir == '/') { -- return snapdir; -+static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx, -+ struct vfs_handle_struct *handle, -+ const char *name, time_t timestamp) -+{ -+ struct smb_filename converted_fname; -+ char *result = NULL; -+ size_t *slashes = NULL; -+ unsigned num_slashes; -+ char *path = NULL; -+ size_t pathlen; -+ char *insert = NULL; -+ char *converted = NULL; -+ size_t insertlen; -+ int i, saved_errno; -+ size_t min_offset; -+ -+ path = talloc_asprintf(mem_ctx, "%s/%s", handle->conn->connectpath, -+ name); -+ if (path == NULL) { -+ errno = ENOMEM; -+ goto fail; -+ } -+ pathlen = talloc_get_size(path)-1; -+ -+ DEBUG(10, ("converting %s\n", path)); -+ -+ if (!shadow_copy2_find_slashes(talloc_tos(), path, -+ &slashes, &num_slashes)) { -+ goto fail; -+ } -+ insert = shadow_copy2_insert_string(talloc_tos(), handle, timestamp); -+ if (insert == NULL) { -+ goto fail; -+ } -+ insertlen = talloc_get_size(insert)-1; -+ converted = talloc_array(mem_ctx, char, pathlen + insertlen + 1); -+ if (converted == NULL) { -+ goto fail; -+ } -+ -+ if (path[pathlen-1] != '/') { -+ /* -+ * Append a fake slash to find the snapshot root -+ */ -+ size_t *tmp; -+ tmp = talloc_realloc(talloc_tos(), slashes, -+ size_t, num_slashes+1); -+ if (tmp == NULL) { -+ goto fail; -+ } -+ slashes = tmp; -+ slashes[num_slashes] = pathlen; -+ num_slashes += 1; - } - -- /* other its relative to the filesystem mount point */ -- mount_point = find_mount_point(mem_ctx, handle); -- if (mount_point == NULL) { -- return NULL; -- } -+ min_offset = 0; - -- ret = talloc_asprintf(mem_ctx, "%s/%s", mount_point, snapdir); -- talloc_free(mount_point); -- return ret; --} -- --/* -- work out the location of the base directory for snapshots of this share -- */ --static const char *shadow_copy2_find_basedir(TALLOC_CTX *mem_ctx, vfs_handle_struct *handle) --{ -- const char *basedir = lp_parm_const_string(SNUM(handle->conn), "shadow", "basedir", NULL); -+ if (!lp_parm_bool(SNUM(handle->conn), "shadow", "crossmountpoints", -+ false)) { -+ char *mount_point; - -- /* other its the filesystem mount point */ -- if (basedir == NULL) { -- basedir = find_mount_point(mem_ctx, handle); -+ mount_point = shadow_copy2_find_mount_point(talloc_tos(), -+ handle); -+ if (mount_point == NULL) { -+ goto fail; -+ } -+ min_offset = strlen(mount_point); -+ TALLOC_FREE(mount_point); - } - -- return basedir; --} -+ memcpy(converted, path, pathlen+1); -+ converted[pathlen+insertlen] = '\0'; - --/* -- convert a filename from a share relative path, to a path in the -- snapshot directory -- */ --static char *convert_shadow2_name(vfs_handle_struct *handle, const char *fname, const char *gmt_path) --{ -- TALLOC_CTX *tmp_ctx = talloc_new(handle->data); -- const char *snapdir, *relpath, *baseoffset, *basedir; -- size_t baselen; -- char *ret, *prefix; -+ ZERO_STRUCT(converted_fname); -+ converted_fname.base_name = converted; - -- struct tm timestamp; -- time_t timestamp_t; -- char snapshot[MAXPATHLEN]; -- const char *fmt; -+ for (i = num_slashes-1; i>=0; i--) { -+ int ret; -+ size_t offset; - -- fmt = lp_parm_const_string(SNUM(handle->conn), "shadow", -- "format", SHADOW_COPY2_DEFAULT_FORMAT); -+ offset = slashes[i]; - -- snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle); -- if (snapdir == NULL) { -- DEBUG(2,("no snapdir found for share at %s\n", handle->conn->connectpath)); -- talloc_free(tmp_ctx); -- return NULL; -- } -- -- basedir = shadow_copy2_find_basedir(tmp_ctx, handle); -- if (basedir == NULL) { -- DEBUG(2,("no basedir found for share at %s\n", handle->conn->connectpath)); -- talloc_free(tmp_ctx); -- return NULL; -- } -- -- prefix = talloc_asprintf(tmp_ctx, "%s/@GMT-", snapdir); -- if (strncmp(fname, prefix, (talloc_get_size(prefix)-1)) == 0) { -- /* this looks like as we have already normalized it, leave it untouched*/ -- talloc_free(tmp_ctx); -- return talloc_strdup(handle->data, fname); -- } -- -- if (strncmp(fname, "@GMT-", 5) != 0) { -- fname = shadow_copy2_normalise_path(tmp_ctx, fname, gmt_path); -- if (fname == NULL) { -- talloc_free(tmp_ctx); -- return NULL; -+ if (offset < min_offset) { -+ errno = ENOENT; -+ goto fail; - } -- } - -- ZERO_STRUCT(timestamp); -- relpath = strptime(fname, SHADOW_COPY2_GMT_FORMAT, ×tamp); -- if (relpath == NULL) { -- talloc_free(tmp_ctx); -- return NULL; -- } -+ memcpy(converted+offset, insert, insertlen); - -- /* relpath is the remaining portion of the path after the @GMT-xxx */ -- -- if (lp_parm_bool(SNUM(handle->conn), "shadow", "localtime", -- SHADOW_COPY2_DEFAULT_LOCALTIME)) -- { -- timestamp_t = timegm(×tamp); -- localtime_r(×tamp_t, ×tamp); -+ offset += insertlen; -+ memcpy(converted+offset, path + slashes[i], -+ pathlen - slashes[i]); -+ -+ ret = SMB_VFS_NEXT_LSTAT(handle, &converted_fname); -+ -+ DEBUG(10, ("Trying %s: %d (%s)\n", converted, -+ ret, ret == 0 ? "ok" : strerror(errno))); -+ if (ret == 0) { -+ /* success */ -+ break; -+ } -+ if (errno == ENOTDIR) { -+ /* -+ * This is a valid condition: We appended the -+ * .snaphots/@GMT.. to a file name. Just try -+ * with the upper levels. -+ */ -+ continue; -+ } -+ if (errno != ENOENT) { -+ /* Other problem than "not found" */ -+ goto fail; -+ } - } - -- strftime(snapshot, MAXPATHLEN, fmt, ×tamp); -- -- baselen = strlen(basedir); -- baseoffset = handle->conn->connectpath + baselen; -- -- /* some sanity checks */ -- if (strncmp(basedir, handle->conn->connectpath, baselen) != 0 || -- (handle->conn->connectpath[baselen] != 0 && handle->conn->connectpath[baselen] != '/')) { -- DEBUG(0,("convert_shadow2_name: basedir %s is not a parent of %s\n", -- basedir, handle->conn->connectpath)); -- talloc_free(tmp_ctx); -- return NULL; -+ if (i >= 0) { -+ /* -+ * Found something -+ */ -+ DEBUG(10, ("Found %s\n", converted)); -+ result = converted; -+ converted = NULL; -+ } else { -+ errno = ENOENT; - } -- -- if (*relpath == '/') relpath++; -- if (*baseoffset == '/') baseoffset++; -- -- ret = talloc_asprintf(handle->data, "%s/%s/%s/%s", -- snapdir, -- snapshot, -- baseoffset, -- relpath); -- DEBUG(6,("convert_shadow2_name: '%s' -> '%s'\n", fname, ret)); -- talloc_free(tmp_ctx); -- return ret; --} -- -- --/* -- simple string hash -- */ --static uint32 string_hash(const char *s) --{ -- uint32 n = 0; -- while (*s) { -- n = ((n << 5) + n) ^ (uint32)(*s++); -- } -- return n; -+fail: -+ saved_errno = errno; -+ TALLOC_FREE(converted); -+ TALLOC_FREE(insert); -+ TALLOC_FREE(slashes); -+ TALLOC_FREE(path); -+ errno = saved_errno; -+ return result; - } - - /* - modify a sbuf return to ensure that inodes in the shadow directory - are different from those in the main directory - */ --static void convert_sbuf(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf) -+static void convert_sbuf(vfs_handle_struct *handle, const char *fname, -+ SMB_STRUCT_STAT *sbuf) - { -- if (lp_parm_bool(SNUM(handle->conn), "shadow", "fixinodes", False)) { -+ if (lp_parm_bool(SNUM(handle->conn), "shadow", "fixinodes", False)) { - /* some snapshot systems, like GPFS, return the name - device:inode for the snapshot files as the current - files. That breaks the 'restore' button in the shadow copy -@@ -526,7 +437,10 @@ static void convert_sbuf(vfs_handle_stru - number collision, but I can't see a better approach - without significant VFS changes - */ -- uint32_t shash = string_hash(fname) & 0xFF000000; -+ uint32_t shash; -+ TDB_DATA data = string_tdb_data(fname); -+ -+ shash = tdb_jenkins_hash(&data) & 0xFF000000; - if (shash == 0) { - shash = 1; - } -@@ -534,303 +448,594 @@ static void convert_sbuf(vfs_handle_stru - } - } - -+static SMB_STRUCT_DIR *shadow_copy2_opendir(vfs_handle_struct *handle, -+ const char *fname, -+ const char *mask, -+ uint32 attr) -+{ -+ time_t timestamp; -+ char *stripped; -+ SMB_STRUCT_DIR *ret; -+ int saved_errno; -+ char *conv; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return NULL; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return NULL; -+ } -+ ret = SMB_VFS_NEXT_OPENDIR(handle, conv, mask, attr); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; -+} -+ - static int shadow_copy2_rename(vfs_handle_struct *handle, - const struct smb_filename *smb_fname_src, - const struct smb_filename *smb_fname_dst) - { -- if (shadow_copy2_match_name(smb_fname_src->base_name, NULL)) { -+ time_t timestamp_src, timestamp_dst; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, -+ smb_fname_src->base_name, -+ ×tamp_src, NULL)) { -+ return -1; -+ } -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, -+ smb_fname_dst->base_name, -+ ×tamp_dst, NULL)) { -+ return -1; -+ } -+ if (timestamp_src != 0) { - errno = EXDEV; - return -1; - } -- SHADOW2_NEXT2_SMB_FNAME(RENAME, -- (handle, smb_fname_src, smb_fname_dst)); -+ if (timestamp_dst != 0) { -+ errno = EROFS; -+ return -1; -+ } -+ return SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst); - } - - static int shadow_copy2_symlink(vfs_handle_struct *handle, - const char *oldname, const char *newname) - { -- SHADOW2_NEXT2(SYMLINK, (handle, oldname, newname)); --} -+ time_t timestamp_old, timestamp_new; - --static int shadow_copy2_link(vfs_handle_struct *handle, -- const char *oldname, const char *newname) --{ -- SHADOW2_NEXT2(LINK, (handle, oldname, newname)); -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, oldname, -+ ×tamp_old, NULL)) { -+ return -1; -+ } -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, newname, -+ ×tamp_new, NULL)) { -+ return -1; -+ } -+ if ((timestamp_old != 0) || (timestamp_new != 0)) { -+ errno = EROFS; -+ return -1; -+ } -+ return SMB_VFS_NEXT_SYMLINK(handle, oldname, newname); - } - --static int shadow_copy2_open(vfs_handle_struct *handle, -- struct smb_filename *smb_fname, files_struct *fsp, -- int flags, mode_t mode) -+static int shadow_copy2_link(vfs_handle_struct *handle, -+ const char *oldname, const char *newname) - { -- SHADOW2_NEXT_SMB_FNAME(OPEN, -- (handle, smb_fname, fsp, flags, mode), -- int, -1); --} -+ time_t timestamp_old, timestamp_new; - --static SMB_STRUCT_DIR *shadow_copy2_opendir(vfs_handle_struct *handle, -- const char *fname, const char *mask, uint32 attr) --{ -- SHADOW2_NEXT(OPENDIR, (handle, name, mask, attr), SMB_STRUCT_DIR *, NULL); -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, oldname, -+ ×tamp_old, NULL)) { -+ return -1; -+ } -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, newname, -+ ×tamp_new, NULL)) { -+ return -1; -+ } -+ if ((timestamp_old != 0) || (timestamp_new != 0)) { -+ errno = EROFS; -+ return -1; -+ } -+ return SMB_VFS_NEXT_LINK(handle, oldname, newname); - } - - static int shadow_copy2_stat(vfs_handle_struct *handle, - struct smb_filename *smb_fname) - { -- _SHADOW2_NEXT_SMB_FNAME(STAT, (handle, smb_fname), int, -1, -- convert_sbuf(handle, smb_fname->base_name, -- &smb_fname->st)); -+ time_t timestamp; -+ char *stripped, *tmp; -+ int ret, saved_errno; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, -+ smb_fname->base_name, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_STAT(handle, smb_fname); -+ } -+ -+ tmp = smb_fname->base_name; -+ smb_fname->base_name = shadow_copy2_convert( -+ talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ -+ if (smb_fname->base_name == NULL) { -+ smb_fname->base_name = tmp; -+ return -1; -+ } -+ -+ ret = SMB_VFS_NEXT_STAT(handle, smb_fname); -+ saved_errno = errno; -+ -+ TALLOC_FREE(smb_fname->base_name); -+ smb_fname->base_name = tmp; -+ -+ if (ret == 0) { -+ convert_sbuf(handle, smb_fname->base_name, &smb_fname->st); -+ } -+ errno = saved_errno; -+ return ret; - } - - static int shadow_copy2_lstat(vfs_handle_struct *handle, - struct smb_filename *smb_fname) - { -- _SHADOW2_NEXT_SMB_FNAME(LSTAT, (handle, smb_fname), int, -1, -- convert_sbuf(handle, smb_fname->base_name, -- &smb_fname->st)); -+ time_t timestamp; -+ char *stripped, *tmp; -+ int ret, saved_errno; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, -+ smb_fname->base_name, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_LSTAT(handle, smb_fname); -+ } -+ -+ tmp = smb_fname->base_name; -+ smb_fname->base_name = shadow_copy2_convert( -+ talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ -+ if (smb_fname->base_name == NULL) { -+ smb_fname->base_name = tmp; -+ return -1; -+ } -+ -+ ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname); -+ saved_errno = errno; -+ -+ TALLOC_FREE(smb_fname->base_name); -+ smb_fname->base_name = tmp; -+ -+ if (ret == 0) { -+ convert_sbuf(handle, smb_fname->base_name, &smb_fname->st); -+ } -+ errno = saved_errno; -+ return ret; - } - --static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf) -+static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp, -+ SMB_STRUCT_STAT *sbuf) - { -- int ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); -- if (ret == 0 && shadow_copy2_match_name(fsp->fsp_name->base_name, NULL)) { -+ time_t timestamp; -+ int ret; -+ -+ ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); -+ if (ret == -1) { -+ return ret; -+ } -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, -+ fsp->fsp_name->base_name, -+ ×tamp, NULL)) { -+ return 0; -+ } -+ if (timestamp != 0) { - convert_sbuf(handle, fsp->fsp_name->base_name, sbuf); - } -+ return 0; -+} -+ -+static int shadow_copy2_open(vfs_handle_struct *handle, -+ struct smb_filename *smb_fname, files_struct *fsp, -+ int flags, mode_t mode) -+{ -+ time_t timestamp; -+ char *stripped, *tmp; -+ int ret, saved_errno; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, -+ smb_fname->base_name, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); -+ } -+ -+ tmp = smb_fname->base_name; -+ smb_fname->base_name = shadow_copy2_convert( -+ talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ -+ if (smb_fname->base_name == NULL) { -+ smb_fname->base_name = tmp; -+ return -1; -+ } -+ -+ ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); -+ saved_errno = errno; -+ -+ TALLOC_FREE(smb_fname->base_name); -+ smb_fname->base_name = tmp; -+ -+ errno = saved_errno; - return ret; - } - - static int shadow_copy2_unlink(vfs_handle_struct *handle, -- const struct smb_filename *smb_fname_in) -+ const struct smb_filename *smb_fname) - { -- struct smb_filename *smb_fname = NULL; -+ time_t timestamp; -+ char *stripped; -+ int ret, saved_errno; -+ struct smb_filename *conv; - NTSTATUS status; - -- status = copy_smb_filename(talloc_tos(), smb_fname_in, &smb_fname); -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, -+ smb_fname->base_name, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_UNLINK(handle, smb_fname); -+ } -+ status = copy_smb_filename(talloc_tos(), smb_fname, &conv); - if (!NT_STATUS_IS_OK(status)) { -- errno = map_errno_from_nt_status(status); -+ errno = ENOMEM; - return -1; - } -- -- SHADOW2_NEXT_SMB_FNAME(UNLINK, (handle, smb_fname), int, -1); -+ conv->base_name = shadow_copy2_convert( -+ conv, handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv->base_name == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_UNLINK(handle, conv); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; - } - --static int shadow_copy2_chmod(vfs_handle_struct *handle, -- const char *fname, mode_t mode) -+static int shadow_copy2_chmod(vfs_handle_struct *handle, const char *fname, -+ mode_t mode) - { -- SHADOW2_NEXT(CHMOD, (handle, name, mode), int, -1); -+ time_t timestamp; -+ char *stripped; -+ int ret, saved_errno; -+ char *conv; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_CHMOD(handle, fname, mode); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_CHMOD(handle, conv, mode); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; - } - --static int shadow_copy2_chown(vfs_handle_struct *handle, -- const char *fname, uid_t uid, gid_t gid) -+static int shadow_copy2_chown(vfs_handle_struct *handle, const char *fname, -+ uid_t uid, gid_t gid) - { -- SHADOW2_NEXT(CHOWN, (handle, name, uid, gid), int, -1); -+ time_t timestamp; -+ char *stripped; -+ int ret, saved_errno; -+ char *conv; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_CHOWN(handle, fname, uid, gid); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_CHOWN(handle, conv, uid, gid); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; - } - - static int shadow_copy2_chdir(vfs_handle_struct *handle, -- const char *fname) -+ const char *fname) - { -- SHADOW2_NEXT(CHDIR, (handle, name), int, -1); -+ time_t timestamp; -+ char *stripped; -+ int ret, saved_errno; -+ char *conv; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_CHDIR(handle, fname); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_CHDIR(handle, conv); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; - } - - static int shadow_copy2_ntimes(vfs_handle_struct *handle, -- const struct smb_filename *smb_fname_in, -+ const struct smb_filename *smb_fname, - struct smb_file_time *ft) - { -- struct smb_filename *smb_fname = NULL; -+ time_t timestamp; -+ char *stripped; -+ int ret, saved_errno; -+ struct smb_filename *conv; - NTSTATUS status; - -- status = copy_smb_filename(talloc_tos(), smb_fname_in, &smb_fname); -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, -+ smb_fname->base_name, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft); -+ } -+ status = copy_smb_filename(talloc_tos(), smb_fname, &conv); - if (!NT_STATUS_IS_OK(status)) { -- errno = map_errno_from_nt_status(status); -+ errno = ENOMEM; - return -1; - } -- -- SHADOW2_NEXT_SMB_FNAME(NTIMES, (handle, smb_fname, ft), int, -1); -+ conv->base_name = shadow_copy2_convert( -+ conv, handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv->base_name == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_NTIMES(handle, conv, ft); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; - } - - static int shadow_copy2_readlink(vfs_handle_struct *handle, - const char *fname, char *buf, size_t bufsiz) - { -- SHADOW2_NEXT(READLINK, (handle, name, buf, bufsiz), int, -1); --} -+ time_t timestamp; -+ char *stripped; -+ int ret, saved_errno; -+ char *conv; - --static int shadow_copy2_mknod(vfs_handle_struct *handle, -- const char *fname, mode_t mode, SMB_DEV_T dev) --{ -- SHADOW2_NEXT(MKNOD, (handle, name, mode, dev), int, -1); -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_READLINK(handle, fname, buf, bufsiz); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_READLINK(handle, conv, buf, bufsiz); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; - } - --static char *shadow_copy2_realpath(vfs_handle_struct *handle, -- const char *fname) -+static int shadow_copy2_mknod(vfs_handle_struct *handle, -+ const char *fname, mode_t mode, SMB_DEV_T dev) - { -- const char *gmt; -+ time_t timestamp; -+ char *stripped; -+ int ret, saved_errno; -+ char *conv; - -- if (shadow_copy2_match_name(fname, &gmt) -- && (gmt[GMT_NAME_LEN] == '\0')) { -- char *copy; -- -- copy = talloc_strdup(talloc_tos(), fname); -- if (copy == NULL) { -- errno = ENOMEM; -- return NULL; -- } -- -- copy[gmt - fname] = '.'; -- copy[gmt - fname + 1] = '\0'; -- -- DEBUG(10, ("calling NEXT_REALPATH with %s\n", copy)); -- SHADOW2_NEXT(REALPATH, (handle, name), char *, -- NULL); -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_MKNOD(handle, fname, mode, dev); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; - } -- SHADOW2_NEXT(REALPATH, (handle, name), char *, NULL); -+ ret = SMB_VFS_NEXT_MKNOD(handle, conv, mode, dev); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; - } - --static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle, -- const char *fname) -+static char *shadow_copy2_realpath(vfs_handle_struct *handle, -+ const char *fname) - { -- TALLOC_CTX *tmp_ctx; -- const char *snapdir, *baseoffset, *basedir, *gmt_start; -- size_t baselen; -- char *ret; -+ time_t timestamp; -+ char *stripped = NULL; -+ char *tmp = NULL; -+ char *result = NULL; -+ char *inserted = NULL; -+ char *inserted_to, *inserted_end; -+ int saved_errno; - -- DEBUG(10, ("shadow_copy2_connectpath called with %s\n", fname)); -- -- if (!shadow_copy2_match_name(fname, &gmt_start)) { -- return handle->conn->connectpath; -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ goto done; - } -- -- /* -- * We have to create a real temporary context because we have -- * to put our result on talloc_tos(). Thus we can't use a -- * talloc_stackframe() here. -- */ -- tmp_ctx = talloc_new(talloc_tos()); -- -- fname = shadow_copy2_normalise_path(tmp_ctx, fname, gmt_start); -- if (fname == NULL) { -- TALLOC_FREE(tmp_ctx); -- return NULL; -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_REALPATH(handle, fname); - } - -- snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle); -- if (snapdir == NULL) { -- DEBUG(2,("no snapdir found for share at %s\n", -- handle->conn->connectpath)); -- TALLOC_FREE(tmp_ctx); -- return NULL; -+ tmp = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ if (tmp == NULL) { -+ goto done; - } - -- basedir = shadow_copy2_find_basedir(tmp_ctx, handle); -- if (basedir == NULL) { -- DEBUG(2,("no basedir found for share at %s\n", -- handle->conn->connectpath)); -- TALLOC_FREE(tmp_ctx); -- return NULL; -+ result = SMB_VFS_NEXT_REALPATH(handle, tmp); -+ if (result == NULL) { -+ goto done; - } - -- baselen = strlen(basedir); -- baseoffset = handle->conn->connectpath + baselen; -- -- /* some sanity checks */ -- if (strncmp(basedir, handle->conn->connectpath, baselen) != 0 || -- (handle->conn->connectpath[baselen] != 0 -- && handle->conn->connectpath[baselen] != '/')) { -- DEBUG(0,("shadow_copy2_connectpath: basedir %s is not a " -- "parent of %s\n", basedir, -- handle->conn->connectpath)); -- TALLOC_FREE(tmp_ctx); -+ /* -+ * Take away what we've inserted. This removes the @GMT-thingy -+ * completely, but will give a path under the share root. -+ */ -+ inserted = shadow_copy2_insert_string(talloc_tos(), handle, timestamp); -+ if (inserted == NULL) { -+ goto done; -+ } -+ inserted_to = strstr_m(result, inserted); -+ if (inserted_to == NULL) { -+ DEBUG(2, ("SMB_VFS_NEXT_REALPATH removed %s\n", inserted)); -+ goto done; -+ } -+ inserted_end = inserted_to + talloc_get_size(inserted) - 1; -+ memmove(inserted_to, inserted_end, strlen(inserted_end)+1); -+ -+done: -+ saved_errno = errno; -+ TALLOC_FREE(inserted); -+ TALLOC_FREE(tmp); -+ TALLOC_FREE(stripped); -+ errno = saved_errno; -+ return result; -+} -+ -+static char *have_snapdir(struct vfs_handle_struct *handle, -+ const char *path) -+{ -+ struct smb_filename smb_fname; -+ int ret; -+ -+ ZERO_STRUCT(smb_fname); -+ smb_fname.base_name = talloc_asprintf( -+ talloc_tos(), "%s/%s", path, -+ lp_parm_const_string(SNUM(handle->conn), "shadow", "snapdir", -+ ".snapshots")); -+ if (smb_fname.base_name == NULL) { - return NULL; - } - -- if (*baseoffset == '/') baseoffset++; -- -- ret = talloc_asprintf(talloc_tos(), "%s/%.*s/%s", -- snapdir, -- GMT_NAME_LEN, fname, -- baseoffset); -- DEBUG(6,("shadow_copy2_connectpath: '%s' -> '%s'\n", fname, ret)); -- TALLOC_FREE(tmp_ctx); -- return ret; --} -- --static NTSTATUS shadow_copy2_get_nt_acl(vfs_handle_struct *handle, -- const char *fname, uint32 security_info, -- struct security_descriptor **ppdesc) --{ -- SHADOW2_NTSTATUS_NEXT(GET_NT_ACL, (handle, name, security_info, ppdesc), NT_STATUS_ACCESS_DENIED); -+ ret = SMB_VFS_NEXT_STAT(handle, &smb_fname); -+ if ((ret == 0) && (S_ISDIR(smb_fname.st.st_ex_mode))) { -+ return smb_fname.base_name; -+ } -+ TALLOC_FREE(smb_fname.base_name); -+ return NULL; - } - --static int shadow_copy2_mkdir(vfs_handle_struct *handle, const char *fname, mode_t mode) -+static char *shadow_copy2_find_snapdir(TALLOC_CTX *mem_ctx, -+ struct vfs_handle_struct *handle, -+ struct smb_filename *smb_fname) - { -- SHADOW2_NEXT(MKDIR, (handle, name, mode), int, -1); --} -+ char *path, *p; -+ char *snapdir; - --static int shadow_copy2_rmdir(vfs_handle_struct *handle, const char *fname) --{ -- SHADOW2_NEXT(RMDIR, (handle, name), int, -1); --} -+ path = talloc_asprintf(mem_ctx, "%s/%s", -+ handle->conn->connectpath, -+ smb_fname->base_name); -+ if (path == NULL) { -+ return NULL; -+ } - --static int shadow_copy2_chflags(vfs_handle_struct *handle, const char *fname, -- unsigned int flags) --{ -- SHADOW2_NEXT(CHFLAGS, (handle, name, flags), int, -1); --} -+ snapdir = have_snapdir(handle, path); -+ if (snapdir != NULL) { -+ TALLOC_FREE(path); -+ return snapdir; -+ } - --static ssize_t shadow_copy2_getxattr(vfs_handle_struct *handle, -- const char *fname, const char *aname, void *value, size_t size) --{ -- SHADOW2_NEXT(GETXATTR, (handle, name, aname, value, size), ssize_t, -1); --} -+ while ((p = strrchr(path, '/')) && (p > path)) { - --static ssize_t shadow_copy2_lgetxattr(vfs_handle_struct *handle, -- const char *fname, const char *aname, void *value, size_t size) --{ -- SHADOW2_NEXT(LGETXATTR, (handle, name, aname, value, size), ssize_t, -1); --} -+ p[0] = '\0'; - --static ssize_t shadow_copy2_listxattr(struct vfs_handle_struct *handle, const char *fname, -- char *list, size_t size) --{ -- SHADOW2_NEXT(LISTXATTR, (handle, name, list, size), ssize_t, -1); -+ snapdir = have_snapdir(handle, path); -+ if (snapdir != NULL) { -+ TALLOC_FREE(path); -+ return snapdir; -+ } -+ } -+ TALLOC_FREE(path); -+ return NULL; - } - --static int shadow_copy2_removexattr(struct vfs_handle_struct *handle, const char *fname, -- const char *aname) -+static bool shadow_copy2_snapshot_to_gmt(TALLOC_CTX *mem_ctx, -+ vfs_handle_struct *handle, -+ const char *name, -+ char *gmt, size_t gmt_len) - { -- SHADOW2_NEXT(REMOVEXATTR, (handle, name, aname), int, -1); --} -+ struct tm timestamp; -+ time_t timestamp_t; -+ const char *fmt; - --static int shadow_copy2_lremovexattr(struct vfs_handle_struct *handle, const char *fname, -- const char *aname) --{ -- SHADOW2_NEXT(LREMOVEXATTR, (handle, name, aname), int, -1); --} -+ fmt = lp_parm_const_string(SNUM(handle->conn), "shadow", -+ "format", GMT_FORMAT); - --static int shadow_copy2_setxattr(struct vfs_handle_struct *handle, const char *fname, -- const char *aname, const void *value, size_t size, int flags) --{ -- SHADOW2_NEXT(SETXATTR, (handle, name, aname, value, size, flags), int, -1); --} -+ ZERO_STRUCT(timestamp); -+ if (strptime(name, fmt, ×tamp) == NULL) { -+ DEBUG(10, ("shadow_copy2_snapshot_to_gmt: no match %s: %s\n", -+ fmt, name)); -+ return false; -+ } - --static int shadow_copy2_lsetxattr(struct vfs_handle_struct *handle, const char *fname, -- const char *aname, const void *value, size_t size, int flags) --{ -- SHADOW2_NEXT(LSETXATTR, (handle, name, aname, value, size, flags), int, -1); --} -+ DEBUG(10, ("shadow_copy2_snapshot_to_gmt: match %s: %s\n", fmt, name)); - --static int shadow_copy2_chmod_acl(vfs_handle_struct *handle, -- const char *fname, mode_t mode) --{ -- SHADOW2_NEXT(CHMOD_ACL, (handle, name, mode), int, -1); -+ if (lp_parm_bool(SNUM(handle->conn), "shadow", "localtime", false)) { -+ timestamp.tm_isdst = -1; -+ timestamp_t = mktime(×tamp); -+ gmtime_r(×tamp_t, ×tamp); -+ } -+ strftime(gmt, gmt_len, GMT_FORMAT, ×tamp); -+ return true; - } - - static int shadow_copy2_label_cmp_asc(const void *x, const void *y) - { -- return strncmp((char *)x, (char *)y, sizeof(SHADOW_COPY_LABEL)); -+ return strncmp((const char *)x, (const char *)y, sizeof(SHADOW_COPY_LABEL)); - } - - static int shadow_copy2_label_cmp_desc(const void *x, const void *y) - { -- return -strncmp((char *)x, (char *)y, sizeof(SHADOW_COPY_LABEL)); -+ return -strncmp((const char *)x, (const char *)y, sizeof(SHADOW_COPY_LABEL)); - } - - /* -@@ -843,7 +1048,7 @@ static void shadow_copy2_sort_data(vfs_h - const char *sort; - - sort = lp_parm_const_string(SNUM(handle->conn), "shadow", -- "sort", SHADOW_COPY2_DEFAULT_SORT); -+ "sort", "desc"); - if (sort == NULL) { - return; - } -@@ -867,18 +1072,17 @@ static void shadow_copy2_sort_data(vfs_h - return; - } - --static int shadow_copy2_get_shadow_copy2_data(vfs_handle_struct *handle, -- files_struct *fsp, -- struct shadow_copy_data *shadow_copy2_data, -- bool labels) -+static int shadow_copy2_get_shadow_copy_data( -+ vfs_handle_struct *handle, files_struct *fsp, -+ struct shadow_copy_data *shadow_copy2_data, -+ bool labels) - { - SMB_STRUCT_DIR *p; - const char *snapdir; - SMB_STRUCT_DIRENT *d; -- TALLOC_CTX *tmp_ctx = talloc_new(handle->data); -- char *snapshot; -+ TALLOC_CTX *tmp_ctx = talloc_stackframe(); - -- snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle); -+ snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle, fsp->fsp_name); - if (snapdir == NULL) { - DEBUG(0,("shadow:snapdir not found for %s in get_shadow_copy_data\n", - handle->conn->connectpath)); -@@ -901,16 +1105,23 @@ static int shadow_copy2_get_shadow_copy2 - shadow_copy2_data->labels = NULL; - - while ((d = SMB_VFS_NEXT_READDIR(handle, p, NULL))) { -+ char snapshot[GMT_NAME_LEN+1]; - SHADOW_COPY_LABEL *tlabels; - -- /* ignore names not of the right form in the snapshot directory */ -- snapshot = shadow_copy2_snapshot_to_gmt(tmp_ctx, handle, -- d->d_name); -- DEBUG(6,("shadow_copy2_get_shadow_copy2_data: %s -> %s\n", -- d->d_name, snapshot)); -- if (!snapshot) { -+ /* -+ * ignore names not of the right form in the snapshot -+ * directory -+ */ -+ if (!shadow_copy2_snapshot_to_gmt( -+ tmp_ctx, handle, d->d_name, -+ snapshot, sizeof(snapshot))) { -+ -+ DEBUG(6, ("shadow_copy2_get_shadow_copy_data: " -+ "ignoring %s\n", d->d_name)); - continue; - } -+ DEBUG(6,("shadow_copy2_get_shadow_copy_data: %s -> %s\n", -+ d->d_name, snapshot)); - - if (!labels) { - /* the caller doesn't want the labels */ -@@ -920,7 +1131,8 @@ static int shadow_copy2_get_shadow_copy2 - - tlabels = talloc_realloc(shadow_copy2_data, - shadow_copy2_data->labels, -- SHADOW_COPY_LABEL, shadow_copy2_data->num_volumes+1); -+ SHADOW_COPY_LABEL, -+ shadow_copy2_data->num_volumes+1); - if (tlabels == NULL) { - DEBUG(0,("shadow_copy2: out of memory\n")); - SMB_VFS_NEXT_CLOSEDIR(handle, p); -@@ -930,7 +1142,6 @@ static int shadow_copy2_get_shadow_copy2 - - strlcpy(tlabels[shadow_copy2_data->num_volumes], snapshot, - sizeof(*tlabels)); -- talloc_free(snapshot); - - shadow_copy2_data->num_volumes++; - shadow_copy2_data->labels = tlabels; -@@ -944,59 +1155,455 @@ static int shadow_copy2_get_shadow_copy2 - return 0; - } - --static struct vfs_fn_pointers vfs_shadow_copy2_fns = { -- .opendir = shadow_copy2_opendir, -- .mkdir = shadow_copy2_mkdir, -- .rmdir = shadow_copy2_rmdir, -- .chflags = shadow_copy2_chflags, -- .getxattr = shadow_copy2_getxattr, -- .lgetxattr = shadow_copy2_lgetxattr, -- .listxattr = shadow_copy2_listxattr, -- .removexattr = shadow_copy2_removexattr, -- .lremovexattr = shadow_copy2_lremovexattr, -- .setxattr = shadow_copy2_setxattr, -- .lsetxattr = shadow_copy2_lsetxattr, -- .open_fn = shadow_copy2_open, -- .rename = shadow_copy2_rename, -- .stat = shadow_copy2_stat, -- .lstat = shadow_copy2_lstat, -- .fstat = shadow_copy2_fstat, -- .unlink = shadow_copy2_unlink, -- .chmod = shadow_copy2_chmod, -- .chown = shadow_copy2_chown, -- .chdir = shadow_copy2_chdir, -- .ntimes = shadow_copy2_ntimes, -- .symlink = shadow_copy2_symlink, -- .vfs_readlink = shadow_copy2_readlink, -- .link = shadow_copy2_link, -- .mknod = shadow_copy2_mknod, -- .realpath = shadow_copy2_realpath, -- .connectpath = shadow_copy2_connectpath, -- .get_nt_acl = shadow_copy2_get_nt_acl, -- .chmod_acl = shadow_copy2_chmod_acl, -- .get_shadow_copy_data = shadow_copy2_get_shadow_copy2_data, --}; -+static NTSTATUS shadow_copy2_fget_nt_acl(vfs_handle_struct *handle, -+ struct files_struct *fsp, -+ uint32 security_info, -+ struct security_descriptor **ppdesc) -+{ -+ time_t timestamp; -+ char *stripped; -+ NTSTATUS status; -+ char *conv; - --NTSTATUS vfs_shadow_copy2_init(void); --NTSTATUS vfs_shadow_copy2_init(void) -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, -+ fsp->fsp_name->base_name, -+ ×tamp, &stripped)) { -+ return map_nt_error_from_unix(errno); -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, -+ ppdesc); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return map_nt_error_from_unix(errno); -+ } -+ status = SMB_VFS_NEXT_GET_NT_ACL(handle, conv, security_info, ppdesc); -+ TALLOC_FREE(conv); -+ return status; -+} -+ -+static NTSTATUS shadow_copy2_get_nt_acl(vfs_handle_struct *handle, -+ const char *fname, -+ uint32 security_info, -+ struct security_descriptor **ppdesc) - { -- NTSTATUS ret; -+ time_t timestamp; -+ char *stripped; -+ NTSTATUS status; -+ char *conv; - -- ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "shadow_copy2", -- &vfs_shadow_copy2_fns); -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return map_nt_error_from_unix(errno); -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_GET_NT_ACL(handle, fname, security_info, -+ ppdesc); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return map_nt_error_from_unix(errno); -+ } -+ status = SMB_VFS_NEXT_GET_NT_ACL(handle, conv, security_info, ppdesc); -+ TALLOC_FREE(conv); -+ return status; -+} - -- if (!NT_STATUS_IS_OK(ret)) -- return ret; -+static int shadow_copy2_mkdir(vfs_handle_struct *handle, -+ const char *fname, mode_t mode) -+{ -+ time_t timestamp; -+ char *stripped; -+ int ret, saved_errno; -+ char *conv; - -- vfs_shadow_copy2_debug_level = debug_add_class("shadow_copy2"); -- if (vfs_shadow_copy2_debug_level == -1) { -- vfs_shadow_copy2_debug_level = DBGC_VFS; -- DEBUG(0, ("%s: Couldn't register custom debugging class!\n", -- "vfs_shadow_copy2_init")); -- } else { -- DEBUG(10, ("%s: Debug class number of '%s': %d\n", -- "vfs_shadow_copy2_init","shadow_copy2",vfs_shadow_copy2_debug_level)); -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_MKDIR(handle, fname, mode); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_MKDIR(handle, conv, mode); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; -+} -+ -+static int shadow_copy2_rmdir(vfs_handle_struct *handle, const char *fname) -+{ -+ time_t timestamp; -+ char *stripped; -+ int ret, saved_errno; -+ char *conv; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; - } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_RMDIR(handle, fname); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_RMDIR(handle, conv); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; -+} -+ -+static int shadow_copy2_chflags(vfs_handle_struct *handle, const char *fname, -+ unsigned int flags) -+{ -+ time_t timestamp; -+ char *stripped; -+ int ret, saved_errno; -+ char *conv; - -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_CHFLAGS(handle, fname, flags); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_CHFLAGS(handle, conv, flags); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; - return ret; - } -+ -+static ssize_t shadow_copy2_getxattr(vfs_handle_struct *handle, -+ const char *fname, const char *aname, -+ void *value, size_t size) -+{ -+ time_t timestamp; -+ char *stripped; -+ ssize_t ret; -+ int saved_errno; -+ char *conv; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_GETXATTR(handle, fname, aname, value, -+ size); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_GETXATTR(handle, conv, aname, value, size); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; -+} -+ -+static ssize_t shadow_copy2_lgetxattr(vfs_handle_struct *handle, -+ const char *fname, const char *aname, -+ void *value, size_t size) -+{ -+ time_t timestamp; -+ char *stripped; -+ ssize_t ret; -+ int saved_errno; -+ char *conv; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_LGETXATTR(handle, fname, aname, value, -+ size); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_LGETXATTR(handle, conv, aname, value, size); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; -+} -+ -+static ssize_t shadow_copy2_listxattr(struct vfs_handle_struct *handle, -+ const char *fname, -+ char *list, size_t size) -+{ -+ time_t timestamp; -+ char *stripped; -+ ssize_t ret; -+ int saved_errno; -+ char *conv; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_LISTXATTR(handle, fname, list, size); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_LISTXATTR(handle, conv, list, size); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; -+} -+ -+static int shadow_copy2_removexattr(vfs_handle_struct *handle, -+ const char *fname, const char *aname) -+{ -+ time_t timestamp; -+ char *stripped; -+ int ret, saved_errno; -+ char *conv; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_REMOVEXATTR(handle, fname, aname); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_REMOVEXATTR(handle, conv, aname); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; -+} -+ -+static int shadow_copy2_lremovexattr(vfs_handle_struct *handle, -+ const char *fname, const char *aname) -+{ -+ time_t timestamp; -+ char *stripped; -+ int ret, saved_errno; -+ char *conv; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_LREMOVEXATTR(handle, fname, aname); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_LREMOVEXATTR(handle, conv, aname); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; -+} -+ -+static int shadow_copy2_setxattr(struct vfs_handle_struct *handle, -+ const char *fname, -+ const char *aname, const void *value, -+ size_t size, int flags) -+{ -+ time_t timestamp; -+ char *stripped; -+ ssize_t ret; -+ int saved_errno; -+ char *conv; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_SETXATTR(handle, fname, aname, value, size, -+ flags); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_SETXATTR(handle, conv, aname, value, size, flags); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; -+} -+ -+static int shadow_copy2_lsetxattr(struct vfs_handle_struct *handle, -+ const char *fname, -+ const char *aname, const void *value, -+ size_t size, int flags) -+{ -+ time_t timestamp; -+ char *stripped; -+ ssize_t ret; -+ int saved_errno; -+ char *conv; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_LSETXATTR(handle, fname, aname, value, -+ size, flags); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_LSETXATTR(handle, conv, aname, value, size, flags); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; -+} -+ -+static int shadow_copy2_chmod_acl(vfs_handle_struct *handle, -+ const char *fname, mode_t mode) -+{ -+ time_t timestamp; -+ char *stripped; -+ ssize_t ret; -+ int saved_errno; -+ char *conv; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_CHMOD_ACL(handle, fname, mode); -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_CHMOD_ACL(handle, conv, mode); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; -+} -+ -+static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle, -+ const char *path, -+ const char *name, -+ TALLOC_CTX *mem_ctx, -+ char **found_name) -+{ -+ time_t timestamp; -+ char *stripped; -+ ssize_t ret; -+ int saved_errno; -+ char *conv; -+ -+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path, -+ ×tamp, &stripped)) { -+ return -1; -+ } -+ if (timestamp == 0) { -+ return SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name, -+ mem_ctx, found_name); -+ } -+ if (stripped[0] == '\0') { -+ *found_name = talloc_strdup(mem_ctx, name); -+ if (*found_name == NULL) { -+ errno = ENOMEM; -+ return -1; -+ } -+ return 0; -+ } -+ conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); -+ TALLOC_FREE(stripped); -+ if (conv == NULL) { -+ return -1; -+ } -+ ret = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, conv, name, -+ mem_ctx, found_name); -+ saved_errno = errno; -+ TALLOC_FREE(conv); -+ errno = saved_errno; -+ return ret; -+} -+ -+ -+static struct vfs_fn_pointers vfs_shadow_copy2_fns = { -+ .opendir = shadow_copy2_opendir, -+ .rename = shadow_copy2_rename, -+ .link = shadow_copy2_link, -+ .symlink = shadow_copy2_symlink, -+ .stat = shadow_copy2_stat, -+ .lstat = shadow_copy2_lstat, -+ .fstat = shadow_copy2_fstat, -+ .open_fn = shadow_copy2_open, -+ .unlink = shadow_copy2_unlink, -+ .chmod = shadow_copy2_chmod, -+ .chown = shadow_copy2_chown, -+ .chdir = shadow_copy2_chdir, -+ .ntimes = shadow_copy2_ntimes, -+ .vfs_readlink = shadow_copy2_readlink, -+ .mknod = shadow_copy2_mknod, -+ .realpath = shadow_copy2_realpath, -+ .get_nt_acl = shadow_copy2_get_nt_acl, -+ .fget_nt_acl = shadow_copy2_fget_nt_acl, -+ .get_shadow_copy_data = shadow_copy2_get_shadow_copy_data, -+ .mkdir = shadow_copy2_mkdir, -+ .rmdir = shadow_copy2_rmdir, -+ .getxattr = shadow_copy2_getxattr, -+ .lgetxattr = shadow_copy2_lgetxattr, -+ .listxattr = shadow_copy2_listxattr, -+ .removexattr = shadow_copy2_removexattr, -+ .lremovexattr = shadow_copy2_lremovexattr, -+ .setxattr = shadow_copy2_setxattr, -+ .lsetxattr = shadow_copy2_lsetxattr, -+ .chmod_acl = shadow_copy2_chmod_acl, -+ .chflags = shadow_copy2_chflags, -+ .get_real_filename = shadow_copy2_get_real_filename, -+}; -+ -+NTSTATUS vfs_shadow_copy2_init(void); -+NTSTATUS vfs_shadow_copy2_init(void) -+{ -+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, -+ "shadow_copy2", &vfs_shadow_copy2_fns); -+} diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/smbclient-pager.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/smbclient-pager.patch deleted file mode 100644 index 429f2cec..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/smbclient-pager.patch +++ /dev/null @@ -1,18 +0,0 @@ -Description: Use the pager alternative as pager is PAGER is undefined -Author: Steve Langasek -Bug-Debian: http://bugs.debian.org/135603 -Forwarded: not-needed - -Index: experimental/source3/include/local.h -=================================================================== ---- experimental.orig/source3/include/local.h -+++ experimental/source3/include/local.h -@@ -127,7 +127,7 @@ - /* the default pager to use for the client "more" command. Users can - override this with the PAGER environment variable */ - #ifndef PAGER --#define PAGER "more" -+#define PAGER "/usr/bin/pager" - #endif - - /* the size of the uid cache used to reduce valid user checks */ diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/smbtar-bashism.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/smbtar-bashism.patch deleted file mode 100644 index 27a47cb5..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/smbtar-bashism.patch +++ /dev/null @@ -1,19 +0,0 @@ -Description: Avoid using bashism in smbtar -Author: Jelmer Vernooij -Bug-Debian: http://bugs.debian.org/486056 -Forwarded: yes -Bug: https://bugzilla.samba.org/show_bug.cgi?id=8924 - -Index: experimental/source3/script/smbtar -=================================================================== ---- experimental.orig/source3/script/smbtar -+++ experimental/source3/script/smbtar -@@ -151,7 +151,7 @@ - if [ -z "$verbose" ]; then - echo "server is $server" - # echo "share is $service" -- echo "share is $service\\$cdcmd" -+ printf "share is %s\\%s\n" "$service" "$cdcmd" - echo "tar args is $tarargs" - # echo "password is $password" # passwords should never be sent to screen - echo "tape is $tapefile" diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/smbtorture-manpage.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/smbtorture-manpage.patch deleted file mode 100644 index 59930b5e..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/smbtorture-manpage.patch +++ /dev/null @@ -1,94 +0,0 @@ -Description: Provide a manpage for smbtorture -Author: Christian Perrier -Bug: https://bugzilla.samba.org/show_bug.cgi?id=8930 -Forwarded: yes -Bug-Debian: http://bugs.debian.org/528735 - -Index: samba/docs/manpages/smbtorture.1 -=================================================================== ---- /dev/null -+++ samba/docs/manpages/smbtorture.1 -@@ -0,0 +1,83 @@ -+.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.40.9. -+.TH smbtorture "1" "May 2012" "samba test suite" "User Commands" -+.SH NAME -+smbtorture \- samba test suite. -+.SH SYNOPSIS -+.B smbtorture -+\fI//server/share TEST1 TEST2 \fR... -+.SH DESCRIPTION -+smbtorture is the original samba3 test suite. It is nowadays recommended to use samba4 torture. -+.HP -+\fB\-d\fR debuglevel -+.HP -+\fB\-U\fR user%pass -+.TP -+\fB\-k\fR -+use kerberos -+.HP -+\fB\-N\fR numprocs -+.HP -+\fB\-n\fR my_netbios_name -+.HP -+\fB\-W\fR workgroup -+.HP -+\fB\-o\fR num_operations -+.HP -+\fB\-O\fR socket_options -+.HP -+\fB\-m\fR maximum protocol -+.HP -+\fB\-L\fR use oplocks -+.TP -+\fB\-c\fR CLIENT.TXT -+specify client load file for NBENCH -+.HP -+\fB\-A\fR showall -+.HP -+\fB\-p\fR port -+.HP -+\fB\-s\fR seed -+.TP -+\fB\-b\fR unclist_filename -+specify multiple shares for multiple connections -+.PP -+tests are: FDPASS LOCK1 LOCK2 LOCK3 LOCK4 LOCK5 LOCK6 LOCK7 LOCK8 LOCK9 UNLINK BROWSE ATTR TRANS2 MAXFID TORTURE RANDOMIPC NEGNOWAIT NBENCH NBENCH2 OPLOCK1 OPLOCK2 OPLOCK3 OPLOCK4 DIR DIR1 DIR\-CREATETIME DENY1 DENY2 TCON TCONDEV RW1 RW2 RW3 RW\-SIGNING OPEN POSIX POSIX\-APPEND ASYNC\-ECHO UID\-REGRESSION\-TEST SHORTNAME\-TEST ADDRCHANGE OPENATTR XCOPY RENAME DELETE DELETE\-LN PROPERTIES MANGLE MANGLE1 W2K TRANS2SCAN NTTRANSSCAN UTABLE CASETABLE ERRMAPEXTRACT PIPE_NUMBER TCON2 IOCTL CHKPATH FDSESS EATEST SESSSETUP_BENCH CHAIN1 CHAIN2 WINDOWS\-WRITE CLI_ECHO GETADDRINFO TLDAP STREAMERROR NOTIFY\-BENCH BAD\-NBT\-SESSION SMB\-ANY\-CONNECT LOCAL\-SUBSTITUTE LOCAL\-GENCACHE LOCAL\-TALLOC\-DICT LOCAL\-BASE64 LOCAL\-RBTREE LOCAL\-MEMCACHE LOCAL\-STREAM\-NAME LOCAL\-WBCLIENT LOCAL\-string_to_sid LOCAL\-binary_to_sid LOCAL\-DBTRANS LOCAL\-TEVENT\-SELECT -+default test is ALL -+.PP -+Usage: smbtorture //server/share TEST1 TEST2 ... -+.HP -+\fB\-d\fR debuglevel -+.HP -+\fB\-U\fR user%pass -+.TP -+\fB\-k\fR -+use kerberos -+.HP -+\fB\-N\fR numprocs -+.HP -+\fB\-n\fR my_netbios_name -+.HP -+\fB\-W\fR workgroup -+.HP -+\fB\-o\fR num_operations -+.HP -+\fB\-O\fR socket_options -+.HP -+\fB\-m\fR maximum protocol -+.HP -+\fB\-L\fR use oplocks -+.TP -+\fB\-c\fR CLIENT.TXT -+specify client load file for NBENCH -+.HP -+\fB\-A\fR showall -+.HP -+\fB\-p\fR port -+.HP -+\fB\-s\fR seed -+.TP -+\fB\-b\fR unclist_filename -+specify multiple shares for multiple connections -+.PP -+tests are: FDPASS LOCK1 LOCK2 LOCK3 LOCK4 LOCK5 LOCK6 LOCK7 LOCK8 LOCK9 UNLINK BROWSE ATTR TRANS2 MAXFID TORTURE RANDOMIPC NEGNOWAIT NBENCH NBENCH2 OPLOCK1 OPLOCK2 OPLOCK3 OPLOCK4 DIR DIR1 DIR\-CREATETIME DENY1 DENY2 TCON TCONDEV RW1 RW2 RW3 RW\-SIGNING OPEN POSIX POSIX\-APPEND ASYNC\-ECHO UID\-REGRESSION\-TEST SHORTNAME\-TEST ADDRCHANGE OPENATTR XCOPY RENAME DELETE DELETE\-LN PROPERTIES MANGLE MANGLE1 W2K TRANS2SCAN NTTRANSSCAN UTABLE CASETABLE ERRMAPEXTRACT PIPE_NUMBER TCON2 IOCTL CHKPATH FDSESS EATEST SESSSETUP_BENCH CHAIN1 CHAIN2 WINDOWS\-WRITE CLI_ECHO GETADDRINFO TLDAP STREAMERROR NOTIFY\-BENCH BAD\-NBT\-SESSION SMB\-ANY\-CONNECT LOCAL\-SUBSTITUTE LOCAL\-GENCACHE LOCAL\-TALLOC\-DICT LOCAL\-BASE64 LOCAL\-RBTREE LOCAL\-MEMCACHE LOCAL\-STREAM\-NAME LOCAL\-WBCLIENT LOCAL\-string_to_sid LOCAL\-binary_to_sid LOCAL\-DBTRANS LOCAL\-TEVENT\-SELECT -+default test is ALL diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/undefined-symbols.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/undefined-symbols.patch deleted file mode 100644 index 5babc1e3..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/undefined-symbols.patch +++ /dev/null @@ -1,24 +0,0 @@ -Description: Fix missing symbols - Fix missing symbols in libsmbclient (and libnss_wins), and add - -Wl,-z,defs to the libsmbclient link options to prevent future - instances of undefined symbols. - . - This should be forwarded upstream once there's a configure test - for it. -Author: Steve Langasek -Bug-Debian: http://bugs.debian.org/281181 -Forwarded: no - -Index: experimental/source3/Makefile.in -=================================================================== ---- experimental.orig/source3/Makefile.in -+++ experimental/source3/Makefile.in -@@ -2594,7 +2594,7 @@ - - $(LIBSMBCLIENT_SHARED_TARGET_SONAME): $(BINARY_PREREQS) $(LIBSMBCLIENT_OBJ) $(LIBSMBCLIENT_THREAD_OBJ) $(LIBSMBCLIENT_SYMS) $(LIBTALLOC) $(LIBTEVENT) $(LIBTDB) $(LIBWBCLIENT) - @echo Linking shared library $@ -- @$(SHLD_DSO) $(LIBSMBCLIENT_OBJ) $(LIBSMBCLIENT_THREAD_OBJ) \ -+ @$(SHLD_DSO) -Wl,-z,defs $(LIBSMBCLIENT_OBJ) $(LIBSMBCLIENT_THREAD_OBJ) \ - $(LIBTALLOC_LIBS) $(LIBTEVENT_LIBS) $(LIBTDB_LIBS) $(LIBWBCLIENT_LIBS) $(LIBS) \ - $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) $(ZLIB_LIBS) $(PTHREAD_LDFLAGS) \ - @SONAMEFLAG@`basename $@` diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/usershare.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/usershare.patch deleted file mode 100644 index 3673db75..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/usershare.patch +++ /dev/null @@ -1,38 +0,0 @@ -Description: Enable net usershares by default at build time - Enable net usershares by default at build time, with a limit of - 100, and update the corresponding documentation. -Author: Mathias Gug , -Author: Steve Langasek -Bug-Debian: http://bugs.debian.org/443230 -Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/samba/+bug/128548 -Forwarded: not-needed - -Index: experimental/docs/manpages/net.8 -=================================================================== ---- experimental.orig/docs/manpages/net.8 -+++ experimental/docs/manpages/net.8 -@@ -800,9 +800,9 @@ - .RE - .SS "USERSHARE" - .PP --Starting with version 3\&.0\&.23, a Samba server now supports the ability for non\-root users to add user defined shares to be exported using the "net usershare" commands\&. -+Starting with version 3\&.0\&.23, a Samba server now supports the ability for non\-root users to add user-defined shares to be exported using the "net usershare" commands\&. - .PP --To set this up, first set up your smb\&.conf by adding to the [global] section: usershare path = /usr/local/samba/lib/usershares Next create the directory /usr/local/samba/lib/usershares, change the owner to root and set the group owner to the UNIX group who should have the ability to create usershares, for example a group called "serverops"\&. Set the permissions on /usr/local/samba/lib/usershares to 01770\&. (Owner and group all access, no access for others, plus the sticky bit, which means that a file in that directory can be renamed or deleted only by the owner of the file)\&. Finally, tell smbd how many usershares you will allow by adding to the [global] section of smb\&.conf a line such as : usershare max shares = 100\&. To allow 100 usershare definitions\&. Now, members of the UNIX group "serverops" can create user defined shares on demand using the commands below\&. -+Members of the UNIX group "sambashare" can create user-defined shares on demand using the commands below\&. - .PP - The usershare commands are: - .RS 4 -Index: experimental/source3/param/loadparm.c -=================================================================== ---- experimental.orig/source3/param/loadparm.c -+++ experimental/source3/param/loadparm.c -@@ -5461,7 +5461,7 @@ - string_set(&Globals.szUsersharePath, s); - SAFE_FREE(s); - string_set(&Globals.szUsershareTemplateShare, ""); -- Globals.iUsershareMaxShares = 0; -+ Globals.iUsershareMaxShares = 100; - /* By default disallow sharing of directories not owned by the sharer. */ - Globals.bUsershareOwnerOnly = True; - /* By default disallow guest access to usershares. */ diff --git a/meta-oe/recipes-connectivity/samba/samba-3.6.25/waf-as-source.patch b/meta-oe/recipes-connectivity/samba/samba-3.6.25/waf-as-source.patch deleted file mode 100644 index 985ed5af..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-3.6.25/waf-as-source.patch +++ /dev/null @@ -1,18534 +0,0 @@ -Description: Include waf as an extracted source directory, rather than as a one-in-a-file script. -Author: Jelmer Vernooij -Bug-Debian: http://bugs.debian.org/654499 -Forwarded: yes -Bug: https://bugzilla.samba.org/show_bug.cgi?id=8923 - -diff --git a/buildtools/README b/buildtools/README -new file mode 100644 -index 0000000..eab0382 ---- /dev/null -+++ b/buildtools/README -@@ -0,0 +1,12 @@ -+See http://code.google.com/p/waf/ for more information on waf -+ -+You can get a svn copy of the upstream source with: -+ -+ svn checkout http://waf.googlecode.com/svn/trunk/ waf-read-only -+ -+Samba currently uses waf 1.5, which can be found at: -+ -+ http://waf.googlecode.com/svn/branches/waf-1.5 -+ -+To update the current copy of waf, use the update-waf.sh script in this -+directory. -diff --git a/buildtools/bin/README b/buildtools/bin/README -deleted file mode 100644 -index 9ef8a1f..0000000 ---- a/buildtools/bin/README -+++ /dev/null -@@ -1,16 +0,0 @@ --This copy of waf-svn is taken from the git mirror of waf --at: -- -- git://git.samba.org/tridge/waf-svn.git -- --using the waf-samba branch -- --It was built using the command: -- -- ./waf-light --zip-type=gz --make-waf -- --See http://code.google.com/p/waf/ for more information on waf -- --You can get a svn copy of the upstream source with: -- -- svn checkout http://waf.googlecode.com/svn/trunk/ waf-read-only -diff --git a/buildtools/update-waf.sh b/buildtools/update-waf.sh -new file mode 100755 -index 0000000..bb3a4bf ---- /dev/null -+++ b/buildtools/update-waf.sh -@@ -0,0 +1,13 @@ -+#!/bin/sh -+# Update our copy of waf -+ -+TARGETDIR="`dirname $0`" -+WORKDIR="`mktemp -d`" -+ -+mkdir -p "$WORKDIR" -+ -+svn checkout http://waf.googlecode.com/svn/branches/waf-1.5/wafadmin "$WORKDIR/wafadmin" -+ -+rsync -C -avz --delete "$WORKDIR/wafadmin/" "$TARGETDIR/wafadmin/" -+ -+rm -rf "$WORKDIR" -diff --git a/buildtools/wafadmin/3rdparty/ParallelDebug.py b/buildtools/wafadmin/3rdparty/ParallelDebug.py -new file mode 100644 -index 0000000..9d0493e ---- /dev/null -+++ b/buildtools/wafadmin/3rdparty/ParallelDebug.py -@@ -0,0 +1,299 @@ -+#! /usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2007-2010 (ita) -+ -+""" -+debugging helpers for parallel compilation, outputs -+a svg file in the build directory -+""" -+ -+import os, time, sys, threading -+try: from Queue import Queue -+except: from queue import Queue -+import Runner, Options, Utils, Task, Logs -+from Constants import * -+ -+#import random -+#random.seed(100) -+ -+def set_options(opt): -+ opt.add_option('--dtitle', action='store', default='Parallel build representation for %r' % ' '.join(sys.argv), -+ help='title for the svg diagram', dest='dtitle') -+ opt.add_option('--dwidth', action='store', type='int', help='diagram width', default=1000, dest='dwidth') -+ opt.add_option('--dtime', action='store', type='float', help='recording interval in seconds', default=0.009, dest='dtime') -+ opt.add_option('--dband', action='store', type='int', help='band width', default=22, dest='dband') -+ opt.add_option('--dmaxtime', action='store', type='float', help='maximum time, for drawing fair comparisons', default=0, dest='dmaxtime') -+ -+# red #ff4d4d -+# green #4da74d -+# lila #a751ff -+ -+color2code = { -+ 'GREEN' : '#4da74d', -+ 'YELLOW' : '#fefe44', -+ 'PINK' : '#a751ff', -+ 'RED' : '#cc1d1d', -+ 'BLUE' : '#6687bb', -+ 'CYAN' : '#34e2e2', -+ -+} -+ -+mp = {} -+info = [] # list of (text,color) -+ -+def map_to_color(name): -+ if name in mp: -+ return mp[name] -+ try: -+ cls = Task.TaskBase.classes[name] -+ except KeyError: -+ return color2code['RED'] -+ if cls.color in mp: -+ return mp[cls.color] -+ if cls.color in color2code: -+ return color2code[cls.color] -+ return color2code['RED'] -+ -+def loop(self): -+ while 1: -+ tsk=Runner.TaskConsumer.ready.get() -+ tsk.master.set_running(1, id(threading.currentThread()), tsk) -+ Runner.process_task(tsk) -+ tsk.master.set_running(-1, id(threading.currentThread()), tsk) -+Runner.TaskConsumer.loop = loop -+ -+ -+old_start = Runner.Parallel.start -+def do_start(self): -+ print Options.options -+ try: -+ Options.options.dband -+ except AttributeError: -+ raise ValueError('use def options(opt): opt.load("parallel_debug")!') -+ -+ self.taskinfo = Queue() -+ old_start(self) -+ process_colors(self) -+Runner.Parallel.start = do_start -+ -+def set_running(self, by, i, tsk): -+ self.taskinfo.put( (i, id(tsk), time.time(), tsk.__class__.__name__, self.processed, self.count, by) ) -+Runner.Parallel.set_running = set_running -+ -+def name2class(name): -+ return name.replace(' ', '_').replace('.', '_') -+ -+def process_colors(producer): -+ # first, cast the parameters -+ tmp = [] -+ try: -+ while True: -+ tup = producer.taskinfo.get(False) -+ tmp.append(list(tup)) -+ except: -+ pass -+ -+ try: -+ ini = float(tmp[0][2]) -+ except: -+ return -+ -+ if not info: -+ seen = [] -+ for x in tmp: -+ name = x[3] -+ if not name in seen: -+ seen.append(name) -+ else: -+ continue -+ -+ info.append((name, map_to_color(name))) -+ info.sort(key=lambda x: x[0]) -+ -+ thread_count = 0 -+ acc = [] -+ for x in tmp: -+ thread_count += x[6] -+ acc.append("%d %d %f %r %d %d %d" % (x[0], x[1], x[2] - ini, x[3], x[4], x[5], thread_count)) -+ f = open('pdebug.dat', 'w') -+ #Utils.write('\n'.join(acc)) -+ f.write('\n'.join(acc)) -+ -+ tmp = [lst[:2] + [float(lst[2]) - ini] + lst[3:] for lst in tmp] -+ -+ st = {} -+ for l in tmp: -+ if not l[0] in st: -+ st[l[0]] = len(st.keys()) -+ tmp = [ [st[lst[0]]] + lst[1:] for lst in tmp ] -+ THREAD_AMOUNT = len(st.keys()) -+ -+ st = {} -+ for l in tmp: -+ if not l[1] in st: -+ st[l[1]] = len(st.keys()) -+ tmp = [ [lst[0]] + [st[lst[1]]] + lst[2:] for lst in tmp ] -+ -+ -+ BAND = Options.options.dband -+ -+ seen = {} -+ acc = [] -+ for x in range(len(tmp)): -+ line = tmp[x] -+ id = line[1] -+ -+ if id in seen: -+ continue -+ seen[id] = True -+ -+ begin = line[2] -+ thread_id = line[0] -+ for y in range(x + 1, len(tmp)): -+ line = tmp[y] -+ if line[1] == id: -+ end = line[2] -+ #print id, thread_id, begin, end -+ #acc.append( ( 10*thread_id, 10*(thread_id+1), 10*begin, 10*end ) ) -+ acc.append( (BAND * begin, BAND*thread_id, BAND*end - BAND*begin, BAND, line[3]) ) -+ break -+ -+ if Options.options.dmaxtime < 0.1: -+ gwidth = 1 -+ for x in tmp: -+ m = BAND * x[2] -+ if m > gwidth: -+ gwidth = m -+ else: -+ gwidth = BAND * Options.options.dmaxtime -+ -+ ratio = float(Options.options.dwidth) / gwidth -+ gwidth = Options.options.dwidth -+ -+ gheight = BAND * (THREAD_AMOUNT + len(info) + 1.5) -+ -+ out = [] -+ -+ out.append(""" -+ -+ -+ -+ -+ -+ -+ -+ -+\n -+ -+""" % (0, 0, gwidth + 4, gheight + 4, 0, 0, gwidth + 4, gheight + 4)) -+ -+ # main title -+ if Options.options.dtitle: -+ out.append("""%s -+""" % (gwidth/2, gheight - 5, Options.options.dtitle)) -+ -+ # the rectangles -+ groups = {} -+ for (x, y, w, h, clsname) in acc: -+ try: -+ groups[clsname].append((x, y, w, h)) -+ except: -+ groups[clsname] = [(x, y, w, h)] -+ -+ for cls in groups: -+ -+ out.append("\n" % name2class(cls)) -+ -+ for (x, y, w, h) in groups[cls]: -+ out.append(""" \n""" % (2 + x*ratio, 2 + y, w*ratio, h, map_to_color(cls))) -+ -+ out.append("\n") -+ -+ # output the caption -+ cnt = THREAD_AMOUNT -+ -+ for (text, color) in info: -+ # caption box -+ b = BAND/2 -+ out.append("""\n""" % (name2class(text), 2 + BAND, 5 + (cnt + 0.5) * BAND, b, b, color)) -+ -+ # caption text -+ out.append("""%s\n""" % (2 + 2 * BAND, 5 + (cnt + 0.5) * BAND + 10, text)) -+ cnt += 1 -+ -+ out.append(""" -+ -+ -+ -+""") -+ -+ out.append("\n") -+ -+ #node = producer.bld.path.make_node('pdebug.svg') -+ f = open('pdebug.svg', 'w') -+ f.write("".join(out)) -+ -+ -diff --git a/buildtools/wafadmin/3rdparty/batched_cc.py b/buildtools/wafadmin/3rdparty/batched_cc.py -new file mode 100644 -index 0000000..8e31074 ---- /dev/null -+++ b/buildtools/wafadmin/3rdparty/batched_cc.py -@@ -0,0 +1,183 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006 (ita) -+ -+""" -+Batched builds - compile faster -+instead of compiling object files one by one, c/c++ compilers are often able to compile at once: -+cc -c ../file1.c ../file2.c ../file3.c -+ -+Files are output on the directory where the compiler is called, and dependencies are more difficult -+to track (do not run the command on all source files if only one file changes) -+ -+As such, we do as if the files were compiled one by one, but no command is actually run: -+replace each cc/cpp Task by a TaskSlave -+A new task called TaskMaster collects the signatures from each slave and finds out the command-line -+to run. -+ -+To set this up, the method ccroot::create_task is replaced by a new version, to enable batched builds -+it is only necessary to import this module in the configuration (no other change required) -+""" -+ -+MAX_BATCH = 50 -+MAXPARALLEL = False -+ -+EXT_C = ['.c', '.cc', '.cpp', '.cxx'] -+ -+import os, threading -+import TaskGen, Task, ccroot, Build, Logs -+from TaskGen import extension, feature, before -+from Constants import * -+ -+cc_str = '${CC} ${CCFLAGS} ${CPPFLAGS} ${_CCINCFLAGS} ${_CCDEFFLAGS} -c ${SRCLST}' -+cc_fun = Task.compile_fun_noshell('batched_cc', cc_str)[0] -+ -+cxx_str = '${CXX} ${CXXFLAGS} ${CPPFLAGS} ${_CXXINCFLAGS} ${_CXXDEFFLAGS} -c ${SRCLST}' -+cxx_fun = Task.compile_fun_noshell('batched_cxx', cxx_str)[0] -+ -+count = 70000 -+class batch_task(Task.Task): -+ color = 'RED' -+ -+ after = 'cc cxx' -+ before = 'cc_link cxx_link static_link' -+ -+ def __str__(self): -+ return '(batch compilation for %d slaves)\n' % len(self.slaves) -+ -+ def __init__(self, *k, **kw): -+ Task.Task.__init__(self, *k, **kw) -+ self.slaves = [] -+ self.inputs = [] -+ self.hasrun = 0 -+ -+ global count -+ count += 1 -+ self.idx = count -+ -+ def add_slave(self, slave): -+ self.slaves.append(slave) -+ self.set_run_after(slave) -+ -+ def runnable_status(self): -+ for t in self.run_after: -+ if not t.hasrun: -+ return ASK_LATER -+ -+ for t in self.slaves: -+ #if t.executed: -+ if t.hasrun != SKIPPED: -+ return RUN_ME -+ -+ return SKIP_ME -+ -+ def run(self): -+ outputs = [] -+ self.outputs = [] -+ -+ srclst = [] -+ slaves = [] -+ for t in self.slaves: -+ if t.hasrun != SKIPPED: -+ slaves.append(t) -+ srclst.append(t.inputs[0].abspath(self.env)) -+ -+ self.env.SRCLST = srclst -+ self.cwd = slaves[0].inputs[0].parent.abspath(self.env) -+ -+ env = self.env -+ app = env.append_unique -+ cpppath_st = env['CPPPATH_ST'] -+ env._CCINCFLAGS = env.CXXINCFLAGS = [] -+ -+ # local flags come first -+ # set the user-defined includes paths -+ for i in env['INC_PATHS']: -+ app('_CCINCFLAGS', cpppath_st % i.abspath()) -+ app('_CXXINCFLAGS', cpppath_st % i.abspath()) -+ app('_CCINCFLAGS', cpppath_st % i.abspath(env)) -+ app('_CXXINCFLAGS', cpppath_st % i.abspath(env)) -+ -+ # set the library include paths -+ for i in env['CPPPATH']: -+ app('_CCINCFLAGS', cpppath_st % i) -+ app('_CXXINCFLAGS', cpppath_st % i) -+ -+ if self.slaves[0].__class__.__name__ == 'cc': -+ ret = cc_fun(self) -+ else: -+ ret = cxx_fun(self) -+ -+ if ret: -+ return ret -+ -+ for t in slaves: -+ t.old_post_run() -+ -+from TaskGen import extension, feature, after -+ -+import cc, cxx -+def wrap(fun): -+ def foo(self, node): -+ # we cannot control the extension, this sucks -+ self.obj_ext = '.o' -+ -+ task = fun(self, node) -+ if not getattr(self, 'masters', None): -+ self.masters = {} -+ self.allmasters = [] -+ -+ if not node.parent.id in self.masters: -+ m = self.masters[node.parent.id] = self.master = self.create_task('batch') -+ self.allmasters.append(m) -+ else: -+ m = self.masters[node.parent.id] -+ if len(m.slaves) > MAX_BATCH: -+ m = self.masters[node.parent.id] = self.master = self.create_task('batch') -+ self.allmasters.append(m) -+ -+ m.add_slave(task) -+ return task -+ return foo -+ -+c_hook = wrap(cc.c_hook) -+extension(cc.EXT_CC)(c_hook) -+ -+cxx_hook = wrap(cxx.cxx_hook) -+extension(cxx.EXT_CXX)(cxx_hook) -+ -+ -+@feature('cprogram', 'cshlib', 'cstaticlib') -+@after('apply_link') -+def link_after_masters(self): -+ if getattr(self, 'allmasters', None): -+ for m in self.allmasters: -+ self.link_task.set_run_after(m) -+ -+for c in ['cc', 'cxx']: -+ t = Task.TaskBase.classes[c] -+ def run(self): -+ pass -+ -+ def post_run(self): -+ #self.executed=1 -+ pass -+ -+ def can_retrieve_cache(self): -+ if self.old_can_retrieve_cache(): -+ for m in self.generator.allmasters: -+ try: -+ m.slaves.remove(self) -+ except ValueError: -+ pass #this task wasn't included in that master -+ return 1 -+ else: -+ return None -+ -+ setattr(t, 'oldrun', t.__dict__['run']) -+ setattr(t, 'run', run) -+ setattr(t, 'old_post_run', t.post_run) -+ setattr(t, 'post_run', post_run) -+ setattr(t, 'old_can_retrieve_cache', t.can_retrieve_cache) -+ setattr(t, 'can_retrieve_cache', can_retrieve_cache) -+ -diff --git a/buildtools/wafadmin/3rdparty/boost.py b/buildtools/wafadmin/3rdparty/boost.py -new file mode 100644 -index 0000000..e690a4e ---- /dev/null -+++ b/buildtools/wafadmin/3rdparty/boost.py -@@ -0,0 +1,343 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# -+# partially based on boost.py written by Gernot Vormayr -+# written by Ruediger Sonderfeld , 2008 -+# modified by Bjoern Michaelsen, 2008 -+# modified by Luca Fossati, 2008 -+# rewritten for waf 1.5.1, Thomas Nagy, 2008 -+# -+#def set_options(opt): -+# opt.tool_options('boost') -+# # ... -+# -+#def configure(conf): -+# # ... (e.g. conf.check_tool('g++')) -+# conf.check_tool('boost') -+# conf.check_boost(lib='signals filesystem', static='onlystatic', score_version=(-1000, 1000), tag_minscore=1000) -+# -+#def build(bld): -+# bld(source='main.c', target='bar', uselib="BOOST BOOST_SYSTEM") -+# -+#ISSUES: -+# * find_includes should be called only once! -+# * support mandatory -+ -+######## boost update ########### -+## ITA: * the method get_boost_version_number does work -+## * the rest of the code has not really been tried -+# * make certain a demo is provided (in demos/adv for example) -+ -+# TODO: bad and underdocumented code -> boost.py will be removed in waf 1.6 to be rewritten later -+ -+import os.path, glob, types, re, sys -+import Configure, config_c, Options, Utils, Logs -+from Logs import warn, debug -+from Configure import conf -+ -+boost_code = ''' -+#include -+#include -+int main() { std::cout << BOOST_VERSION << std::endl; } -+''' -+ -+boost_libpath = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib'] -+boost_cpppath = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include'] -+ -+STATIC_NOSTATIC = 'nostatic' -+STATIC_BOTH = 'both' -+STATIC_ONLYSTATIC = 'onlystatic' -+ -+is_versiontag = re.compile('^\d+_\d+_?\d*$') -+is_threadingtag = re.compile('^mt$') -+is_abitag = re.compile('^[sgydpn]+$') -+is_toolsettag = re.compile('^(acc|borland|como|cw|dmc|darwin|gcc|hp_cxx|intel|kylix|vc|mgw|qcc|sun|vacpp)\d*$') -+is_pythontag=re.compile('^py[0-9]{2}$') -+ -+def set_options(opt): -+ opt.add_option('--boost-includes', type='string', default='', dest='boostincludes', help='path to the boost directory where the includes are e.g. /usr/local/include/boost-1_35') -+ opt.add_option('--boost-libs', type='string', default='', dest='boostlibs', help='path to the directory where the boost libs are e.g. /usr/local/lib') -+ -+def string_to_version(s): -+ version = s.split('.') -+ if len(version) < 3: return 0 -+ return int(version[0])*100000 + int(version[1])*100 + int(version[2]) -+ -+def version_string(version): -+ major = version / 100000 -+ minor = version / 100 % 1000 -+ minor_minor = version % 100 -+ if minor_minor == 0: -+ return "%d_%d" % (major, minor) -+ else: -+ return "%d_%d_%d" % (major, minor, minor_minor) -+ -+def libfiles(lib, pattern, lib_paths): -+ result = [] -+ for lib_path in lib_paths: -+ libname = pattern % ('boost_%s[!_]*' % lib) -+ result += glob.glob(os.path.join(lib_path, libname)) -+ return result -+ -+@conf -+def get_boost_version_number(self, dir): -+ """silently retrieve the boost version number""" -+ try: -+ return self.run_c_code(compiler='cxx', code=boost_code, includes=dir, execute=1, env=self.env.copy(), type='cprogram', compile_mode='cxx', compile_filename='test.cpp') -+ except Configure.ConfigurationError, e: -+ return -1 -+ -+def set_default(kw, var, val): -+ if not var in kw: -+ kw[var] = val -+ -+def tags_score(tags, kw): -+ """ -+ checks library tags -+ -+ see http://www.boost.org/doc/libs/1_35_0/more/getting_started/unix-variants.html 6.1 -+ """ -+ score = 0 -+ needed_tags = { -+ 'threading': kw['tag_threading'], -+ 'abi': kw['tag_abi'], -+ 'toolset': kw['tag_toolset'], -+ 'version': kw['tag_version'], -+ 'python': kw['tag_python'] -+ } -+ -+ if kw['tag_toolset'] is None: -+ v = kw['env'] -+ toolset = v['CXX_NAME'] -+ if v['CXX_VERSION']: -+ version_no = v['CXX_VERSION'].split('.') -+ toolset += version_no[0] -+ if len(version_no) > 1: -+ toolset += version_no[1] -+ needed_tags['toolset'] = toolset -+ -+ found_tags = {} -+ for tag in tags: -+ if is_versiontag.match(tag): found_tags['version'] = tag -+ if is_threadingtag.match(tag): found_tags['threading'] = tag -+ if is_abitag.match(tag): found_tags['abi'] = tag -+ if is_toolsettag.match(tag): found_tags['toolset'] = tag -+ if is_pythontag.match(tag): found_tags['python'] = tag -+ -+ for tagname in needed_tags.iterkeys(): -+ if needed_tags[tagname] is not None and tagname in found_tags: -+ if re.compile(needed_tags[tagname]).match(found_tags[tagname]): -+ score += kw['score_' + tagname][0] -+ else: -+ score += kw['score_' + tagname][1] -+ return score -+ -+@conf -+def validate_boost(self, kw): -+ ver = kw.get('version', '') -+ -+ for x in 'min_version max_version version'.split(): -+ set_default(kw, x, ver) -+ -+ set_default(kw, 'lib', '') -+ kw['lib'] = Utils.to_list(kw['lib']) -+ -+ set_default(kw, 'env', self.env) -+ -+ set_default(kw, 'libpath', boost_libpath) -+ set_default(kw, 'cpppath', boost_cpppath) -+ -+ for x in 'tag_threading tag_version tag_toolset'.split(): -+ set_default(kw, x, None) -+ set_default(kw, 'tag_abi', '^[^d]*$') -+ -+ set_default(kw, 'python', str(sys.version_info[0]) + str(sys.version_info[1]) ) -+ set_default(kw, 'tag_python', '^py' + kw['python'] + '$') -+ -+ set_default(kw, 'score_threading', (10, -10)) -+ set_default(kw, 'score_abi', (10, -10)) -+ set_default(kw, 'score_python', (10,-10)) -+ set_default(kw, 'score_toolset', (1, -1)) -+ set_default(kw, 'score_version', (100, -100)) -+ -+ set_default(kw, 'score_min', 0) -+ set_default(kw, 'static', STATIC_NOSTATIC) -+ set_default(kw, 'found_includes', False) -+ set_default(kw, 'min_score', 0) -+ -+ set_default(kw, 'errmsg', 'not found') -+ set_default(kw, 'okmsg', 'ok') -+ -+@conf -+def find_boost_includes(self, kw): -+ """ -+ check every path in kw['cpppath'] for subdir -+ that either starts with boost- or is named boost. -+ -+ Then the version is checked and selected accordingly to -+ min_version/max_version. The highest possible version number is -+ selected! -+ -+ If no versiontag is set the versiontag is set accordingly to the -+ selected library and CPPPATH_BOOST is set. -+ """ -+ boostPath = getattr(Options.options, 'boostincludes', '') -+ if boostPath: -+ boostPath = [os.path.normpath(os.path.expandvars(os.path.expanduser(boostPath)))] -+ else: -+ boostPath = Utils.to_list(kw['cpppath']) -+ -+ min_version = string_to_version(kw.get('min_version', '')) -+ max_version = string_to_version(kw.get('max_version', '')) or (sys.maxint - 1) -+ -+ version = 0 -+ for include_path in boostPath: -+ boost_paths = [p for p in glob.glob(os.path.join(include_path, 'boost*')) if os.path.isdir(p)] -+ debug('BOOST Paths: %r' % boost_paths) -+ for path in boost_paths: -+ pathname = os.path.split(path)[-1] -+ ret = -1 -+ if pathname == 'boost': -+ path = include_path -+ ret = self.get_boost_version_number(path) -+ elif pathname.startswith('boost-'): -+ ret = self.get_boost_version_number(path) -+ ret = int(ret) -+ -+ if ret != -1 and ret >= min_version and ret <= max_version and ret > version: -+ boost_path = path -+ version = ret -+ if not version: -+ self.fatal('boost headers not found! (required version min: %s max: %s)' -+ % (kw['min_version'], kw['max_version'])) -+ return False -+ -+ found_version = version_string(version) -+ versiontag = '^' + found_version + '$' -+ if kw['tag_version'] is None: -+ kw['tag_version'] = versiontag -+ elif kw['tag_version'] != versiontag: -+ warn('boost header version %r and tag_version %r do not match!' % (versiontag, kw['tag_version'])) -+ env = self.env -+ env['CPPPATH_BOOST'] = boost_path -+ env['BOOST_VERSION'] = found_version -+ self.found_includes = 1 -+ ret = 'Version %s (%s)' % (found_version, boost_path) -+ return ret -+ -+@conf -+def find_boost_library(self, lib, kw): -+ -+ def find_library_from_list(lib, files): -+ lib_pattern = re.compile('.*boost_(.*?)\..*') -+ result = (None, None) -+ resultscore = kw['min_score'] - 1 -+ for file in files: -+ m = lib_pattern.search(file, 1) -+ if m: -+ libname = m.group(1) -+ libtags = libname.split('-')[1:] -+ currentscore = tags_score(libtags, kw) -+ if currentscore > resultscore: -+ result = (libname, file) -+ resultscore = currentscore -+ return result -+ -+ lib_paths = getattr(Options.options, 'boostlibs', '') -+ if lib_paths: -+ lib_paths = [os.path.normpath(os.path.expandvars(os.path.expanduser(lib_paths)))] -+ else: -+ lib_paths = Utils.to_list(kw['libpath']) -+ -+ v = kw.get('env', self.env) -+ -+ (libname, file) = (None, None) -+ if kw['static'] in [STATIC_NOSTATIC, STATIC_BOTH]: -+ st_env_prefix = 'LIB' -+ files = libfiles(lib, v['shlib_PATTERN'], lib_paths) -+ (libname, file) = find_library_from_list(lib, files) -+ if libname is None and kw['static'] in [STATIC_ONLYSTATIC, STATIC_BOTH]: -+ st_env_prefix = 'STATICLIB' -+ staticLibPattern = v['staticlib_PATTERN'] -+ if self.env['CC_NAME'] == 'msvc': -+ staticLibPattern = 'lib' + staticLibPattern -+ files = libfiles(lib, staticLibPattern, lib_paths) -+ (libname, file) = find_library_from_list(lib, files) -+ if libname is not None: -+ v['LIBPATH_BOOST_' + lib.upper()] = [os.path.split(file)[0]] -+ if self.env['CC_NAME'] == 'msvc' and os.path.splitext(file)[1] == '.lib': -+ v[st_env_prefix + '_BOOST_' + lib.upper()] = ['libboost_'+libname] -+ else: -+ v[st_env_prefix + '_BOOST_' + lib.upper()] = ['boost_'+libname] -+ return -+ self.fatal('lib boost_' + lib + ' not found!') -+ -+@conf -+def check_boost(self, *k, **kw): -+ """ -+ This should be the main entry point -+ -+- min_version -+- max_version -+- version -+- include_path -+- lib_path -+- lib -+- toolsettag - None or a regexp -+- threadingtag - None or a regexp -+- abitag - None or a regexp -+- versiontag - WARNING: you should rather use version or min_version/max_version -+- static - look for static libs (values: -+ 'nostatic' or STATIC_NOSTATIC - ignore static libs (default) -+ 'both' or STATIC_BOTH - find static libs, too -+ 'onlystatic' or STATIC_ONLYSTATIC - find only static libs -+- score_version -+- score_abi -+- scores_threading -+- score_toolset -+ * the scores are tuples (match_score, nomatch_score) -+ match_score is the added to the score if the tag is matched -+ nomatch_score is added when a tag is found and does not match -+- min_score -+ """ -+ -+ if not self.env['CXX']: -+ self.fatal('load a c++ compiler tool first, for example conf.check_tool("g++")') -+ self.validate_boost(kw) -+ ret = None -+ try: -+ if not kw.get('found_includes', None): -+ self.check_message_1(kw.get('msg_includes', 'boost headers')) -+ ret = self.find_boost_includes(kw) -+ -+ except Configure.ConfigurationError, e: -+ if 'errmsg' in kw: -+ self.check_message_2(kw['errmsg'], 'YELLOW') -+ if 'mandatory' in kw: -+ if Logs.verbose > 1: -+ raise -+ else: -+ self.fatal('the configuration failed (see %r)' % self.log.name) -+ else: -+ if 'okmsg' in kw: -+ self.check_message_2(kw.get('okmsg_includes', ret)) -+ -+ for lib in kw['lib']: -+ self.check_message_1('library boost_'+lib) -+ try: -+ self.find_boost_library(lib, kw) -+ except Configure.ConfigurationError, e: -+ ret = False -+ if 'errmsg' in kw: -+ self.check_message_2(kw['errmsg'], 'YELLOW') -+ if 'mandatory' in kw: -+ if Logs.verbose > 1: -+ raise -+ else: -+ self.fatal('the configuration failed (see %r)' % self.log.name) -+ else: -+ if 'okmsg' in kw: -+ self.check_message_2(kw['okmsg']) -+ -+ return ret -+ -diff --git a/buildtools/wafadmin/3rdparty/fluid.py b/buildtools/wafadmin/3rdparty/fluid.py -new file mode 100644 -index 0000000..117edef ---- /dev/null -+++ b/buildtools/wafadmin/3rdparty/fluid.py -@@ -0,0 +1,27 @@ -+#!/usr/bin/python -+# encoding: utf-8 -+# Grygoriy Fuchedzhy 2009 -+ -+""" -+Compile fluid files (fltk graphic library). Use the 'fluid' feature in conjuction with the 'cxx' feature. -+""" -+ -+import Task -+from TaskGen import extension -+ -+Task.simple_task_type('fluid', '${FLUID} -c -o ${TGT[0].abspath(env)} -h ${TGT[1].abspath(env)} ${SRC}', 'BLUE', shell=False, ext_out='.cxx') -+ -+@extension('.fl') -+def fluid(self, node): -+ """add the .fl to the source list; the cxx file generated will be compiled when possible""" -+ cpp = node.change_ext('.cpp') -+ hpp = node.change_ext('.hpp') -+ self.create_task('fluid', node, [cpp, hpp]) -+ -+ if 'cxx' in self.features: -+ self.allnodes.append(cpp) -+ -+def detect(conf): -+ fluid = conf.find_program('fluid', var='FLUID', mandatory=True) -+ conf.check_cfg(path='fltk-config', package='', args='--cxxflags --ldflags', uselib_store='FLTK', mandatory=True) -+ -diff --git a/buildtools/wafadmin/3rdparty/gccdeps.py b/buildtools/wafadmin/3rdparty/gccdeps.py -new file mode 100644 -index 0000000..6600c9c ---- /dev/null -+++ b/buildtools/wafadmin/3rdparty/gccdeps.py -@@ -0,0 +1,128 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2008-2010 (ita) -+ -+""" -+Execute the tasks with gcc -MD, read the dependencies from the .d file -+and prepare the dependency calculation for the next run -+""" -+ -+import os, re, threading -+import Task, Logs, Utils, preproc -+from TaskGen import before, after, feature -+ -+lock = threading.Lock() -+ -+preprocessor_flag = '-MD' -+ -+@feature('cc') -+@before('apply_core') -+def add_mmd_cc(self): -+ if self.env.get_flat('CCFLAGS').find(preprocessor_flag) < 0: -+ self.env.append_value('CCFLAGS', preprocessor_flag) -+ -+@feature('cxx') -+@before('apply_core') -+def add_mmd_cxx(self): -+ if self.env.get_flat('CXXFLAGS').find(preprocessor_flag) < 0: -+ self.env.append_value('CXXFLAGS', preprocessor_flag) -+ -+def scan(self): -+ "the scanner does not do anything initially" -+ nodes = self.generator.bld.node_deps.get(self.unique_id(), []) -+ names = [] -+ return (nodes, names) -+ -+re_o = re.compile("\.o$") -+re_src = re.compile("^(\.\.)[\\/](.*)$") -+ -+def post_run(self): -+ # The following code is executed by threads, it is not safe, so a lock is needed... -+ -+ if getattr(self, 'cached', None): -+ return Task.Task.post_run(self) -+ -+ name = self.outputs[0].abspath(self.env) -+ name = re_o.sub('.d', name) -+ txt = Utils.readf(name) -+ #os.unlink(name) -+ -+ txt = txt.replace('\\\n', '') -+ -+ lst = txt.strip().split(':') -+ val = ":".join(lst[1:]) -+ val = val.split() -+ -+ nodes = [] -+ bld = self.generator.bld -+ -+ f = re.compile("^("+self.env.variant()+"|\.\.)[\\/](.*)$") -+ for x in val: -+ if os.path.isabs(x): -+ -+ if not preproc.go_absolute: -+ continue -+ -+ lock.acquire() -+ try: -+ node = bld.root.find_resource(x) -+ finally: -+ lock.release() -+ else: -+ g = re.search(re_src, x) -+ if g: -+ x = g.group(2) -+ lock.acquire() -+ try: -+ node = bld.bldnode.parent.find_resource(x) -+ finally: -+ lock.release() -+ else: -+ g = re.search(f, x) -+ if g: -+ x = g.group(2) -+ lock.acquire() -+ try: -+ node = bld.srcnode.find_resource(x) -+ finally: -+ lock.release() -+ -+ if id(node) == id(self.inputs[0]): -+ # ignore the source file, it is already in the dependencies -+ # this way, successful config tests may be retrieved from the cache -+ continue -+ -+ if not node: -+ raise ValueError('could not find %r for %r' % (x, self)) -+ else: -+ nodes.append(node) -+ -+ Logs.debug('deps: real scanner for %s returned %s' % (str(self), str(nodes))) -+ -+ bld.node_deps[self.unique_id()] = nodes -+ bld.raw_deps[self.unique_id()] = [] -+ -+ try: -+ del self.cache_sig -+ except: -+ pass -+ -+ Task.Task.post_run(self) -+ -+import Constants, Utils -+def sig_implicit_deps(self): -+ try: -+ return Task.Task.sig_implicit_deps(self) -+ except Utils.WafError: -+ return Constants.SIG_NIL -+ -+for name in 'cc cxx'.split(): -+ try: -+ cls = Task.TaskBase.classes[name] -+ except KeyError: -+ pass -+ else: -+ cls.post_run = post_run -+ cls.scan = scan -+ cls.sig_implicit_deps = sig_implicit_deps -+ -diff --git a/buildtools/wafadmin/3rdparty/go.py b/buildtools/wafadmin/3rdparty/go.py -new file mode 100644 -index 0000000..2d8df0d ---- /dev/null -+++ b/buildtools/wafadmin/3rdparty/go.py -@@ -0,0 +1,111 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# go.py - Waf tool for the Go programming language -+# By: Tom Wambold -+ -+import platform, os -+ -+import Task -+import Utils -+from TaskGen import feature, extension, after -+ -+Task.simple_task_type('gocompile', '${GOC} ${GOCFLAGS} -o ${TGT} ${SRC}', shell=False) -+Task.simple_task_type('gopack', '${GOP} grc ${TGT} ${SRC}', shell=False) -+Task.simple_task_type('golink', '${GOL} ${GOLFLAGS} -o ${TGT} ${SRC}', shell=False) -+ -+def detect(conf): -+ -+ def set_def(var, val): -+ if not conf.env[var]: -+ conf.env[var] = val -+ -+ goarch = os.getenv("GOARCH") -+ -+ if goarch == '386': -+ set_def('GO_PLATFORM', 'i386') -+ elif goarch == 'amd64': -+ set_def('GO_PLATFORM', 'x86_64') -+ elif goarch == 'arm': -+ set_def('GO_PLATFORM', 'arm') -+ else: -+ set_def('GO_PLATFORM', platform.machine()) -+ -+ if conf.env.GO_PLATFORM == 'x86_64': -+ set_def('GO_COMPILER', '6g') -+ set_def('GO_LINKER', '6l') -+ set_def('GO_EXTENSION', '.6') -+ elif conf.env.GO_PLATFORM in ['i386', 'i486', 'i586', 'i686']: -+ set_def('GO_COMPILER', '8g') -+ set_def('GO_LINKER', '8l') -+ set_def('GO_EXTENSION', '.8') -+ elif conf.env.GO_PLATFORM == 'arm': -+ set_def('GO_COMPILER', '5g') -+ set_def('GO_LINKER', '5l') -+ set_def('GO_EXTENSION', '.5') -+ -+ if not (conf.env.GO_COMPILER or conf.env.GO_LINKER or conf.env.GO_EXTENSION): -+ raise conf.fatal('Unsupported platform ' + platform.machine()) -+ -+ set_def('GO_PACK', 'gopack') -+ set_def('GO_PACK_EXTENSION', '.a') -+ -+ conf.find_program(conf.env.GO_COMPILER, var='GOC', mandatory=True) -+ conf.find_program(conf.env.GO_LINKER, var='GOL', mandatory=True) -+ conf.find_program(conf.env.GO_PACK, var='GOP', mandatory=True) -+ conf.find_program('cgo', var='CGO', mandatory=True) -+ -+@extension('.go') -+def compile_go(self, node): -+ try: -+ self.go_nodes.append(node) -+ except AttributeError: -+ self.go_nodes = [node] -+ -+@feature('go') -+@after('apply_core') -+def apply_compile_go(self): -+ try: -+ nodes = self.go_nodes -+ except AttributeError: -+ self.go_compile_task = None -+ else: -+ self.go_compile_task = self.create_task('gocompile', -+ nodes, -+ [self.path.find_or_declare(self.target + self.env.GO_EXTENSION)]) -+ -+@feature('gopackage', 'goprogram') -+@after('apply_compile_go') -+def apply_goinc(self): -+ if not getattr(self, 'go_compile_task', None): -+ return -+ -+ names = self.to_list(getattr(self, 'uselib_local', [])) -+ for name in names: -+ obj = self.name_to_obj(name) -+ if not obj: -+ raise Utils.WafError('object %r was not found in uselib_local ' -+ '(required by %r)' % (lib_name, self.name)) -+ obj.post() -+ self.go_compile_task.set_run_after(obj.go_package_task) -+ self.go_compile_task.dep_nodes.extend(obj.go_package_task.outputs) -+ self.env.append_unique('GOCFLAGS', '-I' + obj.path.abspath(obj.env)) -+ self.env.append_unique('GOLFLAGS', '-L' + obj.path.abspath(obj.env)) -+ -+@feature('gopackage') -+@after('apply_goinc') -+def apply_gopackage(self): -+ self.go_package_task = self.create_task('gopack', -+ self.go_compile_task.outputs[0], -+ self.path.find_or_declare(self.target + self.env.GO_PACK_EXTENSION)) -+ self.go_package_task.set_run_after(self.go_compile_task) -+ self.go_package_task.dep_nodes.extend(self.go_compile_task.outputs) -+ -+@feature('goprogram') -+@after('apply_goinc') -+def apply_golink(self): -+ self.go_link_task = self.create_task('golink', -+ self.go_compile_task.outputs[0], -+ self.path.find_or_declare(self.target)) -+ self.go_link_task.set_run_after(self.go_compile_task) -+ self.go_link_task.dep_nodes.extend(self.go_compile_task.outputs) -+ -diff --git a/buildtools/wafadmin/3rdparty/lru_cache.py b/buildtools/wafadmin/3rdparty/lru_cache.py -new file mode 100644 -index 0000000..5b00abc ---- /dev/null -+++ b/buildtools/wafadmin/3rdparty/lru_cache.py -@@ -0,0 +1,97 @@ -+#! /usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy 2011 -+ -+import os, shutil, re -+import Options, Build, Logs -+ -+""" -+Apply a least recently used policy to the Waf cache. -+ -+For performance reasons, it is called after the build is complete. -+ -+We assume that the the folders are written atomically -+ -+Do export WAFCACHE=/tmp/foo-xyz where xyz represents the cache size in megabytes -+If missing, the default cache size will be set to 10GB -+""" -+ -+re_num = re.compile('[a-zA-Z_]+(\d+)') -+ -+CACHESIZE = 10*1024*1024*1024 # in bytes -+CLEANRATIO = 0.8 -+DIRSIZE = 4096 -+ -+def compile(self): -+ if Options.cache_global and not Options.options.nocache: -+ try: -+ os.makedirs(Options.cache_global) -+ except: -+ pass -+ -+ try: -+ self.raw_compile() -+ finally: -+ if Options.cache_global and not Options.options.nocache: -+ self.sweep() -+ -+def sweep(self): -+ global CACHESIZE -+ CACHEDIR = Options.cache_global -+ -+ # get the cache max size from the WAFCACHE filename -+ re_num = re.compile('[a-zA-Z_]+(\d+)') -+ val = re_num.sub('\\1', os.path.basename(Options.cache_global)) -+ try: -+ CACHESIZE = int(val) -+ except: -+ pass -+ -+ # map folder names to timestamps -+ flist = {} -+ for x in os.listdir(CACHEDIR): -+ j = os.path.join(CACHEDIR, x) -+ if os.path.isdir(j) and len(x) == 32: # dir names are md5 hexdigests -+ flist[x] = [os.stat(j).st_mtime, 0] -+ -+ for (x, v) in flist.items(): -+ cnt = DIRSIZE # each entry takes 4kB -+ d = os.path.join(CACHEDIR, x) -+ for k in os.listdir(d): -+ cnt += os.stat(os.path.join(d, k)).st_size -+ flist[x][1] = cnt -+ -+ total = sum([x[1] for x in flist.values()]) -+ Logs.debug('lru: Cache size is %r' % total) -+ -+ if total >= CACHESIZE: -+ Logs.debug('lru: Trimming the cache since %r > %r' % (total, CACHESIZE)) -+ -+ # make a list to sort the folders by timestamp -+ lst = [(p, v[0], v[1]) for (p, v) in flist.items()] -+ lst.sort(key=lambda x: x[1]) # sort by timestamp -+ lst.reverse() -+ -+ while total >= CACHESIZE * CLEANRATIO: -+ (k, t, s) = lst.pop() -+ p = os.path.join(CACHEDIR, k) -+ v = p + '.del' -+ try: -+ os.rename(p, v) -+ except: -+ # someone already did it -+ pass -+ else: -+ try: -+ shutil.rmtree(v) -+ except: -+ # this should not happen, but who knows? -+ Logs.warn('If you ever see this message, report it (%r)' % v) -+ total -= s -+ del flist[k] -+ Logs.debug('lru: Total at the end %r' % total) -+ -+Build.BuildContext.raw_compile = Build.BuildContext.compile -+Build.BuildContext.compile = compile -+Build.BuildContext.sweep = sweep -+ -diff --git a/buildtools/wafadmin/3rdparty/paranoid.py b/buildtools/wafadmin/3rdparty/paranoid.py -new file mode 100644 -index 0000000..ead64ea ---- /dev/null -+++ b/buildtools/wafadmin/3rdparty/paranoid.py -@@ -0,0 +1,35 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# ita 2010 -+ -+import Logs, Utils, Build, Task -+ -+def say(txt): -+ Logs.warn("^o^: %s" % txt) -+ -+try: -+ ret = Utils.cmd_output('which cowsay 2> /dev/null').strip() -+except Exception, e: -+ pass -+else: -+ def say(txt): -+ f = Utils.cmd_output([ret, txt]) -+ Utils.pprint('PINK', f) -+ -+say('you make the errors, we detect them') -+ -+def check_task_classes(self): -+ for x in Task.TaskBase.classes: -+ if isinstance(x, Task.Task): -+ if not getattr(cls, 'ext_in', None) or getattr(cls, 'before', None): -+ say('class %s has no precedence constraints (ext_in/before)') -+ if not getattr(cls, 'ext_out', None) or getattr(cls, 'after', None): -+ say('class %s has no precedence constraints (ext_out/after)') -+ -+comp = Build.BuildContext.compile -+def compile(self): -+ if not getattr(self, 'magic', None): -+ check_task_classes(self) -+ return comp(self) -+Build.BuildContext.compile = compile -+ -diff --git a/buildtools/wafadmin/3rdparty/swig.py b/buildtools/wafadmin/3rdparty/swig.py -new file mode 100644 -index 0000000..c0a4108 ---- /dev/null -+++ b/buildtools/wafadmin/3rdparty/swig.py -@@ -0,0 +1,190 @@ -+#! /usr/bin/env python -+# encoding: UTF-8 -+# Petar Forai -+# Thomas Nagy 2008 -+ -+import re -+import Task, Utils, Logs -+from TaskGen import extension -+from Configure import conf -+import preproc -+ -+""" -+Welcome in the hell of adding tasks dynamically -+ -+swig interface files may be created at runtime, the module name may be unknown in advance -+ -+rev 5859 is much more simple -+""" -+ -+SWIG_EXTS = ['.swig', '.i'] -+ -+swig_str = '${SWIG} ${SWIGFLAGS} ${_CCINCFLAGS} ${_CXXINCFLAGS} ${_CCDEFFLAGS} ${_CXXDEFFLAGS} ${SRC}' -+cls = Task.simple_task_type('swig', swig_str, color='BLUE', ext_in='.i .h', ext_out='.o .c .cxx', shell=False) -+ -+def runnable_status(self): -+ for t in self.run_after: -+ if not t.hasrun: -+ return ASK_LATER -+ -+ if not getattr(self, 'init_outputs', None): -+ self.init_outputs = True -+ if not getattr(self, 'module', None): -+ # search the module name -+ txt = self.inputs[0].read(self.env) -+ m = re_module.search(txt) -+ if not m: -+ raise ValueError("could not find the swig module name") -+ self.module = m.group(1) -+ -+ swig_c(self) -+ -+ # add the language-specific output files as nodes -+ # call funs in the dict swig_langs -+ for x in self.env['SWIGFLAGS']: -+ # obtain the language -+ x = x[1:] -+ try: -+ fun = swig_langs[x] -+ except KeyError: -+ pass -+ else: -+ fun(self) -+ -+ return Task.Task.runnable_status(self) -+setattr(cls, 'runnable_status', runnable_status) -+ -+re_module = re.compile('%module(?:\s*\(.*\))?\s+(.+)', re.M) -+ -+re_1 = re.compile(r'^%module.*?\s+([\w]+)\s*?$', re.M) -+re_2 = re.compile('%include "(.*)"', re.M) -+re_3 = re.compile('#include "(.*)"', re.M) -+ -+def scan(self): -+ "scan for swig dependencies, climb the .i files" -+ env = self.env -+ -+ lst_src = [] -+ -+ seen = [] -+ to_see = [self.inputs[0]] -+ -+ while to_see: -+ node = to_see.pop(0) -+ if node.id in seen: -+ continue -+ seen.append(node.id) -+ lst_src.append(node) -+ -+ # read the file -+ code = node.read(env) -+ code = preproc.re_nl.sub('', code) -+ code = preproc.re_cpp.sub(preproc.repl, code) -+ -+ # find .i files and project headers -+ names = re_2.findall(code) + re_3.findall(code) -+ for n in names: -+ for d in self.generator.env.INC_PATHS + [node.parent]: -+ u = d.find_resource(n) -+ if u: -+ to_see.append(u) -+ break -+ else: -+ Logs.warn('could not find %r' % n) -+ -+ # list of nodes this one depends on, and module name if present -+ if Logs.verbose: -+ Logs.debug('deps: deps for %s: %s' % (str(self), str(lst_src))) -+ return (lst_src, []) -+cls.scan = scan -+ -+# provide additional language processing -+swig_langs = {} -+def swig(fun): -+ swig_langs[fun.__name__.replace('swig_', '')] = fun -+ -+def swig_c(self): -+ ext = '.swigwrap_%d.c' % self.generator.idx -+ flags = self.env['SWIGFLAGS'] -+ if '-c++' in flags: -+ ext += 'xx' -+ out_node = self.inputs[0].parent.find_or_declare(self.module + ext) -+ -+ try: -+ if '-c++' in flags: -+ fun = self.generator.cxx_hook -+ else: -+ fun = self.generator.c_hook -+ except AttributeError: -+ raise Utils.WafError('No c%s compiler was found to process swig files' % ('-c++' in flags and '++' or '')) -+ -+ task = fun(out_node) -+ task.set_run_after(self) -+ -+ ge = self.generator.bld.generator -+ ge.outstanding.insert(0, task) -+ ge.total += 1 -+ -+ try: -+ ltask = self.generator.link_task -+ except AttributeError: -+ pass -+ else: -+ ltask.inputs.append(task.outputs[0]) -+ -+ self.outputs.append(out_node) -+ -+ if not '-o' in self.env['SWIGFLAGS']: -+ self.env.append_value('SWIGFLAGS', '-o') -+ self.env.append_value('SWIGFLAGS', self.outputs[0].abspath(self.env)) -+ -+@swig -+def swig_python(tsk): -+ tsk.set_outputs(tsk.inputs[0].parent.find_or_declare(tsk.module + '.py')) -+ -+@swig -+def swig_ocaml(tsk): -+ tsk.set_outputs(tsk.inputs[0].parent.find_or_declare(tsk.module + '.ml')) -+ tsk.set_outputs(tsk.inputs[0].parent.find_or_declare(tsk.module + '.mli')) -+ -+@extension(SWIG_EXTS) -+def i_file(self, node): -+ # the task instance -+ tsk = self.create_task('swig') -+ tsk.set_inputs(node) -+ tsk.module = getattr(self, 'swig_module', None) -+ -+ flags = self.to_list(getattr(self, 'swig_flags', [])) -+ self.env.append_value('SWIGFLAGS', flags) -+ -+ if not '-outdir' in flags: -+ flags.append('-outdir') -+ flags.append(node.parent.abspath(self.env)) -+ -+@conf -+def check_swig_version(conf, minver=None): -+ """Check for a minimum swig version like conf.check_swig_version('1.3.28') -+ or conf.check_swig_version((1,3,28)) """ -+ reg_swig = re.compile(r'SWIG Version\s(.*)', re.M) -+ -+ swig_out = Utils.cmd_output('%s -version' % conf.env['SWIG']) -+ -+ swigver = [int(s) for s in reg_swig.findall(swig_out)[0].split('.')] -+ if isinstance(minver, basestring): -+ minver = [int(s) for s in minver.split(".")] -+ if isinstance(minver, tuple): -+ minver = [int(s) for s in minver] -+ result = (minver is None) or (minver[:3] <= swigver[:3]) -+ swigver_full = '.'.join(map(str, swigver)) -+ if result: -+ conf.env['SWIG_VERSION'] = swigver_full -+ minver_str = '.'.join(map(str, minver)) -+ if minver is None: -+ conf.check_message_custom('swig version', '', swigver_full) -+ else: -+ conf.check_message('swig version', '>= %s' % (minver_str,), result, option=swigver_full) -+ return result -+ -+def detect(conf): -+ swig = conf.find_program('swig', var='SWIG', mandatory=True) -+ -diff --git a/buildtools/wafadmin/3rdparty/valadoc.py b/buildtools/wafadmin/3rdparty/valadoc.py -new file mode 100644 -index 0000000..d0a9fe8 ---- /dev/null -+++ b/buildtools/wafadmin/3rdparty/valadoc.py -@@ -0,0 +1,113 @@ -+#! /usr/bin/env python -+# encoding: UTF-8 -+# Nicolas Joseph 2009 -+ -+from fnmatch import fnmatchcase -+import os, os.path, re, stat -+import Task, Utils, Node, Constants -+from TaskGen import feature, extension, after -+from Logs import debug, warn, error -+ -+VALADOC_STR = '${VALADOC}' -+ -+class valadoc_task(Task.Task): -+ -+ vars = ['VALADOC', 'VALADOCFLAGS'] -+ color = 'BLUE' -+ after = 'cxx_link cc_link' -+ quiet = True -+ -+ output_dir = '' -+ doclet = '' -+ package_name = '' -+ package_version = '' -+ files = [] -+ protected = True -+ private = False -+ inherit = False -+ deps = False -+ enable_non_null_experimental = False -+ force = False -+ -+ def runnable_status(self): -+ return True -+ -+ def run(self): -+ if self.env['VALADOC']: -+ if not self.env['VALADOCFLAGS']: -+ self.env['VALADOCFLAGS'] = '' -+ cmd = [Utils.subst_vars(VALADOC_STR, self.env)] -+ cmd.append ('-o %s' % self.output_dir) -+ if getattr(self, 'doclet', None): -+ cmd.append ('--doclet %s' % self.doclet) -+ cmd.append ('--package-name %s' % self.package_name) -+ if getattr(self, 'version', None): -+ cmd.append ('--package-version %s' % self.package_version) -+ if getattr(self, 'packages', None): -+ for package in self.packages: -+ cmd.append ('--pkg %s' % package) -+ if getattr(self, 'vapi_dirs', None): -+ for vapi_dir in self.vapi_dirs: -+ cmd.append ('--vapidir %s' % vapi_dir) -+ if not getattr(self, 'protected', None): -+ cmd.append ('--no-protected') -+ if getattr(self, 'private', None): -+ cmd.append ('--private') -+ if getattr(self, 'inherit', None): -+ cmd.append ('--inherit') -+ if getattr(self, 'deps', None): -+ cmd.append ('--deps') -+ if getattr(self, 'enable_non_null_experimental', None): -+ cmd.append ('--enable-non-null-experimental') -+ if getattr(self, 'force', None): -+ cmd.append ('--force') -+ cmd.append (' '.join ([x.relpath_gen (self.generator.bld.bldnode) for x in self.files])) -+ return self.generator.bld.exec_command(' '.join(cmd)) -+ else: -+ error ('You must install valadoc for generate the API documentation') -+ return -1 -+ -+@feature('valadoc') -+def process_valadoc(self): -+ task = getattr(self, 'task', None) -+ if not task: -+ task = self.create_task('valadoc') -+ self.task = task -+ if getattr(self, 'output_dir', None): -+ task.output_dir = self.output_dir -+ else: -+ Utils.WafError('no output directory') -+ if getattr(self, 'doclet', None): -+ task.doclet = self.doclet -+ else: -+ Utils.WafError('no doclet directory') -+ if getattr(self, 'package_name', None): -+ task.package_name = self.package_name -+ else: -+ Utils.WafError('no package name') -+ if getattr(self, 'package_version', None): -+ task.package_version = self.package_version -+ if getattr(self, 'packages', None): -+ task.packages = Utils.to_list(self.packages) -+ if getattr(self, 'vapi_dirs', None): -+ task.vapi_dirs = Utils.to_list(self.vapi_dirs) -+ if getattr(self, 'files', None): -+ task.files = self.files -+ else: -+ Utils.WafError('no input file') -+ if getattr(self, 'protected', None): -+ task.protected = self.protected -+ if getattr(self, 'private', None): -+ task.private = self.private -+ if getattr(self, 'inherit', None): -+ task.inherit = self.inherit -+ if getattr(self, 'deps', None): -+ task.deps = self.deps -+ if getattr(self, 'enable_non_null_experimental', None): -+ task.enable_non_null_experimental = self.enable_non_null_experimental -+ if getattr(self, 'force', None): -+ task.force = self.force -+ -+def detect(conf): -+ conf.find_program('valadoc', var='VALADOC', mandatory=False) -+ -diff --git a/buildtools/wafadmin/Build.py b/buildtools/wafadmin/Build.py -new file mode 100644 -index 0000000..8e7c72c ---- /dev/null -+++ b/buildtools/wafadmin/Build.py -@@ -0,0 +1,1033 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2005 (ita) -+ -+""" -+Dependency tree holder -+ -+The class Build holds all the info related to a build: -+* file system representation (tree of Node instances) -+* various cached objects (task signatures, file scan results, ..) -+ -+There is only one Build object at a time (bld singleton) -+""" -+ -+import os, sys, errno, re, glob, gc, datetime, shutil -+try: import cPickle -+except: import pickle as cPickle -+import Runner, TaskGen, Node, Scripting, Utils, Environment, Task, Logs, Options -+from Logs import debug, error, info -+from Constants import * -+ -+SAVED_ATTRS = 'root srcnode bldnode node_sigs node_deps raw_deps task_sigs id_nodes'.split() -+"Build class members to save" -+ -+bld = None -+"singleton - safe to use when Waf is not used as a library" -+ -+class BuildError(Utils.WafError): -+ def __init__(self, b=None, t=[]): -+ self.bld = b -+ self.tasks = t -+ self.ret = 1 -+ Utils.WafError.__init__(self, self.format_error()) -+ -+ def format_error(self): -+ lst = ['Build failed:'] -+ for tsk in self.tasks: -+ txt = tsk.format_error() -+ if txt: lst.append(txt) -+ sep = ' ' -+ if len(lst) > 2: -+ sep = '\n' -+ return sep.join(lst) -+ -+def group_method(fun): -+ """ -+ sets a build context method to execute after the current group has finished executing -+ this is useful for installing build files: -+ * calling install_files/install_as will fail if called too early -+ * people do not want to define install method in their task classes -+ -+ TODO: try it -+ """ -+ def f(*k, **kw): -+ if not k[0].is_install: -+ return False -+ -+ postpone = True -+ if 'postpone' in kw: -+ postpone = kw['postpone'] -+ del kw['postpone'] -+ -+ # TODO waf 1.6 in theory there should be no reference to the TaskManager internals here -+ if postpone: -+ m = k[0].task_manager -+ if not m.groups: m.add_group() -+ m.groups[m.current_group].post_funs.append((fun, k, kw)) -+ if not 'cwd' in kw: -+ kw['cwd'] = k[0].path -+ else: -+ fun(*k, **kw) -+ return f -+ -+class BuildContext(Utils.Context): -+ "holds the dependency tree" -+ def __init__(self): -+ -+ # not a singleton, but provided for compatibility -+ global bld -+ bld = self -+ -+ self.task_manager = Task.TaskManager() -+ -+ # instead of hashing the nodes, we assign them a unique id when they are created -+ self.id_nodes = 0 -+ self.idx = {} -+ -+ # map names to environments, the 'default' must be defined -+ self.all_envs = {} -+ -+ # ======================================= # -+ # code for reading the scripts -+ -+ # project build directory - do not reset() from load_dirs() -+ self.bdir = '' -+ -+ # the current directory from which the code is run -+ # the folder changes everytime a wscript is read -+ self.path = None -+ -+ # Manual dependencies. -+ self.deps_man = Utils.DefaultDict(list) -+ -+ # ======================================= # -+ # cache variables -+ -+ # local cache for absolute paths - cache_node_abspath[variant][node] -+ self.cache_node_abspath = {} -+ -+ # list of folders that are already scanned -+ # so that we do not need to stat them one more time -+ self.cache_scanned_folders = {} -+ -+ # list of targets to uninstall for removing the empty folders after uninstalling -+ self.uninstall = [] -+ -+ # ======================================= # -+ # tasks and objects -+ -+ # build dir variants (release, debug, ..) -+ for v in 'cache_node_abspath task_sigs node_deps raw_deps node_sigs'.split(): -+ var = {} -+ setattr(self, v, var) -+ -+ self.cache_dir_contents = {} -+ -+ self.all_task_gen = [] -+ self.task_gen_cache_names = {} -+ self.cache_sig_vars = {} -+ self.log = None -+ -+ self.root = None -+ self.srcnode = None -+ self.bldnode = None -+ -+ # bind the build context to the nodes in use -+ # this means better encapsulation and no build context singleton -+ class node_class(Node.Node): -+ pass -+ self.node_class = node_class -+ self.node_class.__module__ = "Node" -+ self.node_class.__name__ = "Nodu" -+ self.node_class.bld = self -+ -+ self.is_install = None -+ -+ def __copy__(self): -+ "nodes are not supposed to be copied" -+ raise Utils.WafError('build contexts are not supposed to be cloned') -+ -+ def load(self): -+ "load the cache from the disk" -+ try: -+ env = Environment.Environment(os.path.join(self.cachedir, 'build.config.py')) -+ except (IOError, OSError): -+ pass -+ else: -+ if env['version'] < HEXVERSION: -+ raise Utils.WafError('Version mismatch! reconfigure the project') -+ for t in env['tools']: -+ self.setup(**t) -+ -+ try: -+ gc.disable() -+ f = data = None -+ -+ Node.Nodu = self.node_class -+ -+ try: -+ f = open(os.path.join(self.bdir, DBFILE), 'rb') -+ except (IOError, EOFError): -+ # handle missing file/empty file -+ pass -+ -+ try: -+ if f: data = cPickle.load(f) -+ except AttributeError: -+ # handle file of an old Waf version -+ # that has an attribute which no longer exist -+ # (e.g. AttributeError: 'module' object has no attribute 'BuildDTO') -+ if Logs.verbose > 1: raise -+ -+ if data: -+ for x in SAVED_ATTRS: setattr(self, x, data[x]) -+ else: -+ debug('build: Build cache loading failed') -+ -+ finally: -+ if f: f.close() -+ gc.enable() -+ -+ def save(self): -+ "store the cache on disk, see self.load" -+ gc.disable() -+ self.root.__class__.bld = None -+ -+ # some people are very nervous with ctrl+c so we have to make a temporary file -+ Node.Nodu = self.node_class -+ db = os.path.join(self.bdir, DBFILE) -+ file = open(db + '.tmp', 'wb') -+ data = {} -+ for x in SAVED_ATTRS: data[x] = getattr(self, x) -+ cPickle.dump(data, file, -1) -+ file.close() -+ -+ # do not use shutil.move -+ try: os.unlink(db) -+ except OSError: pass -+ os.rename(db + '.tmp', db) -+ self.root.__class__.bld = self -+ gc.enable() -+ -+ # ======================================= # -+ -+ def clean(self): -+ debug('build: clean called') -+ -+ # does not clean files created during the configuration -+ precious = set([]) -+ for env in self.all_envs.values(): -+ for x in env[CFG_FILES]: -+ node = self.srcnode.find_resource(x) -+ if node: -+ precious.add(node.id) -+ -+ def clean_rec(node): -+ for x in list(node.childs.keys()): -+ nd = node.childs[x] -+ -+ tp = nd.id & 3 -+ if tp == Node.DIR: -+ clean_rec(nd) -+ elif tp == Node.BUILD: -+ if nd.id in precious: continue -+ for env in self.all_envs.values(): -+ try: os.remove(nd.abspath(env)) -+ except OSError: pass -+ node.childs.__delitem__(x) -+ -+ clean_rec(self.srcnode) -+ -+ for v in 'node_sigs node_deps task_sigs raw_deps cache_node_abspath'.split(): -+ setattr(self, v, {}) -+ -+ def compile(self): -+ """The cache file is not written if nothing was build at all (build is up to date)""" -+ debug('build: compile called') -+ -+ """ -+ import cProfile, pstats -+ cProfile.run("import Build\nBuild.bld.flush()", 'profi.txt') -+ p = pstats.Stats('profi.txt') -+ p.sort_stats('cumulative').print_stats(80) -+ """ -+ self.flush() -+ #""" -+ -+ self.generator = Runner.Parallel(self, Options.options.jobs) -+ -+ def dw(on=True): -+ if Options.options.progress_bar: -+ if on: sys.stderr.write(Logs.colors.cursor_on) -+ else: sys.stderr.write(Logs.colors.cursor_off) -+ -+ debug('build: executor starting') -+ -+ back = os.getcwd() -+ os.chdir(self.bldnode.abspath()) -+ -+ try: -+ try: -+ dw(on=False) -+ self.generator.start() -+ except KeyboardInterrupt: -+ dw() -+ # if self.generator.processed != 1: TODO -+ self.save() -+ raise -+ except Exception: -+ dw() -+ # do not store anything, for something bad happened -+ raise -+ else: -+ dw() -+ #if self.generator.processed != 1: TODO -+ self.save() -+ -+ if self.generator.error: -+ raise BuildError(self, self.task_manager.tasks_done) -+ -+ finally: -+ os.chdir(back) -+ -+ def install(self): -+ "this function is called for both install and uninstall" -+ debug('build: install called') -+ -+ self.flush() -+ -+ # remove empty folders after uninstalling -+ if self.is_install < 0: -+ lst = [] -+ for x in self.uninstall: -+ dir = os.path.dirname(x) -+ if not dir in lst: lst.append(dir) -+ lst.sort() -+ lst.reverse() -+ -+ nlst = [] -+ for y in lst: -+ x = y -+ while len(x) > 4: -+ if not x in nlst: nlst.append(x) -+ x = os.path.dirname(x) -+ -+ nlst.sort() -+ nlst.reverse() -+ for x in nlst: -+ try: os.rmdir(x) -+ except OSError: pass -+ -+ def new_task_gen(self, *k, **kw): -+ if self.task_gen_cache_names: -+ self.task_gen_cache_names = {} -+ -+ kw['bld'] = self -+ if len(k) == 0: -+ ret = TaskGen.task_gen(*k, **kw) -+ else: -+ cls_name = k[0] -+ -+ try: cls = TaskGen.task_gen.classes[cls_name] -+ except KeyError: raise Utils.WscriptError('%s is not a valid task generator -> %s' % -+ (cls_name, [x for x in TaskGen.task_gen.classes])) -+ ret = cls(*k, **kw) -+ return ret -+ -+ def __call__(self, *k, **kw): -+ if self.task_gen_cache_names: -+ self.task_gen_cache_names = {} -+ -+ kw['bld'] = self -+ return TaskGen.task_gen(*k, **kw) -+ -+ def load_envs(self): -+ try: -+ lst = Utils.listdir(self.cachedir) -+ except OSError, e: -+ if e.errno == errno.ENOENT: -+ raise Utils.WafError('The project was not configured: run "waf configure" first!') -+ else: -+ raise -+ -+ if not lst: -+ raise Utils.WafError('The cache directory is empty: reconfigure the project') -+ -+ for file in lst: -+ if file.endswith(CACHE_SUFFIX): -+ env = Environment.Environment(os.path.join(self.cachedir, file)) -+ name = file[:-len(CACHE_SUFFIX)] -+ -+ self.all_envs[name] = env -+ -+ self.init_variants() -+ -+ for env in self.all_envs.values(): -+ for f in env[CFG_FILES]: -+ newnode = self.path.find_or_declare(f) -+ try: -+ hash = Utils.h_file(newnode.abspath(env)) -+ except (IOError, AttributeError): -+ error("cannot find "+f) -+ hash = SIG_NIL -+ self.node_sigs[env.variant()][newnode.id] = hash -+ -+ # TODO: hmmm, these nodes are removed from the tree when calling rescan() -+ self.bldnode = self.root.find_dir(self.bldnode.abspath()) -+ self.path = self.srcnode = self.root.find_dir(self.srcnode.abspath()) -+ self.cwd = self.bldnode.abspath() -+ -+ def setup(self, tool, tooldir=None, funs=None): -+ "setup tools for build process" -+ if isinstance(tool, list): -+ for i in tool: self.setup(i, tooldir) -+ return -+ -+ if not tooldir: tooldir = Options.tooldir -+ -+ module = Utils.load_tool(tool, tooldir) -+ if hasattr(module, "setup"): module.setup(self) -+ -+ def init_variants(self): -+ debug('build: init variants') -+ -+ lstvariants = [] -+ for env in self.all_envs.values(): -+ if not env.variant() in lstvariants: -+ lstvariants.append(env.variant()) -+ self.lst_variants = lstvariants -+ -+ debug('build: list of variants is %r', lstvariants) -+ -+ for name in lstvariants+[0]: -+ for v in 'node_sigs cache_node_abspath'.split(): -+ var = getattr(self, v) -+ if not name in var: -+ var[name] = {} -+ -+ # ======================================= # -+ # node and folder handling -+ -+ # this should be the main entry point -+ def load_dirs(self, srcdir, blddir, load_cache=1): -+ "this functions should be the start of everything" -+ -+ assert(os.path.isabs(srcdir)) -+ assert(os.path.isabs(blddir)) -+ -+ self.cachedir = os.path.join(blddir, CACHE_DIR) -+ -+ if srcdir == blddir: -+ raise Utils.WafError("build dir must be different from srcdir: %s <-> %s " % (srcdir, blddir)) -+ -+ self.bdir = blddir -+ -+ # try to load the cache file, if it does not exist, nothing happens -+ self.load() -+ -+ if not self.root: -+ Node.Nodu = self.node_class -+ self.root = Node.Nodu('', None, Node.DIR) -+ -+ if not self.srcnode: -+ self.srcnode = self.root.ensure_dir_node_from_path(srcdir) -+ debug('build: srcnode is %s and srcdir %s', self.srcnode.name, srcdir) -+ -+ self.path = self.srcnode -+ -+ # create this build dir if necessary -+ try: os.makedirs(blddir) -+ except OSError: pass -+ -+ if not self.bldnode: -+ self.bldnode = self.root.ensure_dir_node_from_path(blddir) -+ -+ self.init_variants() -+ -+ def rescan(self, src_dir_node): -+ """ -+ look the contents of a (folder)node and update its list of childs -+ -+ The intent is to perform the following steps -+ * remove the nodes for the files that have disappeared -+ * remove the signatures for the build files that have disappeared -+ * cache the results of os.listdir -+ * create the build folder equivalent (mkdir) for each variant -+ src/bar -> build/default/src/bar, build/release/src/bar -+ -+ when a folder in the source directory is removed, we do not check recursively -+ to remove the unused nodes. To do that, call 'waf clean' and build again. -+ """ -+ -+ # do not rescan over and over again -+ # TODO use a single variable in waf 1.6 -+ if self.cache_scanned_folders.get(src_dir_node.id, None): return -+ self.cache_scanned_folders[src_dir_node.id] = True -+ -+ # TODO remove in waf 1.6 -+ if hasattr(self, 'repository'): self.repository(src_dir_node) -+ -+ if not src_dir_node.name and sys.platform == 'win32': -+ # the root has no name, contains drive letters, and cannot be listed -+ return -+ -+ -+ # first, take the case of the source directory -+ parent_path = src_dir_node.abspath() -+ try: -+ lst = set(Utils.listdir(parent_path)) -+ except OSError: -+ lst = set([]) -+ -+ # TODO move this at the bottom -+ self.cache_dir_contents[src_dir_node.id] = lst -+ -+ # hash the existing source files, remove the others -+ cache = self.node_sigs[0] -+ for x in src_dir_node.childs.values(): -+ if x.id & 3 != Node.FILE: continue -+ if x.name in lst: -+ try: -+ cache[x.id] = Utils.h_file(x.abspath()) -+ except IOError: -+ raise Utils.WafError('The file %s is not readable or has become a dir' % x.abspath()) -+ else: -+ try: del cache[x.id] -+ except KeyError: pass -+ -+ del src_dir_node.childs[x.name] -+ -+ -+ # first obtain the differences between srcnode and src_dir_node -+ h1 = self.srcnode.height() -+ h2 = src_dir_node.height() -+ -+ lst = [] -+ child = src_dir_node -+ while h2 > h1: -+ lst.append(child.name) -+ child = child.parent -+ h2 -= 1 -+ lst.reverse() -+ -+ # list the files in the build dirs -+ try: -+ for variant in self.lst_variants: -+ sub_path = os.path.join(self.bldnode.abspath(), variant , *lst) -+ self.listdir_bld(src_dir_node, sub_path, variant) -+ except OSError: -+ -+ # listdir failed, remove the build node signatures for all variants -+ for node in src_dir_node.childs.values(): -+ if node.id & 3 != Node.BUILD: -+ continue -+ -+ for dct in self.node_sigs.values(): -+ if node.id in dct: -+ dct.__delitem__(node.id) -+ -+ # the policy is to avoid removing nodes representing directories -+ src_dir_node.childs.__delitem__(node.name) -+ -+ for variant in self.lst_variants: -+ sub_path = os.path.join(self.bldnode.abspath(), variant , *lst) -+ try: -+ os.makedirs(sub_path) -+ except OSError: -+ pass -+ -+ # ======================================= # -+ def listdir_src(self, parent_node): -+ """do not use, kept for compatibility""" -+ pass -+ -+ def remove_node(self, node): -+ """do not use, kept for compatibility""" -+ pass -+ -+ def listdir_bld(self, parent_node, path, variant): -+ """in this method we do not add timestamps but we remove them -+ when the files no longer exist (file removed in the build dir)""" -+ -+ i_existing_nodes = [x for x in parent_node.childs.values() if x.id & 3 == Node.BUILD] -+ -+ lst = set(Utils.listdir(path)) -+ node_names = set([x.name for x in i_existing_nodes]) -+ remove_names = node_names - lst -+ -+ # remove the stamps of the build nodes that no longer exist on the filesystem -+ ids_to_remove = [x.id for x in i_existing_nodes if x.name in remove_names] -+ cache = self.node_sigs[variant] -+ for nid in ids_to_remove: -+ if nid in cache: -+ cache.__delitem__(nid) -+ -+ def get_env(self): -+ return self.env_of_name('default') -+ def set_env(self, name, val): -+ self.all_envs[name] = val -+ -+ env = property(get_env, set_env) -+ -+ def add_manual_dependency(self, path, value): -+ if isinstance(path, Node.Node): -+ node = path -+ elif os.path.isabs(path): -+ node = self.root.find_resource(path) -+ else: -+ node = self.path.find_resource(path) -+ self.deps_man[node.id].append(value) -+ -+ def launch_node(self): -+ """return the launch directory as a node""" -+ # p_ln is kind of private, but public in case if -+ try: -+ return self.p_ln -+ except AttributeError: -+ self.p_ln = self.root.find_dir(Options.launch_dir) -+ return self.p_ln -+ -+ def glob(self, pattern, relative=True): -+ "files matching the pattern, seen from the current folder" -+ path = self.path.abspath() -+ files = [self.root.find_resource(x) for x in glob.glob(path+os.sep+pattern)] -+ if relative: -+ files = [x.path_to_parent(self.path) for x in files if x] -+ else: -+ files = [x.abspath() for x in files if x] -+ return files -+ -+ ## the following methods are candidates for the stable apis ## -+ -+ def add_group(self, *k): -+ self.task_manager.add_group(*k) -+ -+ def set_group(self, *k, **kw): -+ self.task_manager.set_group(*k, **kw) -+ -+ def hash_env_vars(self, env, vars_lst): -+ """hash environment variables -+ ['CXX', ..] -> [env['CXX'], ..] -> md5()""" -+ -+ # ccroot objects use the same environment for building the .o at once -+ # the same environment and the same variables are used -+ -+ idx = str(id(env)) + str(vars_lst) -+ try: return self.cache_sig_vars[idx] -+ except KeyError: pass -+ -+ lst = [str(env[a]) for a in vars_lst] -+ ret = Utils.h_list(lst) -+ debug('envhash: %r %r', ret, lst) -+ -+ # next time -+ self.cache_sig_vars[idx] = ret -+ return ret -+ -+ def name_to_obj(self, name, env): -+ """retrieve a task generator from its name or its target name -+ remember that names must be unique""" -+ cache = self.task_gen_cache_names -+ if not cache: -+ # create the index lazily -+ for x in self.all_task_gen: -+ vt = x.env.variant() + '_' -+ if x.name: -+ cache[vt + x.name] = x -+ else: -+ if isinstance(x.target, str): -+ target = x.target -+ else: -+ target = ' '.join(x.target) -+ v = vt + target -+ if not cache.get(v, None): -+ cache[v] = x -+ return cache.get(env.variant() + '_' + name, None) -+ -+ def flush(self, all=1): -+ """tell the task generators to create the tasks""" -+ -+ self.ini = datetime.datetime.now() -+ # force the initialization of the mapping name->object in flush -+ # name_to_obj can be used in userland scripts, in that case beware of incomplete mapping -+ self.task_gen_cache_names = {} -+ self.name_to_obj('', self.env) -+ -+ debug('build: delayed operation TaskGen.flush() called') -+ -+ if Options.options.compile_targets: -+ debug('task_gen: posting objects %r listed in compile_targets', Options.options.compile_targets) -+ -+ mana = self.task_manager -+ to_post = [] -+ min_grp = 0 -+ -+ # ensure the target names exist, fail before any post() -+ target_objects = Utils.DefaultDict(list) -+ for target_name in Options.options.compile_targets.split(','): -+ # trim target_name (handle cases when the user added spaces to targets) -+ target_name = target_name.strip() -+ for env in self.all_envs.values(): -+ tg = self.name_to_obj(target_name, env) -+ if tg: -+ target_objects[target_name].append(tg) -+ -+ m = mana.group_idx(tg) -+ if m > min_grp: -+ min_grp = m -+ to_post = [tg] -+ elif m == min_grp: -+ to_post.append(tg) -+ -+ if not target_name in target_objects and all: -+ raise Utils.WafError("target '%s' does not exist" % target_name) -+ -+ debug('group: Forcing up to group %s for target %s', mana.group_name(min_grp), Options.options.compile_targets) -+ -+ # post all the task generators in previous groups -+ for i in xrange(len(mana.groups)): -+ mana.current_group = i -+ if i == min_grp: -+ break -+ g = mana.groups[i] -+ debug('group: Forcing group %s', mana.group_name(g)) -+ for t in g.tasks_gen: -+ debug('group: Posting %s', t.name or t.target) -+ t.post() -+ -+ # then post the task generators listed in compile_targets in the last group -+ for t in to_post: -+ t.post() -+ -+ else: -+ debug('task_gen: posting objects (normal)') -+ ln = self.launch_node() -+ # if the build is started from the build directory, do as if it was started from the top-level -+ # for the pretty-printing (Node.py), the two lines below cannot be moved to Build::launch_node -+ if ln.is_child_of(self.bldnode) or not ln.is_child_of(self.srcnode): -+ ln = self.srcnode -+ -+ # if the project file is located under the source directory, build all targets by default -+ # else 'waf configure build' does nothing -+ proj_node = self.root.find_dir(os.path.split(Utils.g_module.root_path)[0]) -+ if proj_node.id != self.srcnode.id: -+ ln = self.srcnode -+ -+ for i in xrange(len(self.task_manager.groups)): -+ g = self.task_manager.groups[i] -+ self.task_manager.current_group = i -+ if Logs.verbose: -+ groups = [x for x in self.task_manager.groups_names if id(self.task_manager.groups_names[x]) == id(g)] -+ name = groups and groups[0] or 'unnamed' -+ Logs.debug('group: group', name) -+ for tg in g.tasks_gen: -+ if not tg.path.is_child_of(ln): -+ continue -+ if Logs.verbose: -+ Logs.debug('group: %s' % tg) -+ tg.post() -+ -+ def env_of_name(self, name): -+ try: -+ return self.all_envs[name] -+ except KeyError: -+ error('no such environment: '+name) -+ return None -+ -+ def progress_line(self, state, total, col1, col2): -+ n = len(str(total)) -+ -+ Utils.rot_idx += 1 -+ ind = Utils.rot_chr[Utils.rot_idx % 4] -+ -+ ini = self.ini -+ -+ pc = (100.*state)/total -+ eta = Utils.get_elapsed_time(ini) -+ fs = "[%%%dd/%%%dd][%%s%%2d%%%%%%s][%s][" % (n, n, ind) -+ left = fs % (state, total, col1, pc, col2) -+ right = '][%s%s%s]' % (col1, eta, col2) -+ -+ cols = Utils.get_term_cols() - len(left) - len(right) + 2*len(col1) + 2*len(col2) -+ if cols < 7: cols = 7 -+ -+ ratio = int((cols*state)/total) - 1 -+ -+ bar = ('='*ratio+'>').ljust(cols) -+ msg = Utils.indicator % (left, bar, right) -+ -+ return msg -+ -+ -+ # do_install is not used anywhere -+ def do_install(self, src, tgt, chmod=O644): -+ """returns true if the file was effectively installed or uninstalled, false otherwise""" -+ if self.is_install > 0: -+ if not Options.options.force: -+ # check if the file is already there to avoid a copy -+ try: -+ st1 = os.stat(tgt) -+ st2 = os.stat(src) -+ except OSError: -+ pass -+ else: -+ # same size and identical timestamps -> make no copy -+ if st1.st_mtime >= st2.st_mtime and st1.st_size == st2.st_size: -+ return False -+ -+ srclbl = src.replace(self.srcnode.abspath(None)+os.sep, '') -+ info("* installing %s as %s" % (srclbl, tgt)) -+ -+ # following is for shared libs and stale inodes (-_-) -+ try: os.remove(tgt) -+ except OSError: pass -+ -+ try: -+ shutil.copy2(src, tgt) -+ os.chmod(tgt, chmod) -+ except IOError: -+ try: -+ os.stat(src) -+ except (OSError, IOError): -+ error('File %r does not exist' % src) -+ raise Utils.WafError('Could not install the file %r' % tgt) -+ return True -+ -+ elif self.is_install < 0: -+ info("* uninstalling %s" % tgt) -+ -+ self.uninstall.append(tgt) -+ -+ try: -+ os.remove(tgt) -+ except OSError, e: -+ if e.errno != errno.ENOENT: -+ if not getattr(self, 'uninstall_error', None): -+ self.uninstall_error = True -+ Logs.warn('build: some files could not be uninstalled (retry with -vv to list them)') -+ if Logs.verbose > 1: -+ Logs.warn('could not remove %s (error code %r)' % (e.filename, e.errno)) -+ return True -+ -+ red = re.compile(r"^([A-Za-z]:)?[/\\\\]*") -+ def get_install_path(self, path, env=None): -+ "installation path prefixed by the destdir, the variables like in '${PREFIX}/bin' are substituted" -+ if not env: env = self.env -+ destdir = env.get_destdir() -+ path = path.replace('/', os.sep) -+ destpath = Utils.subst_vars(path, env) -+ if destdir: -+ destpath = os.path.join(destdir, self.red.sub('', destpath)) -+ return destpath -+ -+ def install_dir(self, path, env=None): -+ """ -+ create empty folders for the installation (very rarely used) -+ """ -+ if env: -+ assert isinstance(env, Environment.Environment), "invalid parameter" -+ else: -+ env = self.env -+ -+ if not path: -+ return [] -+ -+ destpath = self.get_install_path(path, env) -+ -+ if self.is_install > 0: -+ info('* creating %s' % destpath) -+ Utils.check_dir(destpath) -+ elif self.is_install < 0: -+ info('* removing %s' % destpath) -+ self.uninstall.append(destpath + '/xxx') # yes, ugly -+ -+ def install_files(self, path, files, env=None, chmod=O644, relative_trick=False, cwd=None): -+ """To install files only after they have been built, put the calls in a method named -+ post_build on the top-level wscript -+ -+ The files must be a list and contain paths as strings or as Nodes -+ -+ The relative_trick flag can be set to install folders, use bld.path.ant_glob() with it -+ """ -+ if env: -+ assert isinstance(env, Environment.Environment), "invalid parameter" -+ else: -+ env = self.env -+ -+ if not path: return [] -+ -+ if not cwd: -+ cwd = self.path -+ -+ if isinstance(files, str) and '*' in files: -+ gl = cwd.abspath() + os.sep + files -+ lst = glob.glob(gl) -+ else: -+ lst = Utils.to_list(files) -+ -+ if not getattr(lst, '__iter__', False): -+ lst = [lst] -+ -+ destpath = self.get_install_path(path, env) -+ -+ Utils.check_dir(destpath) -+ -+ installed_files = [] -+ for filename in lst: -+ if isinstance(filename, str) and os.path.isabs(filename): -+ alst = Utils.split_path(filename) -+ destfile = os.path.join(destpath, alst[-1]) -+ else: -+ if isinstance(filename, Node.Node): -+ nd = filename -+ else: -+ nd = cwd.find_resource(filename) -+ if not nd: -+ raise Utils.WafError("Unable to install the file %r (not found in %s)" % (filename, cwd)) -+ -+ if relative_trick: -+ destfile = os.path.join(destpath, filename) -+ Utils.check_dir(os.path.dirname(destfile)) -+ else: -+ destfile = os.path.join(destpath, nd.name) -+ -+ filename = nd.abspath(env) -+ -+ if self.do_install(filename, destfile, chmod): -+ installed_files.append(destfile) -+ return installed_files -+ -+ def install_as(self, path, srcfile, env=None, chmod=O644, cwd=None): -+ """ -+ srcfile may be a string or a Node representing the file to install -+ -+ returns True if the file was effectively installed, False otherwise -+ """ -+ if env: -+ assert isinstance(env, Environment.Environment), "invalid parameter" -+ else: -+ env = self.env -+ -+ if not path: -+ raise Utils.WafError("where do you want to install %r? (%r?)" % (srcfile, path)) -+ -+ if not cwd: -+ cwd = self.path -+ -+ destpath = self.get_install_path(path, env) -+ -+ dir, name = os.path.split(destpath) -+ Utils.check_dir(dir) -+ -+ # the source path -+ if isinstance(srcfile, Node.Node): -+ src = srcfile.abspath(env) -+ else: -+ src = srcfile -+ if not os.path.isabs(srcfile): -+ node = cwd.find_resource(srcfile) -+ if not node: -+ raise Utils.WafError("Unable to install the file %r (not found in %s)" % (srcfile, cwd)) -+ src = node.abspath(env) -+ -+ return self.do_install(src, destpath, chmod) -+ -+ def symlink_as(self, path, src, env=None, cwd=None): -+ """example: bld.symlink_as('${PREFIX}/lib/libfoo.so', 'libfoo.so.1.2.3') """ -+ -+ if sys.platform == 'win32': -+ # well, this *cannot* work -+ return -+ -+ if not path: -+ raise Utils.WafError("where do you want to install %r? (%r?)" % (src, path)) -+ -+ tgt = self.get_install_path(path, env) -+ -+ dir, name = os.path.split(tgt) -+ Utils.check_dir(dir) -+ -+ if self.is_install > 0: -+ link = False -+ if not os.path.islink(tgt): -+ link = True -+ elif os.readlink(tgt) != src: -+ link = True -+ -+ if link: -+ try: os.remove(tgt) -+ except OSError: pass -+ -+ info('* symlink %s (-> %s)' % (tgt, src)) -+ os.symlink(src, tgt) -+ return 0 -+ -+ else: # UNINSTALL -+ try: -+ info('* removing %s' % (tgt)) -+ os.remove(tgt) -+ return 0 -+ except OSError: -+ return 1 -+ -+ def exec_command(self, cmd, **kw): -+ # 'runner' zone is printed out for waf -v, see wafadmin/Options.py -+ debug('runner: system command -> %s', cmd) -+ if self.log: -+ self.log.write('%s\n' % cmd) -+ kw['log'] = self.log -+ try: -+ if not kw.get('cwd', None): -+ kw['cwd'] = self.cwd -+ except AttributeError: -+ self.cwd = kw['cwd'] = self.bldnode.abspath() -+ return Utils.exec_command(cmd, **kw) -+ -+ def printout(self, s): -+ f = self.log or sys.stderr -+ f.write(s) -+ f.flush() -+ -+ def add_subdirs(self, dirs): -+ self.recurse(dirs, 'build') -+ -+ def pre_recurse(self, name_or_mod, path, nexdir): -+ if not hasattr(self, 'oldpath'): -+ self.oldpath = [] -+ self.oldpath.append(self.path) -+ self.path = self.root.find_dir(nexdir) -+ return {'bld': self, 'ctx': self} -+ -+ def post_recurse(self, name_or_mod, path, nexdir): -+ self.path = self.oldpath.pop() -+ -+ ###### user-defined behaviour -+ -+ def pre_build(self): -+ if hasattr(self, 'pre_funs'): -+ for m in self.pre_funs: -+ m(self) -+ -+ def post_build(self): -+ if hasattr(self, 'post_funs'): -+ for m in self.post_funs: -+ m(self) -+ -+ def add_pre_fun(self, meth): -+ try: self.pre_funs.append(meth) -+ except AttributeError: self.pre_funs = [meth] -+ -+ def add_post_fun(self, meth): -+ try: self.post_funs.append(meth) -+ except AttributeError: self.post_funs = [meth] -+ -+ def use_the_magic(self): -+ Task.algotype = Task.MAXPARALLEL -+ Task.file_deps = Task.extract_deps -+ self.magic = True -+ -+ install_as = group_method(install_as) -+ install_files = group_method(install_files) -+ symlink_as = group_method(symlink_as) -+ -diff --git a/buildtools/wafadmin/Configure.py b/buildtools/wafadmin/Configure.py -new file mode 100644 -index 0000000..35b4e51 ---- /dev/null -+++ b/buildtools/wafadmin/Configure.py -@@ -0,0 +1,444 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2005-2008 (ita) -+ -+""" -+Configuration system -+ -+A configuration instance is created when "waf configure" is called, it is used to: -+* create data dictionaries (Environment instances) -+* store the list of modules to import -+ -+The old model (copied from Scons) was to store logic (mapping file extensions to functions) -+along with the data. In Waf a way was found to separate that logic by adding an indirection -+layer (storing the names in the Environment instances) -+ -+In the new model, the logic is more object-oriented, and the user scripts provide the -+logic. The data files (Environments) must contain configuration data only (flags, ..). -+ -+Note: the c/c++ related code is in the module config_c -+""" -+ -+import os, shlex, sys, time -+try: import cPickle -+except ImportError: import pickle as cPickle -+import Environment, Utils, Options, Logs -+from Logs import warn -+from Constants import * -+ -+try: -+ from urllib import request -+except: -+ from urllib import urlopen -+else: -+ urlopen = request.urlopen -+ -+conf_template = '''# project %(app)s configured on %(now)s by -+# waf %(wafver)s (abi %(abi)s, python %(pyver)x on %(systype)s) -+# using %(args)s -+# -+''' -+ -+class ConfigurationError(Utils.WscriptError): -+ pass -+ -+autoconfig = False -+"reconfigure the project automatically" -+ -+def find_file(filename, path_list): -+ """find a file in a list of paths -+ @param filename: name of the file to search for -+ @param path_list: list of directories to search -+ @return: the first occurrence filename or '' if filename could not be found -+""" -+ for directory in Utils.to_list(path_list): -+ if os.path.exists(os.path.join(directory, filename)): -+ return directory -+ return '' -+ -+def find_program_impl(env, filename, path_list=[], var=None, environ=None): -+ """find a program in folders path_lst, and sets env[var] -+ @param env: environment -+ @param filename: name of the program to search for -+ @param path_list: list of directories to search for filename -+ @param var: environment value to be checked for in env or os.environ -+ @return: either the value that is referenced with [var] in env or os.environ -+ or the first occurrence filename or '' if filename could not be found -+""" -+ -+ if not environ: -+ environ = os.environ -+ -+ try: path_list = path_list.split() -+ except AttributeError: pass -+ -+ if var: -+ if env[var]: return env[var] -+ if var in environ: env[var] = environ[var] -+ -+ if not path_list: path_list = environ.get('PATH', '').split(os.pathsep) -+ -+ ext = (Options.platform == 'win32') and '.exe,.com,.bat,.cmd' or '' -+ for y in [filename+x for x in ext.split(',')]: -+ for directory in path_list: -+ x = os.path.join(directory, y) -+ if os.path.isfile(x): -+ if var: env[var] = x -+ return x -+ return '' -+ -+class ConfigurationContext(Utils.Context): -+ tests = {} -+ error_handlers = [] -+ def __init__(self, env=None, blddir='', srcdir=''): -+ self.env = None -+ self.envname = '' -+ -+ self.environ = dict(os.environ) -+ -+ self.line_just = 40 -+ -+ self.blddir = blddir -+ self.srcdir = srcdir -+ self.all_envs = {} -+ -+ # curdir: necessary for recursion -+ self.cwd = self.curdir = os.getcwd() -+ -+ self.tools = [] # tools loaded in the configuration, and that will be loaded when building -+ -+ self.setenv(DEFAULT) -+ -+ self.lastprog = '' -+ -+ self.hash = 0 -+ self.files = [] -+ -+ self.tool_cache = [] -+ -+ if self.blddir: -+ self.post_init() -+ -+ def post_init(self): -+ -+ self.cachedir = os.path.join(self.blddir, CACHE_DIR) -+ -+ path = os.path.join(self.blddir, WAF_CONFIG_LOG) -+ try: os.unlink(path) -+ except (OSError, IOError): pass -+ -+ try: -+ self.log = open(path, 'w') -+ except (OSError, IOError): -+ self.fatal('could not open %r for writing' % path) -+ -+ app = Utils.g_module.APPNAME -+ if app: -+ ver = getattr(Utils.g_module, 'VERSION', '') -+ if ver: -+ app = "%s (%s)" % (app, ver) -+ -+ now = time.ctime() -+ pyver = sys.hexversion -+ systype = sys.platform -+ args = " ".join(sys.argv) -+ wafver = WAFVERSION -+ abi = ABI -+ self.log.write(conf_template % vars()) -+ -+ def __del__(self): -+ """cleanup function: close config.log""" -+ -+ # may be ran by the gc, not always after initialization -+ if hasattr(self, 'log') and self.log: -+ self.log.close() -+ -+ def fatal(self, msg): -+ raise ConfigurationError(msg) -+ -+ def check_tool(self, input, tooldir=None, funs=None): -+ "load a waf tool" -+ -+ tools = Utils.to_list(input) -+ if tooldir: tooldir = Utils.to_list(tooldir) -+ for tool in tools: -+ tool = tool.replace('++', 'xx') -+ if tool == 'java': tool = 'javaw' -+ if tool.lower() == 'unittest': tool = 'unittestw' -+ # avoid loading the same tool more than once with the same functions -+ # used by composite projects -+ -+ mag = (tool, id(self.env), funs) -+ if mag in self.tool_cache: -+ continue -+ self.tool_cache.append(mag) -+ -+ module = None -+ try: -+ module = Utils.load_tool(tool, tooldir) -+ except Exception, e: -+ ex = e -+ if Options.options.download: -+ _3rdparty = os.path.normpath(Options.tooldir[0] + os.sep + '..' + os.sep + '3rdparty') -+ -+ # try to download the tool from the repository then -+ # the default is set to false -+ for x in Utils.to_list(Options.remote_repo): -+ for sub in ['branches/waf-%s/wafadmin/3rdparty' % WAFVERSION, 'trunk/wafadmin/3rdparty']: -+ url = '/'.join((x, sub, tool + '.py')) -+ try: -+ web = urlopen(url) -+ if web.getcode() != 200: -+ continue -+ except Exception, e: -+ # on python3 urlopen throws an exception -+ continue -+ else: -+ loc = None -+ try: -+ loc = open(_3rdparty + os.sep + tool + '.py', 'wb') -+ loc.write(web.read()) -+ web.close() -+ finally: -+ if loc: -+ loc.close() -+ Logs.warn('downloaded %s from %s' % (tool, url)) -+ try: -+ module = Utils.load_tool(tool, tooldir) -+ except: -+ Logs.warn('module %s from %s is unusable' % (tool, url)) -+ try: -+ os.unlink(_3rdparty + os.sep + tool + '.py') -+ except: -+ pass -+ continue -+ else: -+ break -+ -+ if not module: -+ Logs.error('Could not load the tool %r or download a suitable replacement from the repository (sys.path %r)\n%s' % (tool, sys.path, e)) -+ raise ex -+ else: -+ Logs.error('Could not load the tool %r in %r (try the --download option?):\n%s' % (tool, sys.path, e)) -+ raise ex -+ -+ if funs is not None: -+ self.eval_rules(funs) -+ else: -+ func = getattr(module, 'detect', None) -+ if func: -+ if type(func) is type(find_file): func(self) -+ else: self.eval_rules(func) -+ -+ self.tools.append({'tool':tool, 'tooldir':tooldir, 'funs':funs}) -+ -+ def sub_config(self, k): -+ "executes the configure function of a wscript module" -+ self.recurse(k, name='configure') -+ -+ def pre_recurse(self, name_or_mod, path, nexdir): -+ return {'conf': self, 'ctx': self} -+ -+ def post_recurse(self, name_or_mod, path, nexdir): -+ if not autoconfig: -+ return -+ self.hash = hash((self.hash, getattr(name_or_mod, 'waf_hash_val', name_or_mod))) -+ self.files.append(path) -+ -+ def store(self, file=''): -+ "save the config results into the cache file" -+ if not os.path.isdir(self.cachedir): -+ os.makedirs(self.cachedir) -+ -+ if not file: -+ file = open(os.path.join(self.cachedir, 'build.config.py'), 'w') -+ file.write('version = 0x%x\n' % HEXVERSION) -+ file.write('tools = %r\n' % self.tools) -+ file.close() -+ -+ if not self.all_envs: -+ self.fatal('nothing to store in the configuration context!') -+ for key in self.all_envs: -+ tmpenv = self.all_envs[key] -+ tmpenv.store(os.path.join(self.cachedir, key + CACHE_SUFFIX)) -+ -+ def set_env_name(self, name, env): -+ "add a new environment called name" -+ self.all_envs[name] = env -+ return env -+ -+ def retrieve(self, name, fromenv=None): -+ "retrieve an environment called name" -+ try: -+ env = self.all_envs[name] -+ except KeyError: -+ env = Environment.Environment() -+ env['PREFIX'] = os.path.abspath(os.path.expanduser(Options.options.prefix)) -+ self.all_envs[name] = env -+ else: -+ if fromenv: warn("The environment %s may have been configured already" % name) -+ return env -+ -+ def setenv(self, name): -+ "enable the environment called name" -+ self.env = self.retrieve(name) -+ self.envname = name -+ -+ def add_os_flags(self, var, dest=None): -+ # do not use 'get' to make certain the variable is not defined -+ try: self.env.append_value(dest or var, Utils.to_list(self.environ[var])) -+ except KeyError: pass -+ -+ def check_message_1(self, sr): -+ self.line_just = max(self.line_just, len(sr)) -+ for x in ('\n', self.line_just * '-', '\n', sr, '\n'): -+ self.log.write(x) -+ Utils.pprint('NORMAL', "%s :" % sr.ljust(self.line_just), sep='') -+ -+ def check_message_2(self, sr, color='GREEN'): -+ self.log.write(sr) -+ self.log.write('\n') -+ Utils.pprint(color, sr) -+ -+ def check_message(self, th, msg, state, option=''): -+ sr = 'Checking for %s %s' % (th, msg) -+ self.check_message_1(sr) -+ p = self.check_message_2 -+ if state: p('ok ' + str(option)) -+ else: p('not found', 'YELLOW') -+ -+ # FIXME remove in waf 1.6 -+ # the parameter 'option' is not used (kept for compatibility) -+ def check_message_custom(self, th, msg, custom, option='', color='PINK'): -+ sr = 'Checking for %s %s' % (th, msg) -+ self.check_message_1(sr) -+ self.check_message_2(custom, color) -+ -+ def msg(self, msg, result, color=None): -+ """Prints a configuration message 'Checking for xxx: ok'""" -+ self.start_msg('Checking for ' + msg) -+ -+ if not isinstance(color, str): -+ color = result and 'GREEN' or 'YELLOW' -+ -+ self.end_msg(result, color) -+ -+ def start_msg(self, msg): -+ try: -+ if self.in_msg: -+ return -+ except: -+ self.in_msg = 0 -+ self.in_msg += 1 -+ -+ self.line_just = max(self.line_just, len(msg)) -+ for x in ('\n', self.line_just * '-', '\n', msg, '\n'): -+ self.log.write(x) -+ Utils.pprint('NORMAL', "%s :" % msg.ljust(self.line_just), sep='') -+ -+ def end_msg(self, result, color): -+ self.in_msg -= 1 -+ if self.in_msg: -+ return -+ -+ if not color: -+ color = 'GREEN' -+ if result == True: -+ msg = 'ok' -+ elif result == False: -+ msg = 'not found' -+ color = 'YELLOW' -+ else: -+ msg = str(result) -+ -+ self.log.write(msg) -+ self.log.write('\n') -+ Utils.pprint(color, msg) -+ -+ def find_program(self, filename, path_list=[], var=None, mandatory=False): -+ "wrapper that adds a configuration message" -+ -+ ret = None -+ if var: -+ if self.env[var]: -+ ret = self.env[var] -+ elif var in os.environ: -+ ret = os.environ[var] -+ -+ if not isinstance(filename, list): filename = [filename] -+ if not ret: -+ for x in filename: -+ ret = find_program_impl(self.env, x, path_list, var, environ=self.environ) -+ if ret: break -+ -+ self.check_message_1('Checking for program %s' % ' or '.join(filename)) -+ self.log.write(' find program=%r paths=%r var=%r\n -> %r\n' % (filename, path_list, var, ret)) -+ if ret: -+ Utils.pprint('GREEN', str(ret)) -+ else: -+ Utils.pprint('YELLOW', 'not found') -+ if mandatory: -+ self.fatal('The program %r is required' % filename) -+ -+ if var: -+ self.env[var] = ret -+ return ret -+ -+ def cmd_to_list(self, cmd): -+ "commands may be written in pseudo shell like 'ccache g++'" -+ if isinstance(cmd, str) and cmd.find(' '): -+ try: -+ os.stat(cmd) -+ except OSError: -+ return shlex.split(cmd) -+ else: -+ return [cmd] -+ return cmd -+ -+ def __getattr__(self, name): -+ r = self.__class__.__dict__.get(name, None) -+ if r: return r -+ if name and name.startswith('require_'): -+ -+ for k in ['check_', 'find_']: -+ n = name.replace('require_', k) -+ ret = self.__class__.__dict__.get(n, None) -+ if ret: -+ def run(*k, **kw): -+ r = ret(self, *k, **kw) -+ if not r: -+ self.fatal('requirement failure') -+ return r -+ return run -+ self.fatal('No such method %r' % name) -+ -+ def eval_rules(self, rules): -+ self.rules = Utils.to_list(rules) -+ for x in self.rules: -+ f = getattr(self, x) -+ if not f: self.fatal("No such method '%s'." % x) -+ try: -+ f() -+ except Exception, e: -+ ret = self.err_handler(x, e) -+ if ret == BREAK: -+ break -+ elif ret == CONTINUE: -+ continue -+ else: -+ self.fatal(e) -+ -+ def err_handler(self, fun, error): -+ pass -+ -+def conf(f): -+ "decorator: attach new configuration functions" -+ setattr(ConfigurationContext, f.__name__, f) -+ return f -+ -+def conftest(f): -+ "decorator: attach new configuration tests (registered as strings)" -+ ConfigurationContext.tests[f.__name__] = f -+ return conf(f) -+ -+ -diff --git a/buildtools/wafadmin/Constants.py b/buildtools/wafadmin/Constants.py -new file mode 100644 -index 0000000..e67dda6 ---- /dev/null -+++ b/buildtools/wafadmin/Constants.py -@@ -0,0 +1,76 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Yinon dot me gmail 2008 -+ -+""" -+these constants are somewhat public, try not to mess them -+ -+maintainer: the version number is updated from the top-level wscript file -+""" -+ -+# do not touch these three lines, they are updated automatically -+HEXVERSION=0x105019 -+WAFVERSION="1.5.19" -+WAFREVISION = "9709M" -+ABI = 7 -+ -+# permissions -+O644 = 420 -+O755 = 493 -+ -+MAXJOBS = 99999999 -+ -+CACHE_DIR = 'c4che' -+CACHE_SUFFIX = '.cache.py' -+DBFILE = '.wafpickle-%d' % ABI -+WSCRIPT_FILE = 'wscript' -+WSCRIPT_BUILD_FILE = 'wscript_build' -+WAF_CONFIG_LOG = 'config.log' -+WAF_CONFIG_H = 'config.h' -+ -+SIG_NIL = 'iluvcuteoverload' -+ -+VARIANT = '_VARIANT_' -+DEFAULT = 'default' -+ -+SRCDIR = 'srcdir' -+BLDDIR = 'blddir' -+APPNAME = 'APPNAME' -+VERSION = 'VERSION' -+ -+DEFINES = 'defines' -+UNDEFINED = () -+ -+BREAK = "break" -+CONTINUE = "continue" -+ -+# task scheduler options -+JOBCONTROL = "JOBCONTROL" -+MAXPARALLEL = "MAXPARALLEL" -+NORMAL = "NORMAL" -+ -+# task state -+NOT_RUN = 0 -+MISSING = 1 -+CRASHED = 2 -+EXCEPTION = 3 -+SKIPPED = 8 -+SUCCESS = 9 -+ -+ASK_LATER = -1 -+SKIP_ME = -2 -+RUN_ME = -3 -+ -+ -+LOG_FORMAT = "%(asctime)s %(c1)s%(zone)s%(c2)s %(message)s" -+HOUR_FORMAT = "%H:%M:%S" -+ -+TEST_OK = True -+ -+CFG_FILES = 'cfg_files' -+ -+# positive '->' install -+# negative '<-' uninstall -+INSTALL = 1337 -+UNINSTALL = -1337 -+ -diff --git a/buildtools/wafadmin/Environment.py b/buildtools/wafadmin/Environment.py -new file mode 100644 -index 0000000..52c83b4 ---- /dev/null -+++ b/buildtools/wafadmin/Environment.py -@@ -0,0 +1,210 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2005 (ita) -+ -+"""Environment representation -+ -+There is one gotcha: getitem returns [] if the contents evals to False -+This means env['foo'] = {}; print env['foo'] will print [] not {} -+""" -+ -+import os, copy, re -+import Logs, Options, Utils -+from Constants import * -+re_imp = re.compile('^(#)*?([^#=]*?)\ =\ (.*?)$', re.M) -+ -+class Environment(object): -+ """A safe-to-use dictionary, but do not attach functions to it please (break cPickle) -+ An environment instance can be stored into a file and loaded easily -+ """ -+ __slots__ = ("table", "parent") -+ def __init__(self, filename=None): -+ self.table = {} -+ #self.parent = None -+ -+ if filename: -+ self.load(filename) -+ -+ def __contains__(self, key): -+ if key in self.table: return True -+ try: return self.parent.__contains__(key) -+ except AttributeError: return False # parent may not exist -+ -+ def __str__(self): -+ keys = set() -+ cur = self -+ while cur: -+ keys.update(cur.table.keys()) -+ cur = getattr(cur, 'parent', None) -+ keys = list(keys) -+ keys.sort() -+ return "\n".join(["%r %r" % (x, self.__getitem__(x)) for x in keys]) -+ -+ def __getitem__(self, key): -+ try: -+ while 1: -+ x = self.table.get(key, None) -+ if not x is None: -+ return x -+ self = self.parent -+ except AttributeError: -+ return [] -+ -+ def __setitem__(self, key, value): -+ self.table[key] = value -+ -+ def __delitem__(self, key): -+ del self.table[key] -+ -+ def pop(self, key, *args): -+ if len(args): -+ return self.table.pop(key, *args) -+ return self.table.pop(key) -+ -+ def set_variant(self, name): -+ self.table[VARIANT] = name -+ -+ def variant(self): -+ try: -+ while 1: -+ x = self.table.get(VARIANT, None) -+ if not x is None: -+ return x -+ self = self.parent -+ except AttributeError: -+ return DEFAULT -+ -+ def copy(self): -+ # TODO waf 1.6 rename this method derive, #368 -+ newenv = Environment() -+ newenv.parent = self -+ return newenv -+ -+ def detach(self): -+ """TODO try it -+ modifying the original env will not change the copy""" -+ tbl = self.get_merged_dict() -+ try: -+ delattr(self, 'parent') -+ except AttributeError: -+ pass -+ else: -+ keys = tbl.keys() -+ for x in keys: -+ tbl[x] = copy.deepcopy(tbl[x]) -+ self.table = tbl -+ -+ def get_flat(self, key): -+ s = self[key] -+ if isinstance(s, str): return s -+ return ' '.join(s) -+ -+ def _get_list_value_for_modification(self, key): -+ """Gets a value that must be a list for further modification. The -+ list may be modified inplace and there is no need to -+ "self.table[var] = value" afterwards. -+ """ -+ try: -+ value = self.table[key] -+ except KeyError: -+ try: value = self.parent[key] -+ except AttributeError: value = [] -+ if isinstance(value, list): -+ value = value[:] -+ else: -+ value = [value] -+ else: -+ if not isinstance(value, list): -+ value = [value] -+ self.table[key] = value -+ return value -+ -+ def append_value(self, var, value): -+ current_value = self._get_list_value_for_modification(var) -+ -+ if isinstance(value, list): -+ current_value.extend(value) -+ else: -+ current_value.append(value) -+ -+ def prepend_value(self, var, value): -+ current_value = self._get_list_value_for_modification(var) -+ -+ if isinstance(value, list): -+ current_value = value + current_value -+ # a new list: update the dictionary entry -+ self.table[var] = current_value -+ else: -+ current_value.insert(0, value) -+ -+ # prepend unique would be ambiguous -+ def append_unique(self, var, value): -+ current_value = self._get_list_value_for_modification(var) -+ -+ if isinstance(value, list): -+ for value_item in value: -+ if value_item not in current_value: -+ current_value.append(value_item) -+ else: -+ if value not in current_value: -+ current_value.append(value) -+ -+ def get_merged_dict(self): -+ """compute a merged table""" -+ table_list = [] -+ env = self -+ while 1: -+ table_list.insert(0, env.table) -+ try: env = env.parent -+ except AttributeError: break -+ merged_table = {} -+ for table in table_list: -+ merged_table.update(table) -+ return merged_table -+ -+ def store(self, filename): -+ "Write the variables into a file" -+ file = open(filename, 'w') -+ merged_table = self.get_merged_dict() -+ keys = list(merged_table.keys()) -+ keys.sort() -+ for k in keys: file.write('%s = %r\n' % (k, merged_table[k])) -+ file.close() -+ -+ def load(self, filename): -+ "Retrieve the variables from a file" -+ tbl = self.table -+ code = Utils.readf(filename) -+ for m in re_imp.finditer(code): -+ g = m.group -+ tbl[g(2)] = eval(g(3)) -+ Logs.debug('env: %s', self.table) -+ -+ def get_destdir(self): -+ "return the destdir, useful for installing" -+ if self.__getitem__('NOINSTALL'): return '' -+ return Options.options.destdir -+ -+ def update(self, d): -+ for k, v in d.iteritems(): -+ self[k] = v -+ -+ -+ def __getattr__(self, name): -+ if name in self.__slots__: -+ return object.__getattr__(self, name) -+ else: -+ return self[name] -+ -+ def __setattr__(self, name, value): -+ if name in self.__slots__: -+ object.__setattr__(self, name, value) -+ else: -+ self[name] = value -+ -+ def __delattr__(self, name): -+ if name in self.__slots__: -+ object.__delattr__(self, name) -+ else: -+ del self[name] -+ -diff --git a/buildtools/wafadmin/Logs.py b/buildtools/wafadmin/Logs.py -new file mode 100644 -index 0000000..c160b37 ---- /dev/null -+++ b/buildtools/wafadmin/Logs.py -@@ -0,0 +1,134 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2005 (ita) -+ -+import ansiterm -+import os, re, logging, traceback, sys -+from Constants import * -+ -+zones = '' -+verbose = 0 -+ -+colors_lst = { -+'USE' : True, -+'BOLD' :'\x1b[01;1m', -+'RED' :'\x1b[01;31m', -+'GREEN' :'\x1b[32m', -+'YELLOW':'\x1b[33m', -+'PINK' :'\x1b[35m', -+'BLUE' :'\x1b[01;34m', -+'CYAN' :'\x1b[36m', -+'NORMAL':'\x1b[0m', -+'cursor_on' :'\x1b[?25h', -+'cursor_off' :'\x1b[?25l', -+} -+ -+got_tty = False -+term = os.environ.get('TERM', 'dumb') -+if not term in ['dumb', 'emacs']: -+ try: -+ got_tty = sys.stderr.isatty() or (sys.platform == 'win32' and term in ['xterm', 'msys']) -+ except AttributeError: -+ pass -+ -+import Utils -+ -+if not got_tty or 'NOCOLOR' in os.environ: -+ colors_lst['USE'] = False -+ -+# test -+#if sys.platform == 'win32': -+# colors_lst['USE'] = True -+ -+def get_color(cl): -+ if not colors_lst['USE']: return '' -+ return colors_lst.get(cl, '') -+ -+class foo(object): -+ def __getattr__(self, a): -+ return get_color(a) -+ def __call__(self, a): -+ return get_color(a) -+ -+colors = foo() -+ -+re_log = re.compile(r'(\w+): (.*)', re.M) -+class log_filter(logging.Filter): -+ def __init__(self, name=None): -+ pass -+ -+ def filter(self, rec): -+ rec.c1 = colors.PINK -+ rec.c2 = colors.NORMAL -+ rec.zone = rec.module -+ if rec.levelno >= logging.INFO: -+ if rec.levelno >= logging.ERROR: -+ rec.c1 = colors.RED -+ elif rec.levelno >= logging.WARNING: -+ rec.c1 = colors.YELLOW -+ else: -+ rec.c1 = colors.GREEN -+ return True -+ -+ zone = '' -+ m = re_log.match(rec.msg) -+ if m: -+ zone = rec.zone = m.group(1) -+ rec.msg = m.group(2) -+ -+ if zones: -+ return getattr(rec, 'zone', '') in zones or '*' in zones -+ elif not verbose > 2: -+ return False -+ return True -+ -+class formatter(logging.Formatter): -+ def __init__(self): -+ logging.Formatter.__init__(self, LOG_FORMAT, HOUR_FORMAT) -+ -+ def format(self, rec): -+ if rec.levelno >= logging.WARNING or rec.levelno == logging.INFO: -+ try: -+ return '%s%s%s' % (rec.c1, rec.msg.decode('utf-8'), rec.c2) -+ except: -+ return rec.c1+rec.msg+rec.c2 -+ return logging.Formatter.format(self, rec) -+ -+def debug(*k, **kw): -+ if verbose: -+ k = list(k) -+ k[0] = k[0].replace('\n', ' ') -+ logging.debug(*k, **kw) -+ -+def error(*k, **kw): -+ logging.error(*k, **kw) -+ if verbose > 1: -+ if isinstance(k[0], Utils.WafError): -+ st = k[0].stack -+ else: -+ st = traceback.extract_stack() -+ if st: -+ st = st[:-1] -+ buf = [] -+ for filename, lineno, name, line in st: -+ buf.append(' File "%s", line %d, in %s' % (filename, lineno, name)) -+ if line: -+ buf.append(' %s' % line.strip()) -+ if buf: logging.error("\n".join(buf)) -+ -+warn = logging.warn -+info = logging.info -+ -+def init_log(): -+ log = logging.getLogger() -+ log.handlers = [] -+ log.filters = [] -+ hdlr = logging.StreamHandler() -+ hdlr.setFormatter(formatter()) -+ log.addHandler(hdlr) -+ log.addFilter(log_filter()) -+ log.setLevel(logging.DEBUG) -+ -+# may be initialized more than once -+init_log() -+ -diff --git a/buildtools/wafadmin/Node.py b/buildtools/wafadmin/Node.py -new file mode 100644 -index 0000000..236dd0d ---- /dev/null -+++ b/buildtools/wafadmin/Node.py -@@ -0,0 +1,695 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2005 (ita) -+ -+""" -+Node: filesystem structure, contains lists of nodes -+ -+IMPORTANT: -+1. Each file/folder is represented by exactly one node. -+ -+2. Most would-be class properties are stored in Build: nodes to depend on, signature, flags, .. -+unused class members increase the .wafpickle file size sensibly with lots of objects. -+ -+3. The build is launched from the top of the build dir (for example, in _build_/). -+ -+4. Node should not be instantiated directly. -+Each instance of Build.BuildContext has a Node subclass. -+(aka: 'Nodu', see BuildContext initializer) -+The BuildContext is referenced here as self.__class__.bld -+Its Node class is referenced here as self.__class__ -+ -+The public and advertised apis are the following: -+${TGT} -> dir/to/file.ext -+${TGT[0].base()} -> dir/to/file -+${TGT[0].dir(env)} -> dir/to -+${TGT[0].file()} -> file.ext -+${TGT[0].file_base()} -> file -+${TGT[0].suffix()} -> .ext -+${TGT[0].abspath(env)} -> /path/to/dir/to/file.ext -+ -+""" -+ -+import os, sys, fnmatch, re, stat -+import Utils, Constants -+ -+UNDEFINED = 0 -+DIR = 1 -+FILE = 2 -+BUILD = 3 -+ -+type_to_string = {UNDEFINED: "unk", DIR: "dir", FILE: "src", BUILD: "bld"} -+ -+# These fnmatch expressions are used by default to prune the directory tree -+# while doing the recursive traversal in the find_iter method of the Node class. -+prune_pats = '.git .bzr .hg .svn _MTN _darcs CVS SCCS'.split() -+ -+# These fnmatch expressions are used by default to exclude files and dirs -+# while doing the recursive traversal in the find_iter method of the Node class. -+exclude_pats = prune_pats + '*~ #*# .#* %*% ._* .gitignore .cvsignore vssver.scc .DS_Store'.split() -+ -+# These Utils.jar_regexp expressions are used by default to exclude files and dirs and also prune the directory tree -+# while doing the recursive traversal in the ant_glob method of the Node class. -+exclude_regs = ''' -+**/*~ -+**/#*# -+**/.#* -+**/%*% -+**/._* -+**/CVS -+**/CVS/** -+**/.cvsignore -+**/SCCS -+**/SCCS/** -+**/vssver.scc -+**/.svn -+**/.svn/** -+**/.git -+**/.git/** -+**/.gitignore -+**/.bzr -+**/.bzr/** -+**/.hg -+**/.hg/** -+**/_MTN -+**/_MTN/** -+**/_darcs -+**/_darcs/** -+**/.DS_Store''' -+ -+class Node(object): -+ __slots__ = ("name", "parent", "id", "childs") -+ def __init__(self, name, parent, node_type = UNDEFINED): -+ self.name = name -+ self.parent = parent -+ -+ # assumption: one build object at a time -+ self.__class__.bld.id_nodes += 4 -+ self.id = self.__class__.bld.id_nodes + node_type -+ -+ if node_type == DIR: self.childs = {} -+ -+ # We do not want to add another type attribute (memory) -+ # use the id to find out: type = id & 3 -+ # for setting: new type = type + x - type & 3 -+ -+ if parent and name in parent.childs: -+ raise Utils.WafError('node %s exists in the parent files %r already' % (name, parent)) -+ -+ if parent: parent.childs[name] = self -+ -+ def __setstate__(self, data): -+ if len(data) == 4: -+ (self.parent, self.name, self.id, self.childs) = data -+ else: -+ (self.parent, self.name, self.id) = data -+ -+ def __getstate__(self): -+ if getattr(self, 'childs', None) is None: -+ return (self.parent, self.name, self.id) -+ else: -+ return (self.parent, self.name, self.id, self.childs) -+ -+ def __str__(self): -+ if not self.parent: return '' -+ return "%s://%s" % (type_to_string[self.id & 3], self.abspath()) -+ -+ def __repr__(self): -+ return self.__str__() -+ -+ def __hash__(self): -+ "expensive, make certain it is not used" -+ raise Utils.WafError('nodes, you are doing it wrong') -+ -+ def __copy__(self): -+ "nodes are not supposed to be copied" -+ raise Utils.WafError('nodes are not supposed to be cloned') -+ -+ def get_type(self): -+ return self.id & 3 -+ -+ def set_type(self, t): -+ "dangerous, you are not supposed to use this" -+ self.id = self.id + t - self.id & 3 -+ -+ def dirs(self): -+ return [x for x in self.childs.values() if x.id & 3 == DIR] -+ -+ def files(self): -+ return [x for x in self.childs.values() if x.id & 3 == FILE] -+ -+ def get_dir(self, name, default=None): -+ node = self.childs.get(name, None) -+ if not node or node.id & 3 != DIR: return default -+ return node -+ -+ def get_file(self, name, default=None): -+ node = self.childs.get(name, None) -+ if not node or node.id & 3 != FILE: return default -+ return node -+ -+ def get_build(self, name, default=None): -+ node = self.childs.get(name, None) -+ if not node or node.id & 3 != BUILD: return default -+ return node -+ -+ def find_resource(self, lst): -+ "Find an existing input file: either a build node declared previously or a source node" -+ if isinstance(lst, str): -+ lst = Utils.split_path(lst) -+ -+ if len(lst) == 1: -+ parent = self -+ else: -+ parent = self.find_dir(lst[:-1]) -+ if not parent: return None -+ self.__class__.bld.rescan(parent) -+ -+ name = lst[-1] -+ node = parent.childs.get(name, None) -+ if node: -+ tp = node.id & 3 -+ if tp == FILE or tp == BUILD: -+ return node -+ else: -+ return None -+ -+ tree = self.__class__.bld -+ if not name in tree.cache_dir_contents[parent.id]: -+ return None -+ -+ path = parent.abspath() + os.sep + name -+ try: -+ st = Utils.h_file(path) -+ except IOError: -+ return None -+ -+ child = self.__class__(name, parent, FILE) -+ tree.node_sigs[0][child.id] = st -+ return child -+ -+ def find_or_declare(self, lst): -+ "Used for declaring a build node representing a file being built" -+ if isinstance(lst, str): -+ lst = Utils.split_path(lst) -+ -+ if len(lst) == 1: -+ parent = self -+ else: -+ parent = self.find_dir(lst[:-1]) -+ if not parent: return None -+ self.__class__.bld.rescan(parent) -+ -+ name = lst[-1] -+ node = parent.childs.get(name, None) -+ if node: -+ tp = node.id & 3 -+ if tp != BUILD: -+ raise Utils.WafError('find_or_declare found a source file where a build file was expected %r' % '/'.join(lst)) -+ return node -+ node = self.__class__(name, parent, BUILD) -+ return node -+ -+ def find_dir(self, lst): -+ "search a folder in the filesystem" -+ -+ if isinstance(lst, str): -+ lst = Utils.split_path(lst) -+ -+ current = self -+ for name in lst: -+ self.__class__.bld.rescan(current) -+ prev = current -+ -+ if not current.parent and name == current.name: -+ continue -+ elif not name: -+ continue -+ elif name == '.': -+ continue -+ elif name == '..': -+ current = current.parent or current -+ else: -+ current = prev.childs.get(name, None) -+ if current is None: -+ dir_cont = self.__class__.bld.cache_dir_contents -+ if prev.id in dir_cont and name in dir_cont[prev.id]: -+ if not prev.name: -+ if os.sep == '/': -+ # cygwin //machine/share -+ dirname = os.sep + name -+ else: -+ # windows c: -+ dirname = name -+ else: -+ # regular path -+ dirname = prev.abspath() + os.sep + name -+ if not os.path.isdir(dirname): -+ return None -+ current = self.__class__(name, prev, DIR) -+ elif (not prev.name and len(name) == 2 and name[1] == ':') or name.startswith('\\\\'): -+ # drive letter or \\ path for windows -+ current = self.__class__(name, prev, DIR) -+ else: -+ return None -+ else: -+ if current.id & 3 != DIR: -+ return None -+ return current -+ -+ def ensure_dir_node_from_path(self, lst): -+ "used very rarely, force the construction of a branch of node instance for representing folders" -+ -+ if isinstance(lst, str): -+ lst = Utils.split_path(lst) -+ -+ current = self -+ for name in lst: -+ if not name: -+ continue -+ elif name == '.': -+ continue -+ elif name == '..': -+ current = current.parent or current -+ else: -+ prev = current -+ current = prev.childs.get(name, None) -+ if current is None: -+ current = self.__class__(name, prev, DIR) -+ return current -+ -+ def exclusive_build_node(self, path): -+ """ -+ create a hierarchy in the build dir (no source folders) for ill-behaving compilers -+ the node is not hashed, so you must do it manually -+ -+ after declaring such a node, find_dir and find_resource should work as expected -+ """ -+ lst = Utils.split_path(path) -+ name = lst[-1] -+ if len(lst) > 1: -+ parent = None -+ try: -+ parent = self.find_dir(lst[:-1]) -+ except OSError: -+ pass -+ if not parent: -+ parent = self.ensure_dir_node_from_path(lst[:-1]) -+ self.__class__.bld.rescan(parent) -+ else: -+ try: -+ self.__class__.bld.rescan(parent) -+ except OSError: -+ pass -+ else: -+ parent = self -+ -+ node = parent.childs.get(name, None) -+ if not node: -+ node = self.__class__(name, parent, BUILD) -+ -+ return node -+ -+ def path_to_parent(self, parent): -+ "path relative to a direct ancestor, as string" -+ lst = [] -+ p = self -+ h1 = parent.height() -+ h2 = p.height() -+ while h2 > h1: -+ h2 -= 1 -+ lst.append(p.name) -+ p = p.parent -+ if lst: -+ lst.reverse() -+ ret = os.path.join(*lst) -+ else: -+ ret = '' -+ return ret -+ -+ def find_ancestor(self, node): -+ "find a common ancestor for two nodes - for the shortest path in hierarchy" -+ dist = self.height() - node.height() -+ if dist < 0: return node.find_ancestor(self) -+ # now the real code -+ cand = self -+ while dist > 0: -+ cand = cand.parent -+ dist -= 1 -+ if cand == node: return cand -+ cursor = node -+ while cand.parent: -+ cand = cand.parent -+ cursor = cursor.parent -+ if cand == cursor: return cand -+ -+ def relpath_gen(self, from_node): -+ "string representing a relative path between self to another node" -+ -+ if self == from_node: return '.' -+ if from_node.parent == self: return '..' -+ -+ # up_path is '../../../' and down_path is 'dir/subdir/subdir/file' -+ ancestor = self.find_ancestor(from_node) -+ lst = [] -+ cand = self -+ while not cand.id == ancestor.id: -+ lst.append(cand.name) -+ cand = cand.parent -+ cand = from_node -+ while not cand.id == ancestor.id: -+ lst.append('..') -+ cand = cand.parent -+ lst.reverse() -+ return os.sep.join(lst) -+ -+ def nice_path(self, env=None): -+ "printed in the console, open files easily from the launch directory" -+ tree = self.__class__.bld -+ ln = tree.launch_node() -+ -+ if self.id & 3 == FILE: return self.relpath_gen(ln) -+ else: return os.path.join(tree.bldnode.relpath_gen(ln), env.variant(), self.relpath_gen(tree.srcnode)) -+ -+ def is_child_of(self, node): -+ "does this node belong to the subtree node" -+ p = self -+ diff = self.height() - node.height() -+ while diff > 0: -+ diff -= 1 -+ p = p.parent -+ return p.id == node.id -+ -+ def variant(self, env): -+ "variant, or output directory for this node, a source has for variant 0" -+ if not env: return 0 -+ elif self.id & 3 == FILE: return 0 -+ else: return env.variant() -+ -+ def height(self): -+ "amount of parents" -+ # README a cache can be added here if necessary -+ d = self -+ val = -1 -+ while d: -+ d = d.parent -+ val += 1 -+ return val -+ -+ # helpers for building things -+ -+ def abspath(self, env=None): -+ """ -+ absolute path -+ @param env [Environment]: -+ * obligatory for build nodes: build/variant/src/dir/bar.o -+ * optional for dirs: get either src/dir or build/variant/src/dir -+ * excluded for source nodes: src/dir/bar.c -+ -+ Instead of computing the absolute path each time again, -+ store the already-computed absolute paths in one of (variants+1) dictionaries: -+ bld.cache_node_abspath[0] holds absolute paths for source nodes. -+ bld.cache_node_abspath[variant] holds the absolute path for the build nodes -+ which reside in the variant given by env. -+ """ -+ ## absolute path - hot zone, so do not touch -+ -+ # less expensive -+ variant = (env and (self.id & 3 != FILE) and env.variant()) or 0 -+ -+ ret = self.__class__.bld.cache_node_abspath[variant].get(self.id, None) -+ if ret: return ret -+ -+ if not variant: -+ # source directory -+ if not self.parent: -+ val = os.sep == '/' and os.sep or '' -+ elif not self.parent.name: # root -+ val = (os.sep == '/' and os.sep or '') + self.name -+ else: -+ val = self.parent.abspath() + os.sep + self.name -+ else: -+ # build directory -+ val = os.sep.join((self.__class__.bld.bldnode.abspath(), variant, self.path_to_parent(self.__class__.bld.srcnode))) -+ self.__class__.bld.cache_node_abspath[variant][self.id] = val -+ return val -+ -+ def change_ext(self, ext): -+ "node of the same path, but with a different extension - hot zone so do not touch" -+ name = self.name -+ k = name.rfind('.') -+ if k >= 0: -+ name = name[:k] + ext -+ else: -+ name = name + ext -+ -+ return self.parent.find_or_declare([name]) -+ -+ def src_dir(self, env): -+ "src path without the file name" -+ return self.parent.srcpath(env) -+ -+ def bld_dir(self, env): -+ "build path without the file name" -+ return self.parent.bldpath(env) -+ -+ def bld_base(self, env): -+ "build path without the extension: src/dir/foo(.cpp)" -+ s = os.path.splitext(self.name)[0] -+ return os.path.join(self.bld_dir(env), s) -+ -+ def bldpath(self, env=None): -+ "path seen from the build dir default/src/foo.cpp" -+ if self.id & 3 == FILE: -+ return self.relpath_gen(self.__class__.bld.bldnode) -+ p = self.path_to_parent(self.__class__.bld.srcnode) -+ if p is not '': -+ return env.variant() + os.sep + p -+ return env.variant() -+ -+ def srcpath(self, env=None): -+ "path in the srcdir from the build dir ../src/foo.cpp" -+ if self.id & 3 == BUILD: -+ return self.bldpath(env) -+ return self.relpath_gen(self.__class__.bld.bldnode) -+ -+ def read(self, env): -+ "get the contents of a file, it is not used anywhere for the moment" -+ return Utils.readf(self.abspath(env)) -+ -+ def dir(self, env): -+ "scons-like" -+ return self.parent.abspath(env) -+ -+ def file(self): -+ "scons-like" -+ return self.name -+ -+ def file_base(self): -+ "scons-like" -+ return os.path.splitext(self.name)[0] -+ -+ def suffix(self): -+ "scons-like - hot zone so do not touch" -+ k = max(0, self.name.rfind('.')) -+ return self.name[k:] -+ -+ def find_iter_impl(self, src=True, bld=True, dir=True, accept_name=None, is_prune=None, maxdepth=25): -+ """find nodes in the filesystem hierarchy, try to instanciate the nodes passively; same gotcha as ant_glob""" -+ bld_ctx = self.__class__.bld -+ bld_ctx.rescan(self) -+ for name in bld_ctx.cache_dir_contents[self.id]: -+ if accept_name(self, name): -+ node = self.find_resource(name) -+ if node: -+ if src and node.id & 3 == FILE: -+ yield node -+ else: -+ node = self.find_dir(name) -+ if node and node.id != bld_ctx.bldnode.id: -+ if dir: -+ yield node -+ if not is_prune(self, name): -+ if maxdepth: -+ for k in node.find_iter_impl(src, bld, dir, accept_name, is_prune, maxdepth=maxdepth - 1): -+ yield k -+ else: -+ if not is_prune(self, name): -+ node = self.find_resource(name) -+ if not node: -+ # not a file, it is a dir -+ node = self.find_dir(name) -+ if node and node.id != bld_ctx.bldnode.id: -+ if maxdepth: -+ for k in node.find_iter_impl(src, bld, dir, accept_name, is_prune, maxdepth=maxdepth - 1): -+ yield k -+ -+ if bld: -+ for node in self.childs.values(): -+ if node.id == bld_ctx.bldnode.id: -+ continue -+ if node.id & 3 == BUILD: -+ if accept_name(self, node.name): -+ yield node -+ raise StopIteration -+ -+ def find_iter(self, in_pat=['*'], ex_pat=exclude_pats, prune_pat=prune_pats, src=True, bld=True, dir=False, maxdepth=25, flat=False): -+ """find nodes recursively, this returns everything but folders by default; same gotcha as ant_glob""" -+ -+ if not (src or bld or dir): -+ raise StopIteration -+ -+ if self.id & 3 != DIR: -+ raise StopIteration -+ -+ in_pat = Utils.to_list(in_pat) -+ ex_pat = Utils.to_list(ex_pat) -+ prune_pat = Utils.to_list(prune_pat) -+ -+ def accept_name(node, name): -+ for pat in ex_pat: -+ if fnmatch.fnmatchcase(name, pat): -+ return False -+ for pat in in_pat: -+ if fnmatch.fnmatchcase(name, pat): -+ return True -+ return False -+ -+ def is_prune(node, name): -+ for pat in prune_pat: -+ if fnmatch.fnmatchcase(name, pat): -+ return True -+ return False -+ -+ ret = self.find_iter_impl(src, bld, dir, accept_name, is_prune, maxdepth=maxdepth) -+ if flat: -+ return " ".join([x.relpath_gen(self) for x in ret]) -+ -+ return ret -+ -+ def ant_glob(self, *k, **kw): -+ """ -+ known gotcha: will enumerate the files, but only if the folder exists in the source directory -+ """ -+ -+ src=kw.get('src', 1) -+ bld=kw.get('bld', 0) -+ dir=kw.get('dir', 0) -+ excl = kw.get('excl', exclude_regs) -+ incl = k and k[0] or kw.get('incl', '**') -+ -+ def to_pat(s): -+ lst = Utils.to_list(s) -+ ret = [] -+ for x in lst: -+ x = x.replace('//', '/') -+ if x.endswith('/'): -+ x += '**' -+ lst2 = x.split('/') -+ accu = [] -+ for k in lst2: -+ if k == '**': -+ accu.append(k) -+ else: -+ k = k.replace('.', '[.]').replace('*', '.*').replace('?', '.') -+ k = '^%s$' % k -+ #print "pattern", k -+ accu.append(re.compile(k)) -+ ret.append(accu) -+ return ret -+ -+ def filtre(name, nn): -+ ret = [] -+ for lst in nn: -+ if not lst: -+ pass -+ elif lst[0] == '**': -+ ret.append(lst) -+ if len(lst) > 1: -+ if lst[1].match(name): -+ ret.append(lst[2:]) -+ else: -+ ret.append([]) -+ elif lst[0].match(name): -+ ret.append(lst[1:]) -+ return ret -+ -+ def accept(name, pats): -+ nacc = filtre(name, pats[0]) -+ nrej = filtre(name, pats[1]) -+ if [] in nrej: -+ nacc = [] -+ return [nacc, nrej] -+ -+ def ant_iter(nodi, maxdepth=25, pats=[]): -+ nodi.__class__.bld.rescan(nodi) -+ tmp = list(nodi.__class__.bld.cache_dir_contents[nodi.id]) -+ tmp.sort() -+ for name in tmp: -+ npats = accept(name, pats) -+ if npats and npats[0]: -+ accepted = [] in npats[0] -+ #print accepted, nodi, name -+ -+ node = nodi.find_resource(name) -+ if node and accepted: -+ if src and node.id & 3 == FILE: -+ yield node -+ else: -+ node = nodi.find_dir(name) -+ if node and node.id != nodi.__class__.bld.bldnode.id: -+ if accepted and dir: -+ yield node -+ if maxdepth: -+ for k in ant_iter(node, maxdepth=maxdepth - 1, pats=npats): -+ yield k -+ if bld: -+ for node in nodi.childs.values(): -+ if node.id == nodi.__class__.bld.bldnode.id: -+ continue -+ if node.id & 3 == BUILD: -+ npats = accept(node.name, pats) -+ if npats and npats[0] and [] in npats[0]: -+ yield node -+ raise StopIteration -+ -+ ret = [x for x in ant_iter(self, pats=[to_pat(incl), to_pat(excl)])] -+ -+ if kw.get('flat', True): -+ return " ".join([x.relpath_gen(self) for x in ret]) -+ -+ return ret -+ -+ def update_build_dir(self, env=None): -+ -+ if not env: -+ for env in bld.all_envs: -+ self.update_build_dir(env) -+ return -+ -+ path = self.abspath(env) -+ -+ lst = Utils.listdir(path) -+ try: -+ self.__class__.bld.cache_dir_contents[self.id].update(lst) -+ except KeyError: -+ self.__class__.bld.cache_dir_contents[self.id] = set(lst) -+ self.__class__.bld.cache_scanned_folders[self.id] = True -+ -+ for k in lst: -+ npath = path + os.sep + k -+ st = os.stat(npath) -+ if stat.S_ISREG(st[stat.ST_MODE]): -+ ick = self.find_or_declare(k) -+ if not (ick.id in self.__class__.bld.node_sigs[env.variant()]): -+ self.__class__.bld.node_sigs[env.variant()][ick.id] = Constants.SIG_NIL -+ elif stat.S_ISDIR(st[stat.ST_MODE]): -+ child = self.find_dir(k) -+ if not child: -+ child = self.ensure_dir_node_from_path(k) -+ child.update_build_dir(env) -+ -+ -+class Nodu(Node): -+ pass -+ -diff --git a/buildtools/wafadmin/Options.py b/buildtools/wafadmin/Options.py -new file mode 100644 -index 0000000..c9ddcfe ---- /dev/null -+++ b/buildtools/wafadmin/Options.py -@@ -0,0 +1,288 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Scott Newton, 2005 (scottn) -+# Thomas Nagy, 2006 (ita) -+ -+"Custom command-line options" -+ -+import os, sys, imp, types, tempfile, optparse -+import Logs, Utils -+from Constants import * -+ -+cmds = 'distclean configure build install clean uninstall check dist distcheck'.split() -+ -+# TODO remove in waf 1.6 the following two -+commands = {} -+is_install = False -+ -+options = {} -+arg_line = [] -+launch_dir = '' -+tooldir = '' -+lockfile = os.environ.get('WAFLOCK', '.lock-wscript') -+try: cache_global = os.path.abspath(os.environ['WAFCACHE']) -+except KeyError: cache_global = '' -+platform = Utils.unversioned_sys_platform() -+conf_file = 'conf-runs-%s-%d.pickle' % (platform, ABI) -+ -+remote_repo = ['http://waf.googlecode.com/svn/'] -+"""remote directory for the plugins""" -+ -+ -+# Such a command-line should work: JOBS=4 PREFIX=/opt/ DESTDIR=/tmp/ahoj/ waf configure -+default_prefix = os.environ.get('PREFIX') -+if not default_prefix: -+ if platform == 'win32': -+ d = tempfile.gettempdir() -+ default_prefix = d[0].upper() + d[1:] -+ # win32 preserves the case, but gettempdir does not -+ else: default_prefix = '/usr/local/' -+ -+default_jobs = os.environ.get('JOBS', -1) -+if default_jobs < 1: -+ try: -+ if 'SC_NPROCESSORS_ONLN' in os.sysconf_names: -+ default_jobs = os.sysconf('SC_NPROCESSORS_ONLN') -+ else: -+ default_jobs = int(Utils.cmd_output(['sysctl', '-n', 'hw.ncpu'])) -+ except: -+ if os.name == 'java': # platform.system() == 'Java' -+ from java.lang import Runtime -+ default_jobs = Runtime.getRuntime().availableProcessors() -+ else: -+ # environment var defined on win32 -+ default_jobs = int(os.environ.get('NUMBER_OF_PROCESSORS', 1)) -+ -+default_destdir = os.environ.get('DESTDIR', '') -+ -+def get_usage(self): -+ cmds_str = [] -+ module = Utils.g_module -+ if module: -+ # create the help messages for commands -+ tbl = module.__dict__ -+ keys = list(tbl.keys()) -+ keys.sort() -+ -+ if 'build' in tbl: -+ if not module.build.__doc__: -+ module.build.__doc__ = 'builds the project' -+ if 'configure' in tbl: -+ if not module.configure.__doc__: -+ module.configure.__doc__ = 'configures the project' -+ -+ ban = ['set_options', 'init', 'shutdown'] -+ -+ optlst = [x for x in keys if not x in ban -+ and type(tbl[x]) is type(parse_args_impl) -+ and tbl[x].__doc__ -+ and not x.startswith('_')] -+ -+ just = max([len(x) for x in optlst]) -+ -+ for x in optlst: -+ cmds_str.append(' %s: %s' % (x.ljust(just), tbl[x].__doc__)) -+ ret = '\n'.join(cmds_str) -+ else: -+ ret = ' '.join(cmds) -+ return '''waf [command] [options] -+ -+Main commands (example: ./waf build -j4) -+%s -+''' % ret -+ -+ -+setattr(optparse.OptionParser, 'get_usage', get_usage) -+ -+def create_parser(module=None): -+ Logs.debug('options: create_parser is called') -+ parser = optparse.OptionParser(conflict_handler="resolve", version = 'waf %s (%s)' % (WAFVERSION, WAFREVISION)) -+ -+ parser.formatter.width = Utils.get_term_cols() -+ p = parser.add_option -+ -+ p('-j', '--jobs', -+ type = 'int', -+ default = default_jobs, -+ help = 'amount of parallel jobs (%r)' % default_jobs, -+ dest = 'jobs') -+ -+ p('-k', '--keep', -+ action = 'store_true', -+ default = False, -+ help = 'keep running happily on independent task groups', -+ dest = 'keep') -+ -+ p('-v', '--verbose', -+ action = 'count', -+ default = 0, -+ help = 'verbosity level -v -vv or -vvv [default: 0]', -+ dest = 'verbose') -+ -+ p('--nocache', -+ action = 'store_true', -+ default = False, -+ help = 'ignore the WAFCACHE (if set)', -+ dest = 'nocache') -+ -+ p('--zones', -+ action = 'store', -+ default = '', -+ help = 'debugging zones (task_gen, deps, tasks, etc)', -+ dest = 'zones') -+ -+ p('-p', '--progress', -+ action = 'count', -+ default = 0, -+ help = '-p: progress bar; -pp: ide output', -+ dest = 'progress_bar') -+ -+ p('--targets', -+ action = 'store', -+ default = '', -+ help = 'build given task generators, e.g. "target1,target2"', -+ dest = 'compile_targets') -+ -+ gr = optparse.OptionGroup(parser, 'configuration options') -+ parser.add_option_group(gr) -+ gr.add_option('-b', '--blddir', -+ action = 'store', -+ default = '', -+ help = 'out dir for the project (configuration)', -+ dest = 'blddir') -+ gr.add_option('-s', '--srcdir', -+ action = 'store', -+ default = '', -+ help = 'top dir for the project (configuration)', -+ dest = 'srcdir') -+ gr.add_option('--prefix', -+ help = 'installation prefix (configuration) [default: %r]' % default_prefix, -+ default = default_prefix, -+ dest = 'prefix') -+ -+ gr.add_option('--download', -+ action = 'store_true', -+ default = False, -+ help = 'try to download the tools if missing', -+ dest = 'download') -+ -+ gr = optparse.OptionGroup(parser, 'installation options') -+ parser.add_option_group(gr) -+ gr.add_option('--destdir', -+ help = 'installation root [default: %r]' % default_destdir, -+ default = default_destdir, -+ dest = 'destdir') -+ gr.add_option('-f', '--force', -+ action = 'store_true', -+ default = False, -+ help = 'force file installation', -+ dest = 'force') -+ -+ return parser -+ -+def parse_args_impl(parser, _args=None): -+ global options, commands, arg_line -+ (options, args) = parser.parse_args(args=_args) -+ -+ arg_line = args -+ #arg_line = args[:] # copy -+ -+ # By default, 'waf' is equivalent to 'waf build' -+ commands = {} -+ for var in cmds: commands[var] = 0 -+ if not args: -+ commands['build'] = 1 -+ args.append('build') -+ -+ # Parse the command arguments -+ for arg in args: -+ commands[arg] = True -+ -+ # the check thing depends on the build -+ if 'check' in args: -+ idx = args.index('check') -+ try: -+ bidx = args.index('build') -+ if bidx > idx: -+ raise ValueError('build before check') -+ except ValueError, e: -+ args.insert(idx, 'build') -+ -+ if args[0] != 'init': -+ args.insert(0, 'init') -+ -+ # TODO -k => -j0 -+ if options.keep: options.jobs = 1 -+ if options.jobs < 1: options.jobs = 1 -+ -+ if 'install' in sys.argv or 'uninstall' in sys.argv: -+ # absolute path only if set -+ options.destdir = options.destdir and os.path.abspath(os.path.expanduser(options.destdir)) -+ -+ Logs.verbose = options.verbose -+ Logs.init_log() -+ -+ if options.zones: -+ Logs.zones = options.zones.split(',') -+ if not Logs.verbose: Logs.verbose = 1 -+ elif Logs.verbose > 0: -+ Logs.zones = ['runner'] -+ if Logs.verbose > 2: -+ Logs.zones = ['*'] -+ -+# TODO waf 1.6 -+# 1. rename the class to OptionsContext -+# 2. instead of a class attribute, use a module (static 'parser') -+# 3. parse_args_impl was made in times when we did not know about binding new methods to classes -+ -+class Handler(Utils.Context): -+ """loads wscript modules in folders for adding options -+ This class should be named 'OptionsContext' -+ A method named 'recurse' is bound when used by the module Scripting""" -+ -+ parser = None -+ # make it possible to access the reference, like Build.bld -+ -+ def __init__(self, module=None): -+ self.parser = create_parser(module) -+ self.cwd = os.getcwd() -+ Handler.parser = self -+ -+ def add_option(self, *k, **kw): -+ self.parser.add_option(*k, **kw) -+ -+ def add_option_group(self, *k, **kw): -+ return self.parser.add_option_group(*k, **kw) -+ -+ def get_option_group(self, opt_str): -+ return self.parser.get_option_group(opt_str) -+ -+ def sub_options(self, *k, **kw): -+ if not k: raise Utils.WscriptError('folder expected') -+ self.recurse(k[0], name='set_options') -+ -+ def tool_options(self, *k, **kw): -+ Utils.python_24_guard() -+ -+ if not k[0]: -+ raise Utils.WscriptError('invalid tool_options call %r %r' % (k, kw)) -+ tools = Utils.to_list(k[0]) -+ -+ # TODO waf 1.6 remove the global variable tooldir -+ path = Utils.to_list(kw.get('tdir', kw.get('tooldir', tooldir))) -+ -+ for tool in tools: -+ tool = tool.replace('++', 'xx') -+ if tool == 'java': tool = 'javaw' -+ if tool.lower() == 'unittest': tool = 'unittestw' -+ module = Utils.load_tool(tool, path) -+ try: -+ fun = module.set_options -+ except AttributeError: -+ pass -+ else: -+ fun(kw.get('option_group', self)) -+ -+ def parse_args(self, args=None): -+ parse_args_impl(self.parser, args) -+ -diff --git a/buildtools/wafadmin/Runner.py b/buildtools/wafadmin/Runner.py -new file mode 100644 -index 0000000..94db0fb ---- /dev/null -+++ b/buildtools/wafadmin/Runner.py -@@ -0,0 +1,236 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2005-2008 (ita) -+ -+"Execute the tasks" -+ -+import os, sys, random, time, threading, traceback -+try: from Queue import Queue -+except ImportError: from queue import Queue -+import Build, Utils, Logs, Options -+from Logs import debug, error -+from Constants import * -+ -+GAP = 15 -+ -+run_old = threading.Thread.run -+def run(*args, **kwargs): -+ try: -+ run_old(*args, **kwargs) -+ except (KeyboardInterrupt, SystemExit): -+ raise -+ except: -+ sys.excepthook(*sys.exc_info()) -+threading.Thread.run = run -+ -+def process_task(tsk): -+ -+ m = tsk.master -+ if m.stop: -+ m.out.put(tsk) -+ return -+ -+ try: -+ tsk.generator.bld.printout(tsk.display()) -+ if tsk.__class__.stat: ret = tsk.__class__.stat(tsk) -+ # actual call to task's run() function -+ else: ret = tsk.call_run() -+ except Exception, e: -+ tsk.err_msg = Utils.ex_stack() -+ tsk.hasrun = EXCEPTION -+ -+ # TODO cleanup -+ m.error_handler(tsk) -+ m.out.put(tsk) -+ return -+ -+ if ret: -+ tsk.err_code = ret -+ tsk.hasrun = CRASHED -+ else: -+ try: -+ tsk.post_run() -+ except Utils.WafError: -+ pass -+ except Exception: -+ tsk.err_msg = Utils.ex_stack() -+ tsk.hasrun = EXCEPTION -+ else: -+ tsk.hasrun = SUCCESS -+ if tsk.hasrun != SUCCESS: -+ m.error_handler(tsk) -+ -+ m.out.put(tsk) -+ -+class TaskConsumer(threading.Thread): -+ ready = Queue(0) -+ consumers = [] -+ -+ def __init__(self): -+ threading.Thread.__init__(self) -+ self.setDaemon(1) -+ self.start() -+ -+ def run(self): -+ try: -+ self.loop() -+ except: -+ pass -+ -+ def loop(self): -+ while 1: -+ tsk = TaskConsumer.ready.get() -+ process_task(tsk) -+ -+class Parallel(object): -+ """ -+ keep the consumer threads busy, and avoid consuming cpu cycles -+ when no more tasks can be added (end of the build, etc) -+ """ -+ def __init__(self, bld, j=2): -+ -+ # number of consumers -+ self.numjobs = j -+ -+ self.manager = bld.task_manager -+ self.manager.current_group = 0 -+ -+ self.total = self.manager.total() -+ -+ # tasks waiting to be processed - IMPORTANT -+ self.outstanding = [] -+ self.maxjobs = MAXJOBS -+ -+ # tasks that are awaiting for another task to complete -+ self.frozen = [] -+ -+ # tasks returned by the consumers -+ self.out = Queue(0) -+ -+ self.count = 0 # tasks not in the producer area -+ -+ self.processed = 1 # progress indicator -+ -+ self.stop = False # error condition to stop the build -+ self.error = False # error flag -+ -+ def get_next(self): -+ "override this method to schedule the tasks in a particular order" -+ if not self.outstanding: -+ return None -+ return self.outstanding.pop(0) -+ -+ def postpone(self, tsk): -+ "override this method to schedule the tasks in a particular order" -+ # TODO consider using a deque instead -+ if random.randint(0, 1): -+ self.frozen.insert(0, tsk) -+ else: -+ self.frozen.append(tsk) -+ -+ def refill_task_list(self): -+ "called to set the next group of tasks" -+ -+ while self.count > self.numjobs + GAP or self.count >= self.maxjobs: -+ self.get_out() -+ -+ while not self.outstanding: -+ if self.count: -+ self.get_out() -+ -+ if self.frozen: -+ self.outstanding += self.frozen -+ self.frozen = [] -+ elif not self.count: -+ (jobs, tmp) = self.manager.get_next_set() -+ if jobs != None: self.maxjobs = jobs -+ if tmp: self.outstanding += tmp -+ break -+ -+ def get_out(self): -+ "the tasks that are put to execute are all collected using get_out" -+ ret = self.out.get() -+ self.manager.add_finished(ret) -+ if not self.stop and getattr(ret, 'more_tasks', None): -+ self.outstanding += ret.more_tasks -+ self.total += len(ret.more_tasks) -+ self.count -= 1 -+ -+ def error_handler(self, tsk): -+ "by default, errors make the build stop (not thread safe so be careful)" -+ if not Options.options.keep: -+ self.stop = True -+ self.error = True -+ -+ def start(self): -+ "execute the tasks" -+ -+ if TaskConsumer.consumers: -+ # the worker pool is usually loaded lazily (see below) -+ # in case it is re-used with a different value of numjobs: -+ while len(TaskConsumer.consumers) < self.numjobs: -+ TaskConsumer.consumers.append(TaskConsumer()) -+ -+ while not self.stop: -+ -+ self.refill_task_list() -+ -+ # consider the next task -+ tsk = self.get_next() -+ if not tsk: -+ if self.count: -+ # tasks may add new ones after they are run -+ continue -+ else: -+ # no tasks to run, no tasks running, time to exit -+ break -+ -+ if tsk.hasrun: -+ # if the task is marked as "run", just skip it -+ self.processed += 1 -+ self.manager.add_finished(tsk) -+ continue -+ -+ try: -+ st = tsk.runnable_status() -+ except Exception, e: -+ self.processed += 1 -+ if self.stop and not Options.options.keep: -+ tsk.hasrun = SKIPPED -+ self.manager.add_finished(tsk) -+ continue -+ self.error_handler(tsk) -+ self.manager.add_finished(tsk) -+ tsk.hasrun = EXCEPTION -+ tsk.err_msg = Utils.ex_stack() -+ continue -+ -+ if st == ASK_LATER: -+ self.postpone(tsk) -+ elif st == SKIP_ME: -+ self.processed += 1 -+ tsk.hasrun = SKIPPED -+ self.manager.add_finished(tsk) -+ else: -+ # run me: put the task in ready queue -+ tsk.position = (self.processed, self.total) -+ self.count += 1 -+ tsk.master = self -+ self.processed += 1 -+ -+ if self.numjobs == 1: -+ process_task(tsk) -+ else: -+ TaskConsumer.ready.put(tsk) -+ # create the consumer threads only if there is something to consume -+ if not TaskConsumer.consumers: -+ TaskConsumer.consumers = [TaskConsumer() for i in xrange(self.numjobs)] -+ -+ # self.count represents the tasks that have been made available to the consumer threads -+ # collect all the tasks after an error else the message may be incomplete -+ while self.error and self.count: -+ self.get_out() -+ -+ #print loop -+ assert (self.count == 0 or self.stop) -+ -diff --git a/buildtools/wafadmin/Scripting.py b/buildtools/wafadmin/Scripting.py -new file mode 100644 -index 0000000..d975bd9 ---- /dev/null -+++ b/buildtools/wafadmin/Scripting.py -@@ -0,0 +1,586 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2005 (ita) -+ -+"Module called for configuring, compiling and installing targets" -+ -+import os, sys, shutil, traceback, datetime, inspect, errno -+ -+import Utils, Configure, Build, Logs, Options, Environment, Task -+from Logs import error, warn, info -+from Constants import * -+ -+g_gz = 'bz2' -+commands = [] -+ -+def prepare_impl(t, cwd, ver, wafdir): -+ Options.tooldir = [t] -+ Options.launch_dir = cwd -+ -+ # some command-line options can be processed immediately -+ if '--version' in sys.argv: -+ opt_obj = Options.Handler() -+ opt_obj.curdir = cwd -+ opt_obj.parse_args() -+ sys.exit(0) -+ -+ # now find the wscript file -+ msg1 = 'Waf: Please run waf from a directory containing a file named "%s" or run distclean' % WSCRIPT_FILE -+ -+ # in theory projects can be configured in an autotool-like manner: -+ # mkdir build && cd build && ../waf configure && ../waf -+ build_dir_override = None -+ candidate = None -+ -+ lst = os.listdir(cwd) -+ -+ search_for_candidate = True -+ if WSCRIPT_FILE in lst: -+ candidate = cwd -+ -+ elif 'configure' in sys.argv and not WSCRIPT_BUILD_FILE in lst: -+ # autotool-like configuration -+ calldir = os.path.abspath(os.path.dirname(sys.argv[0])) -+ if WSCRIPT_FILE in os.listdir(calldir): -+ candidate = calldir -+ search_for_candidate = False -+ else: -+ error('arg[0] directory does not contain a wscript file') -+ sys.exit(1) -+ build_dir_override = cwd -+ -+ # climb up to find a script if it is not found -+ while search_for_candidate: -+ if len(cwd) <= 3: -+ break # stop at / or c: -+ dirlst = os.listdir(cwd) -+ if WSCRIPT_FILE in dirlst: -+ candidate = cwd -+ if 'configure' in sys.argv and candidate: -+ break -+ if Options.lockfile in dirlst: -+ env = Environment.Environment() -+ try: -+ env.load(os.path.join(cwd, Options.lockfile)) -+ except: -+ error('could not load %r' % Options.lockfile) -+ try: -+ os.stat(env['cwd']) -+ except: -+ candidate = cwd -+ else: -+ candidate = env['cwd'] -+ break -+ cwd = os.path.dirname(cwd) # climb up -+ -+ if not candidate: -+ # check if the user only wanted to display the help -+ if '-h' in sys.argv or '--help' in sys.argv: -+ warn('No wscript file found: the help message may be incomplete') -+ opt_obj = Options.Handler() -+ opt_obj.curdir = cwd -+ opt_obj.parse_args() -+ else: -+ error(msg1) -+ sys.exit(0) -+ -+ # We have found wscript, but there is no guarantee that it is valid -+ try: -+ os.chdir(candidate) -+ except OSError: -+ raise Utils.WafError("the folder %r is unreadable" % candidate) -+ -+ # define the main module containing the functions init, shutdown, .. -+ Utils.set_main_module(os.path.join(candidate, WSCRIPT_FILE)) -+ -+ if build_dir_override: -+ d = getattr(Utils.g_module, BLDDIR, None) -+ if d: -+ # test if user has set the blddir in wscript. -+ msg = ' Overriding build directory %s with %s' % (d, build_dir_override) -+ warn(msg) -+ Utils.g_module.blddir = build_dir_override -+ -+ # bind a few methods and classes by default -+ -+ def set_def(obj, name=''): -+ n = name or obj.__name__ -+ if not n in Utils.g_module.__dict__: -+ setattr(Utils.g_module, n, obj) -+ -+ for k in [dist, distclean, distcheck, clean, install, uninstall]: -+ set_def(k) -+ -+ set_def(Configure.ConfigurationContext, 'configure_context') -+ -+ for k in ['build', 'clean', 'install', 'uninstall']: -+ set_def(Build.BuildContext, k + '_context') -+ -+ # now parse the options from the user wscript file -+ opt_obj = Options.Handler(Utils.g_module) -+ opt_obj.curdir = candidate -+ try: -+ f = Utils.g_module.set_options -+ except AttributeError: -+ pass -+ else: -+ opt_obj.sub_options(['']) -+ opt_obj.parse_args() -+ -+ if not 'init' in Utils.g_module.__dict__: -+ Utils.g_module.init = Utils.nada -+ if not 'shutdown' in Utils.g_module.__dict__: -+ Utils.g_module.shutdown = Utils.nada -+ -+ main() -+ -+def prepare(t, cwd, ver, wafdir): -+ if WAFVERSION != ver: -+ msg = 'Version mismatch: waf %s <> wafadmin %s (wafdir %s)' % (ver, WAFVERSION, wafdir) -+ print('\033[91mError: %s\033[0m' % msg) -+ sys.exit(1) -+ -+ #""" -+ try: -+ prepare_impl(t, cwd, ver, wafdir) -+ except Utils.WafError, e: -+ error(str(e)) -+ sys.exit(1) -+ except KeyboardInterrupt: -+ Utils.pprint('RED', 'Interrupted') -+ sys.exit(68) -+ """ -+ import cProfile, pstats -+ cProfile.runctx("import Scripting; Scripting.prepare_impl(t, cwd, ver, wafdir)", {}, -+ {'t': t, 'cwd':cwd, 'ver':ver, 'wafdir':wafdir}, -+ 'profi.txt') -+ p = pstats.Stats('profi.txt') -+ p.sort_stats('time').print_stats(45) -+ #""" -+ -+def main(): -+ global commands -+ commands = Options.arg_line[:] -+ -+ while commands: -+ x = commands.pop(0) -+ -+ ini = datetime.datetime.now() -+ if x == 'configure': -+ fun = configure -+ elif x == 'build': -+ fun = build -+ else: -+ fun = getattr(Utils.g_module, x, None) -+ -+ if not fun: -+ raise Utils.WscriptError('No such command %r' % x) -+ -+ ctx = getattr(Utils.g_module, x + '_context', Utils.Context)() -+ -+ if x in ['init', 'shutdown', 'dist', 'distclean', 'distcheck']: -+ # compatibility TODO remove in waf 1.6 -+ try: -+ fun(ctx) -+ except TypeError: -+ fun() -+ else: -+ fun(ctx) -+ -+ ela = '' -+ if not Options.options.progress_bar: -+ ela = ' (%s)' % Utils.get_elapsed_time(ini) -+ -+ if x != 'init' and x != 'shutdown': -+ info('%r finished successfully%s' % (x, ela)) -+ -+ if not commands and x != 'shutdown': -+ commands.append('shutdown') -+ -+def configure(conf): -+ -+ src = getattr(Options.options, SRCDIR, None) -+ if not src: src = getattr(Utils.g_module, SRCDIR, None) -+ if not src: src = getattr(Utils.g_module, 'top', None) -+ if not src: -+ src = '.' -+ incomplete_src = 1 -+ src = os.path.abspath(src) -+ -+ bld = getattr(Options.options, BLDDIR, None) -+ if not bld: bld = getattr(Utils.g_module, BLDDIR, None) -+ if not bld: bld = getattr(Utils.g_module, 'out', None) -+ if not bld: -+ bld = 'build' -+ incomplete_bld = 1 -+ if bld == '.': -+ raise Utils.WafError('Setting blddir="." may cause distclean problems') -+ bld = os.path.abspath(bld) -+ -+ try: os.makedirs(bld) -+ except OSError: pass -+ -+ # It is not possible to compile specific targets in the configuration -+ # this may cause configuration errors if autoconfig is set -+ targets = Options.options.compile_targets -+ Options.options.compile_targets = None -+ Options.is_install = False -+ -+ conf.srcdir = src -+ conf.blddir = bld -+ conf.post_init() -+ -+ if 'incomplete_src' in vars(): -+ conf.check_message_1('Setting srcdir to') -+ conf.check_message_2(src) -+ if 'incomplete_bld' in vars(): -+ conf.check_message_1('Setting blddir to') -+ conf.check_message_2(bld) -+ -+ # calling to main wscript's configure() -+ conf.sub_config(['']) -+ -+ conf.store() -+ -+ # this will write a configure lock so that subsequent builds will -+ # consider the current path as the root directory (see prepare_impl). -+ # to remove: use 'waf distclean' -+ env = Environment.Environment() -+ env[BLDDIR] = bld -+ env[SRCDIR] = src -+ env['argv'] = sys.argv -+ env['commands'] = Options.commands -+ env['options'] = Options.options.__dict__ -+ -+ # conf.hash & conf.files hold wscript files paths and hash -+ # (used only by Configure.autoconfig) -+ env['hash'] = conf.hash -+ env['files'] = conf.files -+ env['environ'] = dict(conf.environ) -+ env['cwd'] = os.path.split(Utils.g_module.root_path)[0] -+ -+ if Utils.g_module.root_path != src: -+ # in case the source dir is somewhere else -+ env.store(os.path.join(src, Options.lockfile)) -+ -+ env.store(Options.lockfile) -+ -+ Options.options.compile_targets = targets -+ -+def clean(bld): -+ '''removes the build files''' -+ try: -+ proj = Environment.Environment(Options.lockfile) -+ except IOError: -+ raise Utils.WafError('Nothing to clean (project not configured)') -+ -+ bld.load_dirs(proj[SRCDIR], proj[BLDDIR]) -+ bld.load_envs() -+ -+ bld.is_install = 0 # False -+ -+ # read the scripts - and set the path to the wscript path (useful for srcdir='/foo/bar') -+ bld.add_subdirs([os.path.split(Utils.g_module.root_path)[0]]) -+ -+ try: -+ bld.clean() -+ finally: -+ bld.save() -+ -+def check_configured(bld): -+ if not Configure.autoconfig: -+ return bld -+ -+ conf_cls = getattr(Utils.g_module, 'configure_context', Utils.Context) -+ bld_cls = getattr(Utils.g_module, 'build_context', Utils.Context) -+ -+ def reconf(proj): -+ back = (Options.commands, Options.options.__dict__, Logs.zones, Logs.verbose) -+ -+ Options.commands = proj['commands'] -+ Options.options.__dict__ = proj['options'] -+ conf = conf_cls() -+ conf.environ = proj['environ'] -+ configure(conf) -+ -+ (Options.commands, Options.options.__dict__, Logs.zones, Logs.verbose) = back -+ -+ try: -+ proj = Environment.Environment(Options.lockfile) -+ except IOError: -+ conf = conf_cls() -+ configure(conf) -+ else: -+ try: -+ bld = bld_cls() -+ bld.load_dirs(proj[SRCDIR], proj[BLDDIR]) -+ bld.load_envs() -+ except Utils.WafError: -+ reconf(proj) -+ return bld_cls() -+ -+ try: -+ proj = Environment.Environment(Options.lockfile) -+ except IOError: -+ raise Utils.WafError('Auto-config: project does not configure (bug)') -+ -+ h = 0 -+ try: -+ for file in proj['files']: -+ if file.endswith('configure'): -+ h = hash((h, Utils.readf(file))) -+ else: -+ mod = Utils.load_module(file) -+ h = hash((h, mod.waf_hash_val)) -+ except (OSError, IOError): -+ warn('Reconfiguring the project: a file is unavailable') -+ reconf(proj) -+ else: -+ if (h != proj['hash']): -+ warn('Reconfiguring the project: the configuration has changed') -+ reconf(proj) -+ -+ return bld_cls() -+ -+def install(bld): -+ '''installs the build files''' -+ bld = check_configured(bld) -+ -+ Options.commands['install'] = True -+ Options.commands['uninstall'] = False -+ Options.is_install = True -+ -+ bld.is_install = INSTALL -+ -+ build_impl(bld) -+ bld.install() -+ -+def uninstall(bld): -+ '''removes the installed files''' -+ Options.commands['install'] = False -+ Options.commands['uninstall'] = True -+ Options.is_install = True -+ -+ bld.is_install = UNINSTALL -+ -+ try: -+ def runnable_status(self): -+ return SKIP_ME -+ setattr(Task.Task, 'runnable_status_back', Task.Task.runnable_status) -+ setattr(Task.Task, 'runnable_status', runnable_status) -+ -+ build_impl(bld) -+ bld.install() -+ finally: -+ setattr(Task.Task, 'runnable_status', Task.Task.runnable_status_back) -+ -+def build(bld): -+ bld = check_configured(bld) -+ -+ Options.commands['install'] = False -+ Options.commands['uninstall'] = False -+ Options.is_install = False -+ -+ bld.is_install = 0 # False -+ -+ return build_impl(bld) -+ -+def build_impl(bld): -+ # compile the project and/or install the files -+ try: -+ proj = Environment.Environment(Options.lockfile) -+ except IOError: -+ raise Utils.WafError("Project not configured (run 'waf configure' first)") -+ -+ bld.load_dirs(proj[SRCDIR], proj[BLDDIR]) -+ bld.load_envs() -+ -+ info("Waf: Entering directory `%s'" % bld.bldnode.abspath()) -+ bld.add_subdirs([os.path.split(Utils.g_module.root_path)[0]]) -+ -+ # execute something immediately before the build starts -+ bld.pre_build() -+ -+ try: -+ bld.compile() -+ finally: -+ if Options.options.progress_bar: print('') -+ info("Waf: Leaving directory `%s'" % bld.bldnode.abspath()) -+ -+ # execute something immediately after a successful build -+ bld.post_build() -+ -+ bld.install() -+ -+excludes = '.bzr .bzrignore .git .gitignore .svn CVS .cvsignore .arch-ids {arch} SCCS BitKeeper .hg _MTN _darcs Makefile Makefile.in config.log .gitattributes .hgignore .hgtags'.split() -+dist_exts = '~ .rej .orig .pyc .pyo .bak .tar.bz2 tar.gz .zip .swp'.split() -+def dont_dist(name, src, build_dir): -+ global excludes, dist_exts -+ -+ if (name.startswith(',,') -+ or name.startswith('++') -+ or name.startswith('.waf') -+ or (src == '.' and name == Options.lockfile) -+ or name in excludes -+ or name == build_dir -+ ): -+ return True -+ -+ for ext in dist_exts: -+ if name.endswith(ext): -+ return True -+ -+ return False -+ -+# like shutil.copytree -+# exclude files and to raise exceptions immediately -+def copytree(src, dst, build_dir): -+ names = os.listdir(src) -+ os.makedirs(dst) -+ for name in names: -+ srcname = os.path.join(src, name) -+ dstname = os.path.join(dst, name) -+ -+ if dont_dist(name, src, build_dir): -+ continue -+ -+ if os.path.isdir(srcname): -+ copytree(srcname, dstname, build_dir) -+ else: -+ shutil.copy2(srcname, dstname) -+ -+# TODO in waf 1.6, change this method if "srcdir == blddir" is allowed -+def distclean(ctx=None): -+ '''removes the build directory''' -+ global commands -+ lst = os.listdir('.') -+ for f in lst: -+ if f == Options.lockfile: -+ try: -+ proj = Environment.Environment(f) -+ except: -+ Logs.warn('could not read %r' % f) -+ continue -+ -+ try: -+ shutil.rmtree(proj[BLDDIR]) -+ except IOError: -+ pass -+ except OSError, e: -+ if e.errno != errno.ENOENT: -+ Logs.warn('project %r cannot be removed' % proj[BLDDIR]) -+ -+ try: -+ os.remove(f) -+ except OSError, e: -+ if e.errno != errno.ENOENT: -+ Logs.warn('file %r cannot be removed' % f) -+ -+ # remove the local waf cache -+ if not commands and f.startswith('.waf'): -+ shutil.rmtree(f, ignore_errors=True) -+ -+# FIXME waf 1.6 a unique ctx parameter, and remove the optional appname and version -+def dist(appname='', version=''): -+ '''makes a tarball for redistributing the sources''' -+ # return return (distdirname, tarballname) -+ import tarfile -+ -+ if not appname: appname = Utils.g_module.APPNAME -+ if not version: version = Utils.g_module.VERSION -+ -+ tmp_folder = appname + '-' + version -+ if g_gz in ['gz', 'bz2']: -+ arch_name = tmp_folder + '.tar.' + g_gz -+ else: -+ arch_name = tmp_folder + '.' + 'zip' -+ -+ # remove the previous dir -+ try: -+ shutil.rmtree(tmp_folder) -+ except (OSError, IOError): -+ pass -+ -+ # remove the previous archive -+ try: -+ os.remove(arch_name) -+ except (OSError, IOError): -+ pass -+ -+ # copy the files into the temporary folder -+ blddir = getattr(Utils.g_module, BLDDIR, None) -+ if not blddir: -+ blddir = getattr(Utils.g_module, 'out', None) -+ copytree('.', tmp_folder, blddir) -+ -+ # undocumented hook for additional cleanup -+ dist_hook = getattr(Utils.g_module, 'dist_hook', None) -+ if dist_hook: -+ back = os.getcwd() -+ os.chdir(tmp_folder) -+ try: -+ dist_hook() -+ finally: -+ # go back to the root directory -+ os.chdir(back) -+ -+ if g_gz in ['gz', 'bz2']: -+ tar = tarfile.open(arch_name, 'w:' + g_gz) -+ tar.add(tmp_folder) -+ tar.close() -+ else: -+ Utils.zip_folder(tmp_folder, arch_name, tmp_folder) -+ -+ try: from hashlib import sha1 as sha -+ except ImportError: from sha import sha -+ try: -+ digest = " (sha=%r)" % sha(Utils.readf(arch_name)).hexdigest() -+ except: -+ digest = '' -+ -+ info('New archive created: %s%s' % (arch_name, digest)) -+ -+ if os.path.exists(tmp_folder): shutil.rmtree(tmp_folder) -+ return arch_name -+ -+# FIXME waf 1.6 a unique ctx parameter, and remove the optional appname and version -+def distcheck(appname='', version='', subdir=''): -+ '''checks if the sources compile (tarball from 'dist')''' -+ import tempfile, tarfile -+ -+ if not appname: appname = Utils.g_module.APPNAME -+ if not version: version = Utils.g_module.VERSION -+ -+ waf = os.path.abspath(sys.argv[0]) -+ tarball = dist(appname, version) -+ -+ path = appname + '-' + version -+ -+ # remove any previous instance -+ if os.path.exists(path): -+ shutil.rmtree(path) -+ -+ t = tarfile.open(tarball) -+ for x in t: t.extract(x) -+ t.close() -+ -+ # build_path is the directory for the waf invocation -+ if subdir: -+ build_path = os.path.join(path, subdir) -+ else: -+ build_path = path -+ -+ instdir = tempfile.mkdtemp('.inst', '%s-%s' % (appname, version)) -+ ret = Utils.pproc.Popen([waf, 'configure', 'build', 'install', 'uninstall', '--destdir=' + instdir], cwd=build_path).wait() -+ if ret: -+ raise Utils.WafError('distcheck failed with code %i' % ret) -+ -+ if os.path.exists(instdir): -+ raise Utils.WafError('distcheck succeeded, but files were left in %s' % instdir) -+ -+ shutil.rmtree(path) -+ -+# FIXME remove in Waf 1.6 (kept for compatibility) -+def add_subdir(dir, bld): -+ bld.recurse(dir, 'build') -+ -diff --git a/buildtools/wafadmin/Task.py b/buildtools/wafadmin/Task.py -new file mode 100644 -index 0000000..5cda2ec ---- /dev/null -+++ b/buildtools/wafadmin/Task.py -@@ -0,0 +1,1200 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2005-2008 (ita) -+ -+""" -+Running tasks in parallel is a simple problem, but in practice it is more complicated: -+* dependencies discovered during the build (dynamic task creation) -+* dependencies discovered after files are compiled -+* the amount of tasks and dependencies (graph size) can be huge -+ -+This is why the dependency management is split on three different levels: -+1. groups of tasks that run all after another group of tasks -+2. groups of tasks that can be run in parallel -+3. tasks that can run in parallel, but with possible unknown ad-hoc dependencies -+ -+The point #1 represents a strict sequential order between groups of tasks, for example a compiler is produced -+and used to compile the rest, whereas #2 and #3 represent partial order constraints where #2 applies to the kind of task -+and #3 applies to the task instances. -+ -+#1 is held by the task manager: ordered list of TaskGroups (see bld.add_group) -+#2 is held by the task groups and the task types: precedence after/before (topological sort), -+ and the constraints extracted from file extensions -+#3 is held by the tasks individually (attribute run_after), -+ and the scheduler (Runner.py) use Task::runnable_status to reorder the tasks -+ -+-- -+ -+To try, use something like this in your code: -+import Constants, Task -+Task.algotype = Constants.MAXPARALLEL -+ -+-- -+ -+There are two concepts with the tasks (individual units of change): -+* dependency (if 1 is recompiled, recompile 2) -+* order (run 2 after 1) -+ -+example 1: if t1 depends on t2 and t2 depends on t3 it is not necessary to make t1 depend on t3 (dependency is transitive) -+example 2: if t1 depends on a node produced by t2, it is not immediately obvious that t1 must run after t2 (order is not obvious) -+ -+The role of the Task Manager is to give the tasks in order (groups of task that may be run in parallel one after the other) -+ -+""" -+ -+import os, shutil, sys, re, random, datetime, tempfile, shlex -+from Utils import md5 -+import Build, Runner, Utils, Node, Logs, Options -+from Logs import debug, warn, error -+from Constants import * -+ -+algotype = NORMAL -+#algotype = JOBCONTROL -+#algotype = MAXPARALLEL -+ -+COMPILE_TEMPLATE_SHELL = ''' -+def f(task): -+ env = task.env -+ wd = getattr(task, 'cwd', None) -+ p = env.get_flat -+ cmd = \'\'\' %s \'\'\' % s -+ return task.exec_command(cmd, cwd=wd) -+''' -+ -+COMPILE_TEMPLATE_NOSHELL = ''' -+def f(task): -+ env = task.env -+ wd = getattr(task, 'cwd', None) -+ def to_list(xx): -+ if isinstance(xx, str): return [xx] -+ return xx -+ lst = [] -+ %s -+ lst = [x for x in lst if x] -+ return task.exec_command(lst, cwd=wd) -+''' -+ -+ -+""" -+Enable different kind of dependency algorithms: -+1 make groups: first compile all cpps and then compile all links (NORMAL) -+2 parallelize all (each link task run after its dependencies) (MAXPARALLEL) -+3 like 1 but provide additional constraints for the parallelization (MAXJOBS) -+ -+In theory 1. will be faster than 2 for waf, but might be slower for builds -+The scheme 2 will not allow for running tasks one by one so it can cause disk thrashing on huge builds -+""" -+ -+file_deps = Utils.nada -+""" -+Additional dependency pre-check may be added by replacing the function file_deps. -+e.g. extract_outputs, extract_deps below. -+""" -+ -+class TaskManager(object): -+ """The manager is attached to the build object, it holds a list of TaskGroup""" -+ def __init__(self): -+ self.groups = [] -+ self.tasks_done = [] -+ self.current_group = 0 -+ self.groups_names = {} -+ -+ def group_name(self, g): -+ """name for the group g (utility)""" -+ if not isinstance(g, TaskGroup): -+ g = self.groups[g] -+ for x in self.groups_names: -+ if id(self.groups_names[x]) == id(g): -+ return x -+ return '' -+ -+ def group_idx(self, tg): -+ """group the task generator tg is in""" -+ se = id(tg) -+ for i in range(len(self.groups)): -+ g = self.groups[i] -+ for t in g.tasks_gen: -+ if id(t) == se: -+ return i -+ return None -+ -+ def get_next_set(self): -+ """return the next set of tasks to execute -+ the first parameter is the maximum amount of parallelization that may occur""" -+ ret = None -+ while not ret and self.current_group < len(self.groups): -+ ret = self.groups[self.current_group].get_next_set() -+ if ret: return ret -+ else: -+ self.groups[self.current_group].process_install() -+ self.current_group += 1 -+ return (None, None) -+ -+ def add_group(self, name=None, set=True): -+ #if self.groups and not self.groups[0].tasks: -+ # error('add_group: an empty group is already present') -+ g = TaskGroup() -+ -+ if name and name in self.groups_names: -+ error('add_group: name %s already present' % name) -+ self.groups_names[name] = g -+ self.groups.append(g) -+ if set: -+ self.current_group = len(self.groups) - 1 -+ -+ def set_group(self, idx): -+ if isinstance(idx, str): -+ g = self.groups_names[idx] -+ for x in xrange(len(self.groups)): -+ if id(g) == id(self.groups[x]): -+ self.current_group = x -+ else: -+ self.current_group = idx -+ -+ def add_task_gen(self, tgen): -+ if not self.groups: self.add_group() -+ self.groups[self.current_group].tasks_gen.append(tgen) -+ -+ def add_task(self, task): -+ if not self.groups: self.add_group() -+ self.groups[self.current_group].tasks.append(task) -+ -+ def total(self): -+ total = 0 -+ if not self.groups: return 0 -+ for group in self.groups: -+ total += len(group.tasks) -+ return total -+ -+ def add_finished(self, tsk): -+ self.tasks_done.append(tsk) -+ bld = tsk.generator.bld -+ if bld.is_install: -+ f = None -+ if 'install' in tsk.__dict__: -+ f = tsk.__dict__['install'] -+ # install=0 to prevent installation -+ if f: f(tsk) -+ else: -+ tsk.install() -+ -+class TaskGroup(object): -+ "the compilation of one group does not begin until the previous group has finished (in the manager)" -+ def __init__(self): -+ self.tasks = [] # this list will be consumed -+ self.tasks_gen = [] -+ -+ self.cstr_groups = Utils.DefaultDict(list) # tasks having equivalent constraints -+ self.cstr_order = Utils.DefaultDict(set) # partial order between the cstr groups -+ self.temp_tasks = [] # tasks put on hold -+ self.ready = 0 -+ self.post_funs = [] -+ -+ def reset(self): -+ "clears the state of the object (put back the tasks into self.tasks)" -+ for x in self.cstr_groups: -+ self.tasks += self.cstr_groups[x] -+ self.tasks = self.temp_tasks + self.tasks -+ self.temp_tasks = [] -+ self.cstr_groups = Utils.DefaultDict(list) -+ self.cstr_order = Utils.DefaultDict(set) -+ self.ready = 0 -+ -+ def process_install(self): -+ for (f, k, kw) in self.post_funs: -+ f(*k, **kw) -+ -+ def prepare(self): -+ "prepare the scheduling" -+ self.ready = 1 -+ file_deps(self.tasks) -+ self.make_cstr_groups() -+ self.extract_constraints() -+ -+ def get_next_set(self): -+ "next list of tasks to execute using max job settings, returns (maxjobs, task_list)" -+ global algotype -+ if algotype == NORMAL: -+ tasks = self.tasks_in_parallel() -+ maxj = MAXJOBS -+ elif algotype == JOBCONTROL: -+ (maxj, tasks) = self.tasks_by_max_jobs() -+ elif algotype == MAXPARALLEL: -+ tasks = self.tasks_with_inner_constraints() -+ maxj = MAXJOBS -+ else: -+ raise Utils.WafError("unknown algorithm type %s" % (algotype)) -+ -+ if not tasks: return () -+ return (maxj, tasks) -+ -+ def make_cstr_groups(self): -+ "unite the tasks that have similar constraints" -+ self.cstr_groups = Utils.DefaultDict(list) -+ for x in self.tasks: -+ h = x.hash_constraints() -+ self.cstr_groups[h].append(x) -+ -+ def set_order(self, a, b): -+ self.cstr_order[a].add(b) -+ -+ def compare_exts(self, t1, t2): -+ "extension production" -+ x = "ext_in" -+ y = "ext_out" -+ in_ = t1.attr(x, ()) -+ out_ = t2.attr(y, ()) -+ for k in in_: -+ if k in out_: -+ return -1 -+ in_ = t2.attr(x, ()) -+ out_ = t1.attr(y, ()) -+ for k in in_: -+ if k in out_: -+ return 1 -+ return 0 -+ -+ def compare_partial(self, t1, t2): -+ "partial relations after/before" -+ m = "after" -+ n = "before" -+ name = t2.__class__.__name__ -+ if name in Utils.to_list(t1.attr(m, ())): return -1 -+ elif name in Utils.to_list(t1.attr(n, ())): return 1 -+ name = t1.__class__.__name__ -+ if name in Utils.to_list(t2.attr(m, ())): return 1 -+ elif name in Utils.to_list(t2.attr(n, ())): return -1 -+ return 0 -+ -+ def extract_constraints(self): -+ "extract the parallelization constraints from the tasks with different constraints" -+ keys = self.cstr_groups.keys() -+ max = len(keys) -+ # hopefully the length of this list is short -+ for i in xrange(max): -+ t1 = self.cstr_groups[keys[i]][0] -+ for j in xrange(i + 1, max): -+ t2 = self.cstr_groups[keys[j]][0] -+ -+ # add the constraints based on the comparisons -+ val = (self.compare_exts(t1, t2) -+ or self.compare_partial(t1, t2) -+ ) -+ if val > 0: -+ self.set_order(keys[i], keys[j]) -+ elif val < 0: -+ self.set_order(keys[j], keys[i]) -+ -+ def tasks_in_parallel(self): -+ "(NORMAL) next list of tasks that may be executed in parallel" -+ -+ if not self.ready: self.prepare() -+ -+ keys = self.cstr_groups.keys() -+ -+ unconnected = [] -+ remainder = [] -+ -+ for u in keys: -+ for k in self.cstr_order.values(): -+ if u in k: -+ remainder.append(u) -+ break -+ else: -+ unconnected.append(u) -+ -+ toreturn = [] -+ for y in unconnected: -+ toreturn.extend(self.cstr_groups[y]) -+ -+ # remove stuff only after -+ for y in unconnected: -+ try: self.cstr_order.__delitem__(y) -+ except KeyError: pass -+ self.cstr_groups.__delitem__(y) -+ -+ if not toreturn and remainder: -+ raise Utils.WafError("circular order constraint detected %r" % remainder) -+ -+ return toreturn -+ -+ def tasks_by_max_jobs(self): -+ "(JOBCONTROL) returns the tasks that can run in parallel with the max amount of jobs" -+ if not self.ready: self.prepare() -+ if not self.temp_tasks: self.temp_tasks = self.tasks_in_parallel() -+ if not self.temp_tasks: return (None, None) -+ -+ maxjobs = MAXJOBS -+ ret = [] -+ remaining = [] -+ for t in self.temp_tasks: -+ m = getattr(t, "maxjobs", getattr(self.__class__, "maxjobs", MAXJOBS)) -+ if m > maxjobs: -+ remaining.append(t) -+ elif m < maxjobs: -+ remaining += ret -+ ret = [t] -+ maxjobs = m -+ else: -+ ret.append(t) -+ self.temp_tasks = remaining -+ return (maxjobs, ret) -+ -+ def tasks_with_inner_constraints(self): -+ """(MAXPARALLEL) returns all tasks in this group, but add the constraints on each task instance -+ as an optimization, it might be desirable to discard the tasks which do not have to run""" -+ if not self.ready: self.prepare() -+ -+ if getattr(self, "done", None): return None -+ -+ for p in self.cstr_order: -+ for v in self.cstr_order[p]: -+ for m in self.cstr_groups[p]: -+ for n in self.cstr_groups[v]: -+ n.set_run_after(m) -+ self.cstr_order = Utils.DefaultDict(set) -+ self.cstr_groups = Utils.DefaultDict(list) -+ self.done = 1 -+ return self.tasks[:] # make a copy -+ -+class store_task_type(type): -+ "store the task types that have a name ending in _task into a map (remember the existing task types)" -+ def __init__(cls, name, bases, dict): -+ super(store_task_type, cls).__init__(name, bases, dict) -+ name = cls.__name__ -+ -+ if name.endswith('_task'): -+ name = name.replace('_task', '') -+ if name != 'TaskBase': -+ TaskBase.classes[name] = cls -+ -+class TaskBase(object): -+ """Base class for all Waf tasks -+ -+ The most important methods are (by usual order of call): -+ 1 runnable_status: ask the task if it should be run, skipped, or if we have to ask later -+ 2 __str__: string to display to the user -+ 3 run: execute the task -+ 4 post_run: after the task is run, update the cache about the task -+ -+ This class should be seen as an interface, it provides the very minimum necessary for the scheduler -+ so it does not do much. -+ -+ For illustration purposes, TaskBase instances try to execute self.fun (if provided) -+ """ -+ -+ __metaclass__ = store_task_type -+ -+ color = "GREEN" -+ maxjobs = MAXJOBS -+ classes = {} -+ stat = None -+ -+ def __init__(self, *k, **kw): -+ self.hasrun = NOT_RUN -+ -+ try: -+ self.generator = kw['generator'] -+ except KeyError: -+ self.generator = self -+ self.bld = Build.bld -+ -+ if kw.get('normal', 1): -+ self.generator.bld.task_manager.add_task(self) -+ -+ def __repr__(self): -+ "used for debugging" -+ return '\n\t{task: %s %s}' % (self.__class__.__name__, str(getattr(self, "fun", ""))) -+ -+ def __str__(self): -+ "string to display to the user" -+ if hasattr(self, 'fun'): -+ return 'executing: %s\n' % self.fun.__name__ -+ return self.__class__.__name__ + '\n' -+ -+ def exec_command(self, *k, **kw): -+ "use this for executing commands from tasks" -+ # TODO in waf 1.6, eliminate bld.exec_command, and move the cwd processing to here -+ if self.env['env']: -+ kw['env'] = self.env['env'] -+ return self.generator.bld.exec_command(*k, **kw) -+ -+ def runnable_status(self): -+ "RUN_ME SKIP_ME or ASK_LATER" -+ return RUN_ME -+ -+ def can_retrieve_cache(self): -+ return False -+ -+ def call_run(self): -+ if self.can_retrieve_cache(): -+ return 0 -+ return self.run() -+ -+ def run(self): -+ "called if the task must run" -+ if hasattr(self, 'fun'): -+ return self.fun(self) -+ return 0 -+ -+ def post_run(self): -+ "update the dependency tree (node stats)" -+ pass -+ -+ def display(self): -+ "print either the description (using __str__) or the progress bar or the ide output" -+ col1 = Logs.colors(self.color) -+ col2 = Logs.colors.NORMAL -+ -+ if Options.options.progress_bar == 1: -+ return self.generator.bld.progress_line(self.position[0], self.position[1], col1, col2) -+ -+ if Options.options.progress_bar == 2: -+ ela = Utils.get_elapsed_time(self.generator.bld.ini) -+ try: -+ ins = ','.join([n.name for n in self.inputs]) -+ except AttributeError: -+ ins = '' -+ try: -+ outs = ','.join([n.name for n in self.outputs]) -+ except AttributeError: -+ outs = '' -+ return '|Total %s|Current %s|Inputs %s|Outputs %s|Time %s|\n' % (self.position[1], self.position[0], ins, outs, ela) -+ -+ total = self.position[1] -+ n = len(str(total)) -+ fs = '[%%%dd/%%%dd] %%s%%s%%s' % (n, n) -+ return fs % (self.position[0], self.position[1], col1, str(self), col2) -+ -+ def attr(self, att, default=None): -+ "retrieve an attribute from the instance or from the class (microoptimization here)" -+ ret = getattr(self, att, self) -+ if ret is self: return getattr(self.__class__, att, default) -+ return ret -+ -+ def hash_constraints(self): -+ "identify a task type for all the constraints relevant for the scheduler: precedence, file production" -+ a = self.attr -+ sum = hash((self.__class__.__name__, -+ str(a('before', '')), -+ str(a('after', '')), -+ str(a('ext_in', '')), -+ str(a('ext_out', '')), -+ self.__class__.maxjobs)) -+ return sum -+ -+ def format_error(self): -+ "error message to display to the user (when a build fails)" -+ if getattr(self, "err_msg", None): -+ return self.err_msg -+ elif self.hasrun == CRASHED: -+ try: -+ return " -> task failed (err #%d): %r" % (self.err_code, self) -+ except AttributeError: -+ return " -> task failed: %r" % self -+ elif self.hasrun == MISSING: -+ return " -> missing files: %r" % self -+ else: -+ return '' -+ -+ def install(self): -+ """ -+ installation is performed by looking at the task attributes: -+ * install_path: installation path like "${PREFIX}/bin" -+ * filename: install the first node in the outputs as a file with a particular name, be certain to give os.sep -+ * chmod: permissions -+ """ -+ bld = self.generator.bld -+ d = self.attr('install') -+ -+ if self.attr('install_path'): -+ lst = [a.relpath_gen(bld.srcnode) for a in self.outputs] -+ perm = self.attr('chmod', O644) -+ if self.attr('src'): -+ # if src is given, install the sources too -+ lst += [a.relpath_gen(bld.srcnode) for a in self.inputs] -+ if self.attr('filename'): -+ dir = self.install_path.rstrip(os.sep) + os.sep + self.attr('filename') -+ bld.install_as(dir, lst[0], self.env, perm) -+ else: -+ bld.install_files(self.install_path, lst, self.env, perm) -+ -+class Task(TaskBase): -+ """The parent class is quite limited, in this version: -+ * file system interaction: input and output nodes -+ * persistence: do not re-execute tasks that have already run -+ * caching: same files can be saved and retrieved from a cache directory -+ * dependencies: -+ implicit, like .c files depending on .h files -+ explicit, like the input nodes or the dep_nodes -+ environment variables, like the CXXFLAGS in self.env -+ """ -+ vars = [] -+ def __init__(self, env, **kw): -+ TaskBase.__init__(self, **kw) -+ self.env = env -+ -+ # inputs and outputs are nodes -+ # use setters when possible -+ self.inputs = [] -+ self.outputs = [] -+ -+ self.dep_nodes = [] -+ self.run_after = [] -+ -+ # Additionally, you may define the following -+ #self.dep_vars = 'PREFIX DATADIR' -+ -+ def __str__(self): -+ "string to display to the user" -+ env = self.env -+ src_str = ' '.join([a.nice_path(env) for a in self.inputs]) -+ tgt_str = ' '.join([a.nice_path(env) for a in self.outputs]) -+ if self.outputs: sep = ' -> ' -+ else: sep = '' -+ return '%s: %s%s%s\n' % (self.__class__.__name__.replace('_task', ''), src_str, sep, tgt_str) -+ -+ def __repr__(self): -+ return "".join(['\n\t{task: ', self.__class__.__name__, " ", ",".join([x.name for x in self.inputs]), " -> ", ",".join([x.name for x in self.outputs]), '}']) -+ -+ def unique_id(self): -+ "get a unique id: hash the node paths, the variant, the class, the function" -+ try: -+ return self.uid -+ except AttributeError: -+ "this is not a real hot zone, but we want to avoid surprizes here" -+ m = md5() -+ up = m.update -+ up(self.__class__.__name__) -+ up(self.env.variant()) -+ p = None -+ for x in self.inputs + self.outputs: -+ if p != x.parent.id: -+ p = x.parent.id -+ up(x.parent.abspath()) -+ up(x.name) -+ self.uid = m.digest() -+ return self.uid -+ -+ def set_inputs(self, inp): -+ if isinstance(inp, list): self.inputs += inp -+ else: self.inputs.append(inp) -+ -+ def set_outputs(self, out): -+ if isinstance(out, list): self.outputs += out -+ else: self.outputs.append(out) -+ -+ def set_run_after(self, task): -+ "set (scheduler) order on another task" -+ # TODO: handle list or object -+ assert isinstance(task, TaskBase) -+ self.run_after.append(task) -+ -+ def add_file_dependency(self, filename): -+ "TODO user-provided file dependencies" -+ node = self.generator.bld.path.find_resource(filename) -+ self.dep_nodes.append(node) -+ -+ def signature(self): -+ # compute the result one time, and suppose the scan_signature will give the good result -+ try: return self.cache_sig[0] -+ except AttributeError: pass -+ -+ self.m = md5() -+ -+ # explicit deps -+ exp_sig = self.sig_explicit_deps() -+ -+ # env vars -+ var_sig = self.sig_vars() -+ -+ # implicit deps -+ -+ imp_sig = SIG_NIL -+ if self.scan: -+ try: -+ imp_sig = self.sig_implicit_deps() -+ except ValueError: -+ return self.signature() -+ -+ # we now have the signature (first element) and the details (for debugging) -+ ret = self.m.digest() -+ self.cache_sig = (ret, exp_sig, imp_sig, var_sig) -+ return ret -+ -+ def runnable_status(self): -+ "SKIP_ME RUN_ME or ASK_LATER" -+ #return 0 # benchmarking -+ -+ if self.inputs and (not self.outputs): -+ if not getattr(self.__class__, 'quiet', None): -+ warn("invalid task (no inputs OR outputs): override in a Task subclass or set the attribute 'quiet' %r" % self) -+ -+ for t in self.run_after: -+ if not t.hasrun: -+ return ASK_LATER -+ -+ env = self.env -+ bld = self.generator.bld -+ -+ # first compute the signature -+ new_sig = self.signature() -+ -+ # compare the signature to a signature computed previously -+ key = self.unique_id() -+ try: -+ prev_sig = bld.task_sigs[key][0] -+ except KeyError: -+ debug("task: task %r must run as it was never run before or the task code changed", self) -+ return RUN_ME -+ -+ # compare the signatures of the outputs -+ for node in self.outputs: -+ variant = node.variant(env) -+ try: -+ if bld.node_sigs[variant][node.id] != new_sig: -+ return RUN_ME -+ except KeyError: -+ debug("task: task %r must run as the output nodes do not exist", self) -+ return RUN_ME -+ -+ # debug if asked to -+ if Logs.verbose: self.debug_why(bld.task_sigs[key]) -+ -+ if new_sig != prev_sig: -+ return RUN_ME -+ return SKIP_ME -+ -+ def post_run(self): -+ "called after a successful task run" -+ bld = self.generator.bld -+ env = self.env -+ sig = self.signature() -+ ssig = sig.encode('hex') -+ -+ variant = env.variant() -+ for node in self.outputs: -+ # check if the node exists .. -+ try: -+ os.stat(node.abspath(env)) -+ except OSError: -+ self.hasrun = MISSING -+ self.err_msg = '-> missing file: %r' % node.abspath(env) -+ raise Utils.WafError -+ -+ # important, store the signature for the next run -+ bld.node_sigs[variant][node.id] = sig -+ bld.task_sigs[self.unique_id()] = self.cache_sig -+ -+ # file caching, if possible -+ # try to avoid data corruption as much as possible -+ if not Options.cache_global or Options.options.nocache or not self.outputs: -+ return None -+ -+ if getattr(self, 'cached', None): -+ return None -+ -+ dname = os.path.join(Options.cache_global, ssig) -+ tmpdir = tempfile.mkdtemp(prefix=Options.cache_global + os.sep + 'waf') -+ -+ try: -+ shutil.rmtree(dname) -+ except: -+ pass -+ -+ try: -+ i = 0 -+ for node in self.outputs: -+ variant = node.variant(env) -+ dest = os.path.join(tmpdir, str(i) + node.name) -+ shutil.copy2(node.abspath(env), dest) -+ i += 1 -+ except (OSError, IOError): -+ try: -+ shutil.rmtree(tmpdir) -+ except: -+ pass -+ else: -+ try: -+ os.rename(tmpdir, dname) -+ except OSError: -+ try: -+ shutil.rmtree(tmpdir) -+ except: -+ pass -+ else: -+ try: -+ os.chmod(dname, O755) -+ except: -+ pass -+ -+ def can_retrieve_cache(self): -+ """ -+ Retrieve build nodes from the cache -+ update the file timestamps to help cleaning the least used entries from the cache -+ additionally, set an attribute 'cached' to avoid re-creating the same cache files -+ -+ suppose there are files in cache/dir1/file1 and cache/dir2/file2 -+ first, read the timestamp of dir1 -+ then try to copy the files -+ then look at the timestamp again, if it has changed, the data may have been corrupt (cache update by another process) -+ should an exception occur, ignore the data -+ """ -+ if not Options.cache_global or Options.options.nocache or not self.outputs: -+ return None -+ -+ env = self.env -+ sig = self.signature() -+ ssig = sig.encode('hex') -+ -+ # first try to access the cache folder for the task -+ dname = os.path.join(Options.cache_global, ssig) -+ try: -+ t1 = os.stat(dname).st_mtime -+ except OSError: -+ return None -+ -+ i = 0 -+ for node in self.outputs: -+ variant = node.variant(env) -+ -+ orig = os.path.join(dname, str(i) + node.name) -+ try: -+ shutil.copy2(orig, node.abspath(env)) -+ # mark the cache file as used recently (modified) -+ os.utime(orig, None) -+ except (OSError, IOError): -+ debug('task: failed retrieving file') -+ return None -+ i += 1 -+ -+ # is it the same folder? -+ try: -+ t2 = os.stat(dname).st_mtime -+ except OSError: -+ return None -+ -+ if t1 != t2: -+ return None -+ -+ for node in self.outputs: -+ self.generator.bld.node_sigs[variant][node.id] = sig -+ if Options.options.progress_bar < 1: -+ self.generator.bld.printout('restoring from cache %r\n' % node.bldpath(env)) -+ -+ self.cached = True -+ return 1 -+ -+ def debug_why(self, old_sigs): -+ "explains why a task is run" -+ -+ new_sigs = self.cache_sig -+ def v(x): -+ return x.encode('hex') -+ -+ debug("Task %r", self) -+ msgs = ['Task must run', '* Source file or manual dependency', '* Implicit dependency', '* Environment variable'] -+ tmp = 'task: -> %s: %s %s' -+ for x in xrange(len(msgs)): -+ if (new_sigs[x] != old_sigs[x]): -+ debug(tmp, msgs[x], v(old_sigs[x]), v(new_sigs[x])) -+ -+ def sig_explicit_deps(self): -+ bld = self.generator.bld -+ up = self.m.update -+ -+ # the inputs -+ for x in self.inputs + getattr(self, 'dep_nodes', []): -+ if not x.parent.id in bld.cache_scanned_folders: -+ bld.rescan(x.parent) -+ -+ variant = x.variant(self.env) -+ try: -+ up(bld.node_sigs[variant][x.id]) -+ except KeyError: -+ raise Utils.WafError('Missing node signature for %r (required by %r)' % (x, self)) -+ -+ # manual dependencies, they can slow down the builds -+ if bld.deps_man: -+ additional_deps = bld.deps_man -+ for x in self.inputs + self.outputs: -+ try: -+ d = additional_deps[x.id] -+ except KeyError: -+ continue -+ -+ for v in d: -+ if isinstance(v, Node.Node): -+ bld.rescan(v.parent) -+ variant = v.variant(self.env) -+ try: -+ v = bld.node_sigs[variant][v.id] -+ except KeyError: -+ raise Utils.WafError('Missing node signature for %r (required by %r)' % (v, self)) -+ elif hasattr(v, '__call__'): -+ v = v() # dependency is a function, call it -+ up(v) -+ -+ for x in self.dep_nodes: -+ v = bld.node_sigs[x.variant(self.env)][x.id] -+ up(v) -+ -+ return self.m.digest() -+ -+ def sig_vars(self): -+ bld = self.generator.bld -+ env = self.env -+ -+ # dependencies on the environment vars -+ act_sig = bld.hash_env_vars(env, self.__class__.vars) -+ self.m.update(act_sig) -+ -+ # additional variable dependencies, if provided -+ dep_vars = getattr(self, 'dep_vars', None) -+ if dep_vars: -+ self.m.update(bld.hash_env_vars(env, dep_vars)) -+ -+ return self.m.digest() -+ -+ #def scan(self, node): -+ # """this method returns a tuple containing: -+ # * a list of nodes corresponding to real files -+ # * a list of names for files not found in path_lst -+ # the input parameters may have more parameters that the ones used below -+ # """ -+ # return ((), ()) -+ scan = None -+ -+ # compute the signature, recompute it if there is no match in the cache -+ def sig_implicit_deps(self): -+ "the signature obtained may not be the one if the files have changed, we do it in two steps" -+ -+ bld = self.generator.bld -+ -+ # get the task signatures from previous runs -+ key = self.unique_id() -+ prev_sigs = bld.task_sigs.get(key, ()) -+ if prev_sigs: -+ try: -+ # for issue #379 -+ if prev_sigs[2] == self.compute_sig_implicit_deps(): -+ return prev_sigs[2] -+ except (KeyError, OSError): -+ pass -+ del bld.task_sigs[key] -+ raise ValueError('rescan') -+ -+ # no previous run or the signature of the dependencies has changed, rescan the dependencies -+ (nodes, names) = self.scan() -+ if Logs.verbose: -+ debug('deps: scanner for %s returned %s %s', str(self), str(nodes), str(names)) -+ -+ # store the dependencies in the cache -+ bld.node_deps[key] = nodes -+ bld.raw_deps[key] = names -+ -+ # recompute the signature and return it -+ try: -+ sig = self.compute_sig_implicit_deps() -+ except KeyError: -+ try: -+ nodes = [] -+ for k in bld.node_deps.get(self.unique_id(), []): -+ if k.id & 3 == 2: # Node.FILE: -+ if not k.id in bld.node_sigs[0]: -+ nodes.append(k) -+ else: -+ if not k.id in bld.node_sigs[self.env.variant()]: -+ nodes.append(k) -+ except: -+ nodes = '?' -+ raise Utils.WafError('Missing node signature for %r (for implicit dependencies %r)' % (nodes, self)) -+ -+ return sig -+ -+ def compute_sig_implicit_deps(self): -+ """it is intended for .cpp and inferred .h files -+ there is a single list (no tree traversal) -+ this is the hot spot so ... do not touch""" -+ upd = self.m.update -+ -+ bld = self.generator.bld -+ tstamp = bld.node_sigs -+ env = self.env -+ -+ for k in bld.node_deps.get(self.unique_id(), []): -+ # unlikely but necessary if it happens -+ if not k.parent.id in bld.cache_scanned_folders: -+ # if the parent folder is removed, an OSError may be thrown -+ bld.rescan(k.parent) -+ -+ # if the parent folder is removed, a KeyError will be thrown -+ if k.id & 3 == 2: # Node.FILE: -+ upd(tstamp[0][k.id]) -+ else: -+ upd(tstamp[env.variant()][k.id]) -+ -+ return self.m.digest() -+ -+def funex(c): -+ dc = {} -+ exec(c, dc) -+ return dc['f'] -+ -+reg_act = re.compile(r"(?P\\)|(?P\$\$)|(?P\$\{(?P\w+)(?P.*?)\})", re.M) -+def compile_fun_shell(name, line): -+ """Compiles a string (once) into a function, eg: -+ simple_task_type('c++', '${CXX} -o ${TGT[0]} ${SRC} -I ${SRC[0].parent.bldpath()}') -+ -+ The env variables (CXX, ..) on the task must not hold dicts (order) -+ The reserved keywords TGT and SRC represent the task input and output nodes -+ -+ quick test: -+ bld(source='wscript', rule='echo "foo\\${SRC[0].name}\\bar"') -+ """ -+ -+ extr = [] -+ def repl(match): -+ g = match.group -+ if g('dollar'): return "$" -+ elif g('backslash'): return '\\\\' -+ elif g('subst'): extr.append((g('var'), g('code'))); return "%s" -+ return None -+ -+ line = reg_act.sub(repl, line) or line -+ -+ parm = [] -+ dvars = [] -+ app = parm.append -+ for (var, meth) in extr: -+ if var == 'SRC': -+ if meth: app('task.inputs%s' % meth) -+ else: app('" ".join([a.srcpath(env) for a in task.inputs])') -+ elif var == 'TGT': -+ if meth: app('task.outputs%s' % meth) -+ else: app('" ".join([a.bldpath(env) for a in task.outputs])') -+ else: -+ if not var in dvars: dvars.append(var) -+ app("p('%s')" % var) -+ if parm: parm = "%% (%s) " % (',\n\t\t'.join(parm)) -+ else: parm = '' -+ -+ c = COMPILE_TEMPLATE_SHELL % (line, parm) -+ -+ debug('action: %s', c) -+ return (funex(c), dvars) -+ -+def compile_fun_noshell(name, line): -+ -+ extr = [] -+ def repl(match): -+ g = match.group -+ if g('dollar'): return "$" -+ elif g('subst'): extr.append((g('var'), g('code'))); return "<<|@|>>" -+ return None -+ -+ line2 = reg_act.sub(repl, line) -+ params = line2.split('<<|@|>>') -+ -+ buf = [] -+ dvars = [] -+ app = buf.append -+ for x in xrange(len(extr)): -+ params[x] = params[x].strip() -+ if params[x]: -+ app("lst.extend(%r)" % params[x].split()) -+ (var, meth) = extr[x] -+ if var == 'SRC': -+ if meth: app('lst.append(task.inputs%s)' % meth) -+ else: app("lst.extend([a.srcpath(env) for a in task.inputs])") -+ elif var == 'TGT': -+ if meth: app('lst.append(task.outputs%s)' % meth) -+ else: app("lst.extend([a.bldpath(env) for a in task.outputs])") -+ else: -+ app('lst.extend(to_list(env[%r]))' % var) -+ if not var in dvars: dvars.append(var) -+ -+ if params[-1]: -+ app("lst.extend(%r)" % shlex.split(params[-1])) -+ -+ fun = COMPILE_TEMPLATE_NOSHELL % "\n\t".join(buf) -+ debug('action: %s', fun) -+ return (funex(fun), dvars) -+ -+def compile_fun(name, line, shell=None): -+ "commands can be launched by the shell or not" -+ if line.find('<') > 0 or line.find('>') > 0 or line.find('&&') > 0: -+ shell = True -+ #else: -+ # shell = False -+ -+ if shell is None: -+ if sys.platform == 'win32': -+ shell = False -+ else: -+ shell = True -+ -+ if shell: -+ return compile_fun_shell(name, line) -+ else: -+ return compile_fun_noshell(name, line) -+ -+def simple_task_type(name, line, color='GREEN', vars=[], ext_in=[], ext_out=[], before=[], after=[], shell=None): -+ """return a new Task subclass with the function run compiled from the line given""" -+ (fun, dvars) = compile_fun(name, line, shell) -+ fun.code = line -+ return task_type_from_func(name, fun, vars or dvars, color, ext_in, ext_out, before, after) -+ -+def task_type_from_func(name, func, vars=[], color='GREEN', ext_in=[], ext_out=[], before=[], after=[]): -+ """return a new Task subclass with the function run compiled from the line given""" -+ params = { -+ 'run': func, -+ 'vars': vars, -+ 'color': color, -+ 'name': name, -+ 'ext_in': Utils.to_list(ext_in), -+ 'ext_out': Utils.to_list(ext_out), -+ 'before': Utils.to_list(before), -+ 'after': Utils.to_list(after), -+ } -+ -+ cls = type(Task)(name, (Task,), params) -+ TaskBase.classes[name] = cls -+ return cls -+ -+def always_run(cls): -+ """Set all task instances of this class to be executed whenever a build is started -+ The task signature is calculated, but the result of the comparation between -+ task signatures is bypassed -+ """ -+ old = cls.runnable_status -+ def always(self): -+ ret = old(self) -+ if ret == SKIP_ME: -+ return RUN_ME -+ return ret -+ cls.runnable_status = always -+ -+def update_outputs(cls): -+ """When a command is always run, it is possible that the output only change -+ sometimes. By default the build node have as a hash the signature of the task -+ which may not change. With this, the output nodes (produced) are hashed, -+ and the hashes are set to the build nodes -+ -+ This may avoid unnecessary recompilations, but it uses more resources -+ (hashing the output files) so it is not used by default -+ """ -+ old_post_run = cls.post_run -+ def post_run(self): -+ old_post_run(self) -+ bld = self.generator.bld -+ for output in self.outputs: -+ bld.node_sigs[self.env.variant()][output.id] = Utils.h_file(output.abspath(self.env)) -+ bld.task_sigs[output.id] = self.unique_id() -+ cls.post_run = post_run -+ -+ old_runnable_status = cls.runnable_status -+ def runnable_status(self): -+ status = old_runnable_status(self) -+ if status != RUN_ME: -+ return status -+ -+ uid = self.unique_id() -+ try: -+ bld = self.outputs[0].__class__.bld -+ new_sig = self.signature() -+ prev_sig = bld.task_sigs[uid][0] -+ if prev_sig == new_sig: -+ for x in self.outputs: -+ if not x.id in bld.node_sigs[self.env.variant()]: -+ return RUN_ME -+ if bld.task_sigs[x.id] != uid: # ensure the outputs are associated with *this* task -+ return RUN_ME -+ return SKIP_ME -+ except KeyError: -+ pass -+ except IndexError: -+ pass -+ return RUN_ME -+ cls.runnable_status = runnable_status -+ -+def extract_outputs(tasks): -+ """file_deps: Infer additional dependencies from task input and output nodes -+ """ -+ v = {} -+ for x in tasks: -+ try: -+ (ins, outs) = v[x.env.variant()] -+ except KeyError: -+ ins = {} -+ outs = {} -+ v[x.env.variant()] = (ins, outs) -+ -+ for a in getattr(x, 'inputs', []): -+ try: ins[a.id].append(x) -+ except KeyError: ins[a.id] = [x] -+ for a in getattr(x, 'outputs', []): -+ try: outs[a.id].append(x) -+ except KeyError: outs[a.id] = [x] -+ -+ for (ins, outs) in v.values(): -+ links = set(ins.iterkeys()).intersection(outs.iterkeys()) -+ for k in links: -+ for a in ins[k]: -+ for b in outs[k]: -+ a.set_run_after(b) -+ -+def extract_deps(tasks): -+ """file_deps: Infer additional dependencies from task input and output nodes and from implicit dependencies -+ returned by the scanners - that will only work if all tasks are created -+ -+ this is aimed at people who have pathological builds and who do not care enough -+ to implement the build dependencies properly -+ -+ with two loops over the list of tasks, do not expect this to be really fast -+ """ -+ -+ # first reuse the function above -+ extract_outputs(tasks) -+ -+ # map the output nodes to the tasks producing them -+ out_to_task = {} -+ for x in tasks: -+ v = x.env.variant() -+ try: -+ lst = x.outputs -+ except AttributeError: -+ pass -+ else: -+ for node in lst: -+ out_to_task[(v, node.id)] = x -+ -+ # map the dependencies found to the tasks compiled -+ dep_to_task = {} -+ for x in tasks: -+ try: -+ x.signature() -+ except: # this is on purpose -+ pass -+ -+ v = x.env.variant() -+ key = x.unique_id() -+ for k in x.generator.bld.node_deps.get(x.unique_id(), []): -+ try: dep_to_task[(v, k.id)].append(x) -+ except KeyError: dep_to_task[(v, k.id)] = [x] -+ -+ # now get the intersection -+ deps = set(dep_to_task.keys()).intersection(set(out_to_task.keys())) -+ -+ # and add the dependencies from task to task -+ for idx in deps: -+ for k in dep_to_task[idx]: -+ k.set_run_after(out_to_task[idx]) -+ -+ # cleanup, remove the signatures -+ for x in tasks: -+ try: -+ delattr(x, 'cache_sig') -+ except AttributeError: -+ pass -+ -diff --git a/buildtools/wafadmin/TaskGen.py b/buildtools/wafadmin/TaskGen.py -new file mode 100644 -index 0000000..ae1834a ---- /dev/null -+++ b/buildtools/wafadmin/TaskGen.py -@@ -0,0 +1,612 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2005-2008 (ita) -+ -+""" -+The class task_gen encapsulates the creation of task objects (low-level code) -+The instances can have various parameters, but the creation of task nodes (Task.py) -+is delayed. To achieve this, various methods are called from the method "apply" -+ -+The class task_gen contains lots of methods, and a configuration table: -+* the methods to call (self.meths) can be specified dynamically (removing, adding, ..) -+* the order of the methods (self.prec or by default task_gen.prec) is configurable -+* new methods can be inserted dynamically without pasting old code -+ -+Additionally, task_gen provides the method apply_core -+* file extensions are mapped to methods: def meth(self, name_or_node) -+* if a mapping is not found in self.mappings, it is searched in task_gen.mappings -+* when called, the functions may modify self.allnodes to re-add source to process -+* the mappings can map an extension or a filename (see the code below) -+ -+WARNING: subclasses must reimplement the clone method -+""" -+ -+import os, traceback, copy -+import Build, Task, Utils, Logs, Options -+from Logs import debug, error, warn -+from Constants import * -+ -+typos = { -+'sources':'source', -+'targets':'target', -+'include':'includes', -+'define':'defines', -+'importpath':'importpaths', -+'install_var':'install_path', -+'install_subdir':'install_path', -+'inst_var':'install_path', -+'inst_dir':'install_path', -+'feature':'features', -+} -+ -+class register_obj(type): -+ """no decorators for classes, so we use a metaclass -+ we store into task_gen.classes the classes that inherit task_gen -+ and whose names end in '_taskgen' -+ """ -+ def __init__(cls, name, bases, dict): -+ super(register_obj, cls).__init__(name, bases, dict) -+ name = cls.__name__ -+ suffix = '_taskgen' -+ if name.endswith(suffix): -+ task_gen.classes[name.replace(suffix, '')] = cls -+ -+class task_gen(object): -+ """ -+ Most methods are of the form 'def meth(self):' without any parameters -+ there are many of them, and they do many different things: -+ * task creation -+ * task results installation -+ * environment modification -+ * attribute addition/removal -+ -+ The inheritance approach is complicated -+ * mixing several languages at once -+ * subclassing is needed even for small changes -+ * inserting new methods is complicated -+ -+ This new class uses a configuration table: -+ * adding new methods easily -+ * obtaining the order in which to call the methods -+ * postponing the method calls (post() -> apply) -+ -+ Additionally, a 'traits' static attribute is provided: -+ * this list contains methods -+ * the methods can remove or add methods from self.meths -+ Example1: the attribute 'staticlib' is set on an instance -+ a method set in the list of traits is executed when the -+ instance is posted, it finds that flag and adds another method for execution -+ Example2: a method set in the list of traits finds the msvc -+ compiler (from self.env['MSVC']==1); more methods are added to self.meths -+ """ -+ -+ __metaclass__ = register_obj -+ mappings = {} -+ mapped = {} -+ prec = Utils.DefaultDict(list) -+ traits = Utils.DefaultDict(set) -+ classes = {} -+ -+ def __init__(self, *kw, **kwargs): -+ self.prec = Utils.DefaultDict(list) -+ "map precedence of function names to call" -+ # so we will have to play with directed acyclic graphs -+ # detect cycles, etc -+ -+ self.source = '' -+ self.target = '' -+ -+ # list of methods to execute - does not touch it by hand unless you know -+ self.meths = [] -+ -+ # list of mappings extension -> function -+ self.mappings = {} -+ -+ # list of features (see the documentation on traits) -+ self.features = list(kw) -+ -+ # not always a good idea -+ self.tasks = [] -+ -+ self.default_chmod = O644 -+ self.default_install_path = None -+ -+ # kind of private, beware of what you put in it, also, the contents are consumed -+ self.allnodes = [] -+ -+ self.bld = kwargs.get('bld', Build.bld) -+ self.env = self.bld.env.copy() -+ -+ self.path = self.bld.path # emulate chdir when reading scripts -+ self.name = '' # give a name to the target (static+shlib with the same targetname ambiguity) -+ -+ # provide a unique id -+ self.idx = self.bld.idx[self.path.id] = self.bld.idx.get(self.path.id, 0) + 1 -+ -+ for key, val in kwargs.iteritems(): -+ setattr(self, key, val) -+ -+ self.bld.task_manager.add_task_gen(self) -+ self.bld.all_task_gen.append(self) -+ -+ def __str__(self): -+ return ("" -+ % (self.name or self.target, self.__class__.__name__, str(self.path))) -+ -+ def __setattr__(self, name, attr): -+ real = typos.get(name, name) -+ if real != name: -+ warn('typo %s -> %s' % (name, real)) -+ if Logs.verbose > 0: -+ traceback.print_stack() -+ object.__setattr__(self, real, attr) -+ -+ def to_list(self, value): -+ "helper: returns a list" -+ if isinstance(value, str): return value.split() -+ else: return value -+ -+ def apply(self): -+ "order the methods to execute using self.prec or task_gen.prec" -+ keys = set(self.meths) -+ -+ # add the methods listed in the features -+ self.features = Utils.to_list(self.features) -+ for x in self.features + ['*']: -+ st = task_gen.traits[x] -+ if not st: -+ warn('feature %r does not exist - bind at least one method to it' % x) -+ keys.update(st) -+ -+ # copy the precedence table -+ prec = {} -+ prec_tbl = self.prec or task_gen.prec -+ for x in prec_tbl: -+ if x in keys: -+ prec[x] = prec_tbl[x] -+ -+ # elements disconnected -+ tmp = [] -+ for a in keys: -+ for x in prec.values(): -+ if a in x: break -+ else: -+ tmp.append(a) -+ -+ # topological sort -+ out = [] -+ while tmp: -+ e = tmp.pop() -+ if e in keys: out.append(e) -+ try: -+ nlst = prec[e] -+ except KeyError: -+ pass -+ else: -+ del prec[e] -+ for x in nlst: -+ for y in prec: -+ if x in prec[y]: -+ break -+ else: -+ tmp.append(x) -+ -+ if prec: raise Utils.WafError("graph has a cycle %s" % str(prec)) -+ out.reverse() -+ self.meths = out -+ -+ # then we run the methods in order -+ debug('task_gen: posting %s %d', self, id(self)) -+ for x in out: -+ try: -+ v = getattr(self, x) -+ except AttributeError: -+ raise Utils.WafError("tried to retrieve %s which is not a valid method" % x) -+ debug('task_gen: -> %s (%d)', x, id(self)) -+ v() -+ -+ def post(self): -+ "runs the code to create the tasks, do not subclass" -+ if not self.name: -+ if isinstance(self.target, list): -+ self.name = ' '.join(self.target) -+ else: -+ self.name = self.target -+ -+ if getattr(self, 'posted', None): -+ #error("OBJECT ALREADY POSTED" + str( self)) -+ return -+ -+ self.apply() -+ self.posted = True -+ debug('task_gen: posted %s', self.name) -+ -+ def get_hook(self, ext): -+ try: return self.mappings[ext] -+ except KeyError: -+ try: return task_gen.mappings[ext] -+ except KeyError: return None -+ -+ # TODO waf 1.6: always set the environment -+ # TODO waf 1.6: create_task(self, name, inputs, outputs) -+ def create_task(self, name, src=None, tgt=None, env=None): -+ env = env or self.env -+ task = Task.TaskBase.classes[name](env.copy(), generator=self) -+ if src: -+ task.set_inputs(src) -+ if tgt: -+ task.set_outputs(tgt) -+ self.tasks.append(task) -+ return task -+ -+ def name_to_obj(self, name): -+ return self.bld.name_to_obj(name, self.env) -+ -+ def find_sources_in_dirs(self, dirnames, excludes=[], exts=[]): -+ """ -+ The attributes "excludes" and "exts" must be lists to avoid the confusion -+ find_sources_in_dirs('a', 'b', 'c') <-> find_sources_in_dirs('a b c') -+ -+ do not use absolute paths -+ do not use paths outside of the source tree -+ the files or folder beginning by . are not returned -+ -+ # TODO: remove in Waf 1.6 -+ """ -+ -+ err_msg = "'%s' attribute must be a list" -+ if not isinstance(excludes, list): -+ raise Utils.WscriptError(err_msg % 'excludes') -+ if not isinstance(exts, list): -+ raise Utils.WscriptError(err_msg % 'exts') -+ -+ lst = [] -+ -+ #make sure dirnames is a list helps with dirnames with spaces -+ dirnames = self.to_list(dirnames) -+ -+ ext_lst = exts or list(self.mappings.keys()) + list(task_gen.mappings.keys()) -+ -+ for name in dirnames: -+ anode = self.path.find_dir(name) -+ -+ if not anode or not anode.is_child_of(self.bld.srcnode): -+ raise Utils.WscriptError("Unable to use '%s' - either because it's not a relative path" \ -+ ", or it's not child of '%s'." % (name, self.bld.srcnode)) -+ -+ self.bld.rescan(anode) -+ for name in self.bld.cache_dir_contents[anode.id]: -+ -+ # ignore hidden files -+ if name.startswith('.'): -+ continue -+ -+ (base, ext) = os.path.splitext(name) -+ if ext in ext_lst and not name in lst and not name in excludes: -+ lst.append((anode.relpath_gen(self.path) or '.') + os.path.sep + name) -+ -+ lst.sort() -+ self.source = self.to_list(self.source) -+ if not self.source: self.source = lst -+ else: self.source += lst -+ -+ def clone(self, env): -+ """when creating a clone in a task generator method, -+ make sure to set posted=False on the clone -+ else the other task generator will not create its tasks""" -+ newobj = task_gen(bld=self.bld) -+ for x in self.__dict__: -+ if x in ['env', 'bld']: -+ continue -+ elif x in ["path", "features"]: -+ setattr(newobj, x, getattr(self, x)) -+ else: -+ setattr(newobj, x, copy.copy(getattr(self, x))) -+ -+ newobj.__class__ = self.__class__ -+ if isinstance(env, str): -+ newobj.env = self.bld.all_envs[env].copy() -+ else: -+ newobj.env = env.copy() -+ -+ return newobj -+ -+ def get_inst_path(self): -+ return getattr(self, '_install_path', getattr(self, 'default_install_path', '')) -+ -+ def set_inst_path(self, val): -+ self._install_path = val -+ -+ install_path = property(get_inst_path, set_inst_path) -+ -+ -+ def get_chmod(self): -+ return getattr(self, '_chmod', getattr(self, 'default_chmod', O644)) -+ -+ def set_chmod(self, val): -+ self._chmod = val -+ -+ chmod = property(get_chmod, set_chmod) -+ -+def declare_extension(var, func): -+ try: -+ for x in Utils.to_list(var): -+ task_gen.mappings[x] = func -+ except: -+ raise Utils.WscriptError('declare_extension takes either a list or a string %r' % var) -+ task_gen.mapped[func.__name__] = func -+ -+def declare_order(*k): -+ assert(len(k) > 1) -+ n = len(k) - 1 -+ for i in xrange(n): -+ f1 = k[i] -+ f2 = k[i+1] -+ if not f1 in task_gen.prec[f2]: -+ task_gen.prec[f2].append(f1) -+ -+def declare_chain(name='', action='', ext_in='', ext_out='', reentrant=True, color='BLUE', -+ install=0, before=[], after=[], decider=None, rule=None, scan=None): -+ """ -+ see Tools/flex.py for an example -+ while i do not like such wrappers, some people really do -+ """ -+ -+ action = action or rule -+ if isinstance(action, str): -+ act = Task.simple_task_type(name, action, color=color) -+ else: -+ act = Task.task_type_from_func(name, action, color=color) -+ act.ext_in = tuple(Utils.to_list(ext_in)) -+ act.ext_out = tuple(Utils.to_list(ext_out)) -+ act.before = Utils.to_list(before) -+ act.after = Utils.to_list(after) -+ act.scan = scan -+ -+ def x_file(self, node): -+ if decider: -+ ext = decider(self, node) -+ else: -+ ext = ext_out -+ -+ if isinstance(ext, str): -+ out_source = node.change_ext(ext) -+ if reentrant: -+ self.allnodes.append(out_source) -+ elif isinstance(ext, list): -+ out_source = [node.change_ext(x) for x in ext] -+ if reentrant: -+ for i in xrange((reentrant is True) and len(out_source) or reentrant): -+ self.allnodes.append(out_source[i]) -+ else: -+ # XXX: useless: it will fail on Utils.to_list above... -+ raise Utils.WafError("do not know how to process %s" % str(ext)) -+ -+ tsk = self.create_task(name, node, out_source) -+ -+ if node.__class__.bld.is_install: -+ tsk.install = install -+ -+ declare_extension(act.ext_in, x_file) -+ return x_file -+ -+def bind_feature(name, methods): -+ lst = Utils.to_list(methods) -+ task_gen.traits[name].update(lst) -+ -+""" -+All the following decorators are registration decorators, i.e add an attribute to current class -+ (task_gen and its derivatives), with same name as func, which points to func itself. -+For example: -+ @taskgen -+ def sayHi(self): -+ print("hi") -+Now taskgen.sayHi() may be called -+ -+If python were really smart, it could infer itself the order of methods by looking at the -+attributes. A prerequisite for execution is to have the attribute set before. -+Intelligent compilers binding aspect-oriented programming and parallelization, what a nice topic for studies. -+""" -+def taskgen(func): -+ """ -+ register a method as a task generator method -+ """ -+ setattr(task_gen, func.__name__, func) -+ return func -+ -+def feature(*k): -+ """ -+ declare a task generator method that will be executed when the -+ object attribute 'feature' contains the corresponding key(s) -+ """ -+ def deco(func): -+ setattr(task_gen, func.__name__, func) -+ for name in k: -+ task_gen.traits[name].update([func.__name__]) -+ return func -+ return deco -+ -+def before(*k): -+ """ -+ declare a task generator method which will be executed -+ before the functions of given name(s) -+ """ -+ def deco(func): -+ setattr(task_gen, func.__name__, func) -+ for fun_name in k: -+ if not func.__name__ in task_gen.prec[fun_name]: -+ task_gen.prec[fun_name].append(func.__name__) -+ return func -+ return deco -+ -+def after(*k): -+ """ -+ declare a task generator method which will be executed -+ after the functions of given name(s) -+ """ -+ def deco(func): -+ setattr(task_gen, func.__name__, func) -+ for fun_name in k: -+ if not fun_name in task_gen.prec[func.__name__]: -+ task_gen.prec[func.__name__].append(fun_name) -+ return func -+ return deco -+ -+def extension(var): -+ """ -+ declare a task generator method which will be invoked during -+ the processing of source files for the extension given -+ """ -+ def deco(func): -+ setattr(task_gen, func.__name__, func) -+ try: -+ for x in Utils.to_list(var): -+ task_gen.mappings[x] = func -+ except: -+ raise Utils.WafError('extension takes either a list or a string %r' % var) -+ task_gen.mapped[func.__name__] = func -+ return func -+ return deco -+ -+# TODO make certain the decorators may be used here -+ -+def apply_core(self): -+ """Process the attribute source -+ transform the names into file nodes -+ try to process the files by name first, later by extension""" -+ # get the list of folders to use by the scanners -+ # all our objects share the same include paths anyway -+ find_resource = self.path.find_resource -+ -+ for filename in self.to_list(self.source): -+ # if self.mappings or task_gen.mappings contains a file of the same name -+ x = self.get_hook(filename) -+ if x: -+ x(self, filename) -+ else: -+ node = find_resource(filename) -+ if not node: raise Utils.WafError("source not found: '%s' in '%s'" % (filename, str(self.path))) -+ self.allnodes.append(node) -+ -+ for node in self.allnodes: -+ # self.mappings or task_gen.mappings map the file extension to a function -+ x = self.get_hook(node.suffix()) -+ -+ if not x: -+ raise Utils.WafError("Cannot guess how to process %s (got mappings %r in %r) -> try conf.check_tool(..)?" % \ -+ (str(node), self.__class__.mappings.keys(), self.__class__)) -+ x(self, node) -+feature('*')(apply_core) -+ -+def exec_rule(self): -+ """Process the attribute rule, when provided the method apply_core will be disabled -+ """ -+ if not getattr(self, 'rule', None): -+ return -+ -+ # someone may have removed it already -+ try: -+ self.meths.remove('apply_core') -+ except ValueError: -+ pass -+ -+ # get the function and the variables -+ func = self.rule -+ -+ vars2 = [] -+ if isinstance(func, str): -+ # use the shell by default for user-defined commands -+ (func, vars2) = Task.compile_fun('', self.rule, shell=getattr(self, 'shell', True)) -+ func.code = self.rule -+ -+ # create the task class -+ name = getattr(self, 'name', None) or self.target or self.rule -+ if not isinstance(name, str): -+ name = str(self.idx) -+ cls = Task.task_type_from_func(name, func, getattr(self, 'vars', vars2)) -+ cls.color = getattr(self, 'color', 'BLUE') -+ -+ # now create one instance -+ tsk = self.create_task(name) -+ -+ dep_vars = getattr(self, 'dep_vars', ['ruledeps']) -+ if dep_vars: -+ tsk.dep_vars = dep_vars -+ if isinstance(self.rule, str): -+ tsk.env.ruledeps = self.rule -+ else: -+ # only works if the function is in a global module such as a waf tool -+ tsk.env.ruledeps = Utils.h_fun(self.rule) -+ -+ # we assume that the user knows that without inputs or outputs -+ #if not getattr(self, 'target', None) and not getattr(self, 'source', None): -+ # cls.quiet = True -+ -+ if getattr(self, 'target', None): -+ cls.quiet = True -+ tsk.outputs = [self.path.find_or_declare(x) for x in self.to_list(self.target)] -+ -+ if getattr(self, 'source', None): -+ cls.quiet = True -+ tsk.inputs = [] -+ for x in self.to_list(self.source): -+ y = self.path.find_resource(x) -+ if not y: -+ raise Utils.WafError('input file %r could not be found (%r)' % (x, self.path.abspath())) -+ tsk.inputs.append(y) -+ -+ if self.allnodes: -+ tsk.inputs.extend(self.allnodes) -+ -+ if getattr(self, 'scan', None): -+ cls.scan = self.scan -+ -+ if getattr(self, 'install_path', None): -+ tsk.install_path = self.install_path -+ -+ if getattr(self, 'cwd', None): -+ tsk.cwd = self.cwd -+ -+ if getattr(self, 'on_results', None): -+ Task.update_outputs(cls) -+ -+ if getattr(self, 'always', None): -+ Task.always_run(cls) -+ -+ for x in ['after', 'before', 'ext_in', 'ext_out']: -+ setattr(cls, x, getattr(self, x, [])) -+feature('*')(exec_rule) -+before('apply_core')(exec_rule) -+ -+def sequence_order(self): -+ """ -+ add a strict sequential constraint between the tasks generated by task generators -+ it uses the fact that task generators are posted in order -+ it will not post objects which belong to other folders -+ there is also an awesome trick for executing the method in last position -+ -+ to use: -+ bld(features='javac seq') -+ bld(features='jar seq') -+ -+ to start a new sequence, set the attribute seq_start, for example: -+ obj.seq_start = True -+ """ -+ if self.meths and self.meths[-1] != 'sequence_order': -+ self.meths.append('sequence_order') -+ return -+ -+ if getattr(self, 'seq_start', None): -+ return -+ -+ # all the tasks previously declared must be run before these -+ if getattr(self.bld, 'prev', None): -+ self.bld.prev.post() -+ for x in self.bld.prev.tasks: -+ for y in self.tasks: -+ y.set_run_after(x) -+ -+ self.bld.prev = self -+ -+feature('seq')(sequence_order) -+ -diff --git a/buildtools/wafadmin/Tools/__init__.py b/buildtools/wafadmin/Tools/__init__.py -new file mode 100644 -index 0000000..bc6ca23 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/__init__.py -@@ -0,0 +1,4 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006 (ita) -+ -diff --git a/buildtools/wafadmin/Tools/ar.py b/buildtools/wafadmin/Tools/ar.py -new file mode 100644 -index 0000000..af9b17f ---- /dev/null -+++ b/buildtools/wafadmin/Tools/ar.py -@@ -0,0 +1,36 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006-2008 (ita) -+# Ralf Habacker, 2006 (rh) -+ -+"ar and ranlib" -+ -+import os, sys -+import Task, Utils -+from Configure import conftest -+ -+ar_str = '${AR} ${ARFLAGS} ${AR_TGT_F}${TGT} ${AR_SRC_F}${SRC}' -+cls = Task.simple_task_type('static_link', ar_str, color='YELLOW', ext_in='.o', ext_out='.bin', shell=False) -+cls.maxjobs = 1 -+cls.install = Utils.nada -+ -+# remove the output in case it already exists -+old = cls.run -+def wrap(self): -+ try: os.remove(self.outputs[0].abspath(self.env)) -+ except OSError: pass -+ return old(self) -+setattr(cls, 'run', wrap) -+ -+def detect(conf): -+ conf.find_program('ar', var='AR') -+ conf.find_program('ranlib', var='RANLIB') -+ conf.env.ARFLAGS = 'rcs' -+ -+@conftest -+def find_ar(conf): -+ v = conf.env -+ conf.check_tool('ar') -+ if not v['AR']: conf.fatal('ar is required for static libraries - not found') -+ -+ -diff --git a/buildtools/wafadmin/Tools/bison.py b/buildtools/wafadmin/Tools/bison.py -new file mode 100644 -index 0000000..49c6051 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/bison.py -@@ -0,0 +1,38 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# John O'Meara, 2006 -+# Thomas Nagy 2009 -+ -+"Bison processing" -+ -+import Task -+from TaskGen import extension -+ -+bison = '${BISON} ${BISONFLAGS} ${SRC[0].abspath()} -o ${TGT[0].name}' -+cls = Task.simple_task_type('bison', bison, 'GREEN', ext_in='.yc .y .yy', ext_out='.c .cxx .h .l', shell=False) -+ -+@extension(['.y', '.yc', '.yy']) -+def big_bison(self, node): -+ """when it becomes complicated (unlike flex), the old recipes work better (cwd)""" -+ has_h = '-d' in self.env['BISONFLAGS'] -+ -+ outs = [] -+ if node.name.endswith('.yc'): -+ outs.append(node.change_ext('.tab.cc')) -+ if has_h: -+ outs.append(node.change_ext('.tab.hh')) -+ else: -+ outs.append(node.change_ext('.tab.c')) -+ if has_h: -+ outs.append(node.change_ext('.tab.h')) -+ -+ tsk = self.create_task('bison', node, outs) -+ tsk.cwd = node.bld_dir(tsk.env) -+ -+ # and the c/cxx file must be compiled too -+ self.allnodes.append(outs[0]) -+ -+def detect(conf): -+ bison = conf.find_program('bison', var='BISON', mandatory=True) -+ conf.env['BISONFLAGS'] = '-d' -+ -diff --git a/buildtools/wafadmin/Tools/cc.py b/buildtools/wafadmin/Tools/cc.py -new file mode 100644 -index 0000000..903a1c5 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/cc.py -@@ -0,0 +1,100 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006 (ita) -+ -+"Base for c programs/libraries" -+ -+import os -+import TaskGen, Build, Utils, Task -+from Logs import debug -+import ccroot -+from TaskGen import feature, before, extension, after -+ -+g_cc_flag_vars = [ -+'CCDEPS', 'FRAMEWORK', 'FRAMEWORKPATH', -+'STATICLIB', 'LIB', 'LIBPATH', 'LINKFLAGS', 'RPATH', -+'CCFLAGS', 'CPPPATH', 'CPPFLAGS', 'CCDEFINES'] -+ -+EXT_CC = ['.c'] -+ -+g_cc_type_vars = ['CCFLAGS', 'LINKFLAGS'] -+ -+# TODO remove in waf 1.6 -+class cc_taskgen(ccroot.ccroot_abstract): -+ pass -+ -+@feature('cc') -+@before('apply_type_vars') -+@after('default_cc') -+def init_cc(self): -+ self.p_flag_vars = set(self.p_flag_vars).union(g_cc_flag_vars) -+ self.p_type_vars = set(self.p_type_vars).union(g_cc_type_vars) -+ -+ if not self.env['CC_NAME']: -+ raise Utils.WafError("At least one compiler (gcc, ..) must be selected") -+ -+@feature('cc') -+@after('apply_incpaths') -+def apply_obj_vars_cc(self): -+ """after apply_incpaths for INC_PATHS""" -+ env = self.env -+ app = env.append_unique -+ cpppath_st = env['CPPPATH_ST'] -+ -+ # local flags come first -+ # set the user-defined includes paths -+ for i in env['INC_PATHS']: -+ app('_CCINCFLAGS', cpppath_st % i.bldpath(env)) -+ app('_CCINCFLAGS', cpppath_st % i.srcpath(env)) -+ -+ # set the library include paths -+ for i in env['CPPPATH']: -+ app('_CCINCFLAGS', cpppath_st % i) -+ -+@feature('cc') -+@after('apply_lib_vars') -+def apply_defines_cc(self): -+ """after uselib is set for CCDEFINES""" -+ self.defines = getattr(self, 'defines', []) -+ lst = self.to_list(self.defines) + self.to_list(self.env['CCDEFINES']) -+ milst = [] -+ -+ # now process the local defines -+ for defi in lst: -+ if not defi in milst: -+ milst.append(defi) -+ -+ # CCDEFINES_ -+ libs = self.to_list(self.uselib) -+ for l in libs: -+ val = self.env['CCDEFINES_'+l] -+ if val: milst += val -+ self.env['DEFLINES'] = ["%s %s" % (x[0], Utils.trimquotes('='.join(x[1:]))) for x in [y.split('=') for y in milst]] -+ y = self.env['CCDEFINES_ST'] -+ self.env.append_unique('_CCDEFFLAGS', [y%x for x in milst]) -+ -+@extension(EXT_CC) -+def c_hook(self, node): -+ # create the compilation task: cpp or cc -+ if getattr(self, 'obj_ext', None): -+ obj_ext = self.obj_ext -+ else: -+ obj_ext = '_%d.o' % self.idx -+ -+ task = self.create_task('cc', node, node.change_ext(obj_ext)) -+ try: -+ self.compiled_tasks.append(task) -+ except AttributeError: -+ raise Utils.WafError('Have you forgotten to set the feature "cc" on %s?' % str(self)) -+ return task -+ -+cc_str = '${CC} ${CCFLAGS} ${CPPFLAGS} ${_CCINCFLAGS} ${_CCDEFFLAGS} ${CC_SRC_F}${SRC} ${CC_TGT_F}${TGT}' -+cls = Task.simple_task_type('cc', cc_str, 'GREEN', ext_out='.o', ext_in='.c', shell=False) -+cls.scan = ccroot.scan -+cls.vars.append('CCDEPS') -+ -+link_str = '${LINK_CC} ${CCLNK_SRC_F}${SRC} ${CCLNK_TGT_F}${TGT[0].abspath(env)} ${LINKFLAGS}' -+cls = Task.simple_task_type('cc_link', link_str, color='YELLOW', ext_in='.o', ext_out='.bin', shell=False) -+cls.maxjobs = 1 -+cls.install = Utils.nada -+ -diff --git a/buildtools/wafadmin/Tools/ccroot.py b/buildtools/wafadmin/Tools/ccroot.py -new file mode 100644 -index 0000000..f54c82f ---- /dev/null -+++ b/buildtools/wafadmin/Tools/ccroot.py -@@ -0,0 +1,629 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2005-2008 (ita) -+ -+"base for all c/c++ programs and libraries" -+ -+import os, sys, re -+import TaskGen, Task, Utils, preproc, Logs, Build, Options -+from Logs import error, debug, warn -+from Utils import md5 -+from TaskGen import taskgen, after, before, feature -+from Constants import * -+from Configure import conftest -+try: -+ from cStringIO import StringIO -+except ImportError: -+ from io import StringIO -+ -+import config_c # <- necessary for the configuration, do not touch -+ -+USE_TOP_LEVEL = False -+ -+def get_cc_version(conf, cc, gcc=False, icc=False): -+ -+ cmd = cc + ['-dM', '-E', '-'] -+ try: -+ p = Utils.pproc.Popen(cmd, stdin=Utils.pproc.PIPE, stdout=Utils.pproc.PIPE, stderr=Utils.pproc.PIPE) -+ p.stdin.write('\n') -+ out = p.communicate()[0] -+ except: -+ conf.fatal('could not determine the compiler version %r' % cmd) -+ -+ # PY3K: do not touch -+ out = str(out) -+ -+ if gcc: -+ if out.find('__INTEL_COMPILER') >= 0: -+ conf.fatal('The intel compiler pretends to be gcc') -+ if out.find('__GNUC__') < 0: -+ conf.fatal('Could not determine the compiler type') -+ -+ if icc and out.find('__INTEL_COMPILER') < 0: -+ conf.fatal('Not icc/icpc') -+ -+ k = {} -+ if icc or gcc: -+ out = out.split('\n') -+ import shlex -+ -+ for line in out: -+ lst = shlex.split(line) -+ if len(lst)>2: -+ key = lst[1] -+ val = lst[2] -+ k[key] = val -+ -+ def isD(var): -+ return var in k -+ -+ def isT(var): -+ return var in k and k[var] != '0' -+ -+ # Some documentation is available at http://predef.sourceforge.net -+ # The names given to DEST_OS must match what Utils.unversioned_sys_platform() returns. -+ mp1 = { -+ '__linux__' : 'linux', -+ '__GNU__' : 'gnu', -+ '__FreeBSD__' : 'freebsd', -+ '__NetBSD__' : 'netbsd', -+ '__OpenBSD__' : 'openbsd', -+ '__sun' : 'sunos', -+ '__hpux' : 'hpux', -+ '__sgi' : 'irix', -+ '_AIX' : 'aix', -+ '__CYGWIN__' : 'cygwin', -+ '__MSYS__' : 'msys', -+ '_UWIN' : 'uwin', -+ '_WIN64' : 'win32', -+ '_WIN32' : 'win32', -+ '__POWERPC__' : 'powerpc', -+ } -+ -+ for i in mp1: -+ if isD(i): -+ conf.env.DEST_OS = mp1[i] -+ break -+ else: -+ if isD('__APPLE__') and isD('__MACH__'): -+ conf.env.DEST_OS = 'darwin' -+ elif isD('__unix__'): # unix must be tested last as it's a generic fallback -+ conf.env.DEST_OS = 'generic' -+ -+ if isD('__ELF__'): -+ conf.env.DEST_BINFMT = 'elf' -+ elif isD('__WINNT__') or isD('__CYGWIN__'): -+ conf.env.DEST_BINFMT = 'pe' -+ elif isD('__APPLE__'): -+ conf.env.DEST_BINFMT = 'mac-o' -+ -+ mp2 = { -+ '__x86_64__' : 'x86_64', -+ '__i386__' : 'x86', -+ '__ia64__' : 'ia', -+ '__mips__' : 'mips', -+ '__sparc__' : 'sparc', -+ '__alpha__' : 'alpha', -+ '__arm__' : 'arm', -+ '__hppa__' : 'hppa', -+ '__powerpc__' : 'powerpc', -+ } -+ for i in mp2: -+ if isD(i): -+ conf.env.DEST_CPU = mp2[i] -+ break -+ -+ debug('ccroot: dest platform: ' + ' '.join([conf.env[x] or '?' for x in ('DEST_OS', 'DEST_BINFMT', 'DEST_CPU')])) -+ conf.env['CC_VERSION'] = (k['__GNUC__'], k['__GNUC_MINOR__'], k['__GNUC_PATCHLEVEL__']) -+ return k -+ -+class DEBUG_LEVELS: -+ """Will disappear in waf 1.6""" -+ ULTRADEBUG = "ultradebug" -+ DEBUG = "debug" -+ RELEASE = "release" -+ OPTIMIZED = "optimized" -+ CUSTOM = "custom" -+ -+ ALL = [ULTRADEBUG, DEBUG, RELEASE, OPTIMIZED, CUSTOM] -+ -+def scan(self): -+ "look for .h the .cpp need" -+ debug('ccroot: _scan_preprocessor(self, node, env, path_lst)') -+ -+ # TODO waf 1.6 - assume the default input has exactly one file -+ -+ if len(self.inputs) == 1: -+ node = self.inputs[0] -+ (nodes, names) = preproc.get_deps(node, self.env, nodepaths = self.env['INC_PATHS']) -+ if Logs.verbose: -+ debug('deps: deps for %s: %r; unresolved %r', str(node), nodes, names) -+ return (nodes, names) -+ -+ all_nodes = [] -+ all_names = [] -+ seen = set() -+ for node in self.inputs: -+ (nodes, names) = preproc.get_deps(node, self.env, nodepaths = self.env['INC_PATHS']) -+ if Logs.verbose: -+ debug('deps: deps for %s: %r; unresolved %r', str(node), nodes, names) -+ for x in nodes: -+ if id(x) in seen: continue -+ seen.add(id(x)) -+ all_nodes.append(x) -+ for x in names: -+ if not x in all_names: -+ all_names.append(x) -+ return (all_nodes, all_names) -+ -+class ccroot_abstract(TaskGen.task_gen): -+ "Parent class for programs and libraries in languages c, c++ and moc (Qt)" -+ def __init__(self, *k, **kw): -+ # COMPAT remove in waf 1.6 TODO -+ if len(k) > 1: -+ k = list(k) -+ if k[1][0] != 'c': -+ k[1] = 'c' + k[1] -+ TaskGen.task_gen.__init__(self, *k, **kw) -+ -+def get_target_name(self): -+ tp = 'program' -+ for x in self.features: -+ if x in ['cshlib', 'cstaticlib']: -+ tp = x.lstrip('c') -+ -+ pattern = self.env[tp + '_PATTERN'] -+ if not pattern: pattern = '%s' -+ -+ dir, name = os.path.split(self.target) -+ -+ if self.env.DEST_BINFMT == 'pe' and getattr(self, 'vnum', None) and 'cshlib' in self.features: -+ # include the version in the dll file name, -+ # the import lib file name stays unversionned. -+ name = name + '-' + self.vnum.split('.')[0] -+ -+ return os.path.join(dir, pattern % name) -+ -+@feature('cc', 'cxx') -+@before('apply_core') -+def default_cc(self): -+ """compiled_tasks attribute must be set before the '.c->.o' tasks can be created""" -+ Utils.def_attrs(self, -+ includes = '', -+ defines= '', -+ rpaths = '', -+ uselib = '', -+ uselib_local = '', -+ add_objects = '', -+ p_flag_vars = [], -+ p_type_vars = [], -+ compiled_tasks = [], -+ link_task = None) -+ -+ # The only thing we need for cross-compilation is DEST_BINFMT. -+ # At some point, we may reach a case where DEST_BINFMT is not enough, but for now it's sufficient. -+ # Currently, cross-compilation is auto-detected only for the gnu and intel compilers. -+ if not self.env.DEST_BINFMT: -+ # Infer the binary format from the os name. -+ self.env.DEST_BINFMT = Utils.unversioned_sys_platform_to_binary_format( -+ self.env.DEST_OS or Utils.unversioned_sys_platform()) -+ -+ if not self.env.BINDIR: self.env.BINDIR = Utils.subst_vars('${PREFIX}/bin', self.env) -+ if not self.env.LIBDIR: self.env.LIBDIR = Utils.subst_vars('${PREFIX}/lib${LIB_EXT}', self.env) -+ -+@feature('cprogram', 'dprogram', 'cstaticlib', 'dstaticlib', 'cshlib', 'dshlib') -+def apply_verif(self): -+ """no particular order, used for diagnostic""" -+ if not (self.source or getattr(self, 'add_objects', None) or getattr(self, 'uselib_local', None) or getattr(self, 'obj_files', None)): -+ raise Utils.WafError('no source files specified for %s' % self) -+ if not self.target: -+ raise Utils.WafError('no target for %s' % self) -+ -+# TODO reference the d programs, shlibs in d.py, not here -+ -+@feature('cprogram', 'dprogram') -+@after('default_cc') -+@before('apply_core') -+def vars_target_cprogram(self): -+ self.default_install_path = self.env.BINDIR -+ self.default_chmod = O755 -+ -+@after('default_cc') -+@feature('cshlib', 'dshlib') -+@before('apply_core') -+def vars_target_cshlib(self): -+ if self.env.DEST_BINFMT == 'pe': -+ # set execute bit on libs to avoid 'permission denied' (issue 283) -+ self.default_chmod = O755 -+ self.default_install_path = self.env.BINDIR -+ else: -+ self.default_install_path = self.env.LIBDIR -+ -+@feature('cprogram', 'dprogram', 'cstaticlib', 'dstaticlib', 'cshlib', 'dshlib') -+@after('apply_link', 'vars_target_cprogram', 'vars_target_cshlib') -+def default_link_install(self): -+ """you may kill this method to inject your own installation for the first element -+ any other install should only process its own nodes and not those from the others""" -+ if self.install_path: -+ self.bld.install_files(self.install_path, self.link_task.outputs[0], env=self.env, chmod=self.chmod) -+ -+@feature('cc', 'cxx') -+@after('apply_type_vars', 'apply_lib_vars', 'apply_core') -+def apply_incpaths(self): -+ """used by the scanner -+ after processing the uselib for CPPPATH -+ after apply_core because some processing may add include paths -+ """ -+ lst = [] -+ # TODO move the uselib processing out of here -+ for lib in self.to_list(self.uselib): -+ for path in self.env['CPPPATH_' + lib]: -+ if not path in lst: -+ lst.append(path) -+ if preproc.go_absolute: -+ for path in preproc.standard_includes: -+ if not path in lst: -+ lst.append(path) -+ -+ for path in self.to_list(self.includes): -+ if not path in lst: -+ if preproc.go_absolute or not os.path.isabs(path): -+ lst.append(path) -+ else: -+ self.env.prepend_value('CPPPATH', path) -+ -+ for path in lst: -+ node = None -+ if os.path.isabs(path): -+ if preproc.go_absolute: -+ node = self.bld.root.find_dir(path) -+ elif path[0] == '#': -+ node = self.bld.srcnode -+ if len(path) > 1: -+ node = node.find_dir(path[1:]) -+ else: -+ node = self.path.find_dir(path) -+ -+ if node: -+ self.env.append_value('INC_PATHS', node) -+ -+ # TODO WAF 1.6 -+ if USE_TOP_LEVEL: -+ self.env.append_value('INC_PATHS', self.bld.srcnode) -+ -+@feature('cc', 'cxx') -+@after('init_cc', 'init_cxx') -+@before('apply_lib_vars') -+def apply_type_vars(self): -+ """before apply_lib_vars because we modify uselib -+ after init_cc and init_cxx because web need p_type_vars -+ """ -+ for x in self.features: -+ if not x in ['cprogram', 'cstaticlib', 'cshlib']: -+ continue -+ x = x.lstrip('c') -+ -+ # if the type defines uselib to add, add them -+ st = self.env[x + '_USELIB'] -+ if st: self.uselib = self.uselib + ' ' + st -+ -+ # each compiler defines variables like 'shlib_CXXFLAGS', 'shlib_LINKFLAGS', etc -+ # so when we make a task generator of the type shlib, CXXFLAGS are modified accordingly -+ for var in self.p_type_vars: -+ compvar = '%s_%s' % (x, var) -+ #print compvar -+ value = self.env[compvar] -+ if value: self.env.append_value(var, value) -+ -+@feature('cprogram', 'cshlib', 'cstaticlib') -+@after('apply_core') -+def apply_link(self): -+ """executes after apply_core for collecting 'compiled_tasks' -+ use a custom linker if specified (self.link='name-of-custom-link-task')""" -+ link = getattr(self, 'link', None) -+ if not link: -+ if 'cstaticlib' in self.features: link = 'static_link' -+ elif 'cxx' in self.features: link = 'cxx_link' -+ else: link = 'cc_link' -+ -+ tsk = self.create_task(link) -+ outputs = [t.outputs[0] for t in self.compiled_tasks] -+ tsk.set_inputs(outputs) -+ tsk.set_outputs(self.path.find_or_declare(get_target_name(self))) -+ -+ self.link_task = tsk -+ -+@feature('cc', 'cxx') -+@after('apply_link', 'init_cc', 'init_cxx', 'apply_core') -+def apply_lib_vars(self): -+ """after apply_link because of 'link_task' -+ after default_cc because of the attribute 'uselib'""" -+ -+ # after 'apply_core' in case if 'cc' if there is no link -+ -+ env = self.env -+ -+ # 1. the case of the libs defined in the project (visit ancestors first) -+ # the ancestors external libraries (uselib) will be prepended -+ self.uselib = self.to_list(self.uselib) -+ names = self.to_list(self.uselib_local) -+ -+ seen = set([]) -+ tmp = Utils.deque(names) # consume a copy of the list of names -+ while tmp: -+ lib_name = tmp.popleft() -+ # visit dependencies only once -+ if lib_name in seen: -+ continue -+ -+ y = self.name_to_obj(lib_name) -+ if not y: -+ raise Utils.WafError('object %r was not found in uselib_local (required by %r)' % (lib_name, self.name)) -+ y.post() -+ seen.add(lib_name) -+ -+ # object has ancestors to process (shared libraries): add them to the end of the list -+ if getattr(y, 'uselib_local', None): -+ lst = y.to_list(y.uselib_local) -+ if 'cshlib' in y.features or 'cprogram' in y.features: -+ lst = [x for x in lst if not 'cstaticlib' in self.name_to_obj(x).features] -+ tmp.extend(lst) -+ -+ # link task and flags -+ if getattr(y, 'link_task', None): -+ -+ link_name = y.target[y.target.rfind(os.sep) + 1:] -+ if 'cstaticlib' in y.features: -+ env.append_value('STATICLIB', link_name) -+ elif 'cshlib' in y.features or 'cprogram' in y.features: -+ # WARNING some linkers can link against programs -+ env.append_value('LIB', link_name) -+ -+ # the order -+ self.link_task.set_run_after(y.link_task) -+ -+ # for the recompilation -+ dep_nodes = getattr(self.link_task, 'dep_nodes', []) -+ self.link_task.dep_nodes = dep_nodes + y.link_task.outputs -+ -+ # add the link path too -+ tmp_path = y.link_task.outputs[0].parent.bldpath(self.env) -+ if not tmp_path in env['LIBPATH']: env.prepend_value('LIBPATH', tmp_path) -+ -+ # add ancestors uselib too - but only propagate those that have no staticlib -+ for v in self.to_list(y.uselib): -+ if not env['STATICLIB_' + v]: -+ if not v in self.uselib: -+ self.uselib.insert(0, v) -+ -+ # if the library task generator provides 'export_incdirs', add to the include path -+ # the export_incdirs must be a list of paths relative to the other library -+ if getattr(y, 'export_incdirs', None): -+ for x in self.to_list(y.export_incdirs): -+ node = y.path.find_dir(x) -+ if not node: -+ raise Utils.WafError('object %r: invalid folder %r in export_incdirs' % (y.target, x)) -+ self.env.append_unique('INC_PATHS', node) -+ -+ # 2. the case of the libs defined outside -+ for x in self.uselib: -+ for v in self.p_flag_vars: -+ val = self.env[v + '_' + x] -+ if val: self.env.append_value(v, val) -+ -+@feature('cprogram', 'cstaticlib', 'cshlib') -+@after('init_cc', 'init_cxx', 'apply_link') -+def apply_objdeps(self): -+ "add the .o files produced by some other object files in the same manner as uselib_local" -+ if not getattr(self, 'add_objects', None): return -+ -+ seen = [] -+ names = self.to_list(self.add_objects) -+ while names: -+ x = names[0] -+ -+ # visit dependencies only once -+ if x in seen: -+ names = names[1:] -+ continue -+ -+ # object does not exist ? -+ y = self.name_to_obj(x) -+ if not y: -+ raise Utils.WafError('object %r was not found in uselib_local (required by add_objects %r)' % (x, self.name)) -+ -+ # object has ancestors to process first ? update the list of names -+ if getattr(y, 'add_objects', None): -+ added = 0 -+ lst = y.to_list(y.add_objects) -+ lst.reverse() -+ for u in lst: -+ if u in seen: continue -+ added = 1 -+ names = [u]+names -+ if added: continue # list of names modified, loop -+ -+ # safe to process the current object -+ y.post() -+ seen.append(x) -+ -+ for t in y.compiled_tasks: -+ self.link_task.inputs.extend(t.outputs) -+ -+@feature('cprogram', 'cshlib', 'cstaticlib') -+@after('apply_lib_vars') -+def apply_obj_vars(self): -+ """after apply_lib_vars for uselib""" -+ v = self.env -+ lib_st = v['LIB_ST'] -+ staticlib_st = v['STATICLIB_ST'] -+ libpath_st = v['LIBPATH_ST'] -+ staticlibpath_st = v['STATICLIBPATH_ST'] -+ rpath_st = v['RPATH_ST'] -+ -+ app = v.append_unique -+ -+ if v['FULLSTATIC']: -+ v.append_value('LINKFLAGS', v['FULLSTATIC_MARKER']) -+ -+ for i in v['RPATH']: -+ if i and rpath_st: -+ app('LINKFLAGS', rpath_st % i) -+ -+ for i in v['LIBPATH']: -+ app('LINKFLAGS', libpath_st % i) -+ app('LINKFLAGS', staticlibpath_st % i) -+ -+ if v['STATICLIB']: -+ v.append_value('LINKFLAGS', v['STATICLIB_MARKER']) -+ k = [(staticlib_st % i) for i in v['STATICLIB']] -+ app('LINKFLAGS', k) -+ -+ # fully static binaries ? -+ if not v['FULLSTATIC']: -+ if v['STATICLIB'] or v['LIB']: -+ v.append_value('LINKFLAGS', v['SHLIB_MARKER']) -+ -+ app('LINKFLAGS', [lib_st % i for i in v['LIB']]) -+ -+@after('apply_link') -+def process_obj_files(self): -+ if not hasattr(self, 'obj_files'): return -+ for x in self.obj_files: -+ node = self.path.find_resource(x) -+ self.link_task.inputs.append(node) -+ -+@taskgen -+def add_obj_file(self, file): -+ """Small example on how to link object files as if they were source -+ obj = bld.create_obj('cc') -+ obj.add_obj_file('foo.o')""" -+ if not hasattr(self, 'obj_files'): self.obj_files = [] -+ if not 'process_obj_files' in self.meths: self.meths.append('process_obj_files') -+ self.obj_files.append(file) -+ -+c_attrs = { -+'cxxflag' : 'CXXFLAGS', -+'cflag' : 'CCFLAGS', -+'ccflag' : 'CCFLAGS', -+'linkflag' : 'LINKFLAGS', -+'ldflag' : 'LINKFLAGS', -+'lib' : 'LIB', -+'libpath' : 'LIBPATH', -+'staticlib': 'STATICLIB', -+'staticlibpath': 'STATICLIBPATH', -+'rpath' : 'RPATH', -+'framework' : 'FRAMEWORK', -+'frameworkpath' : 'FRAMEWORKPATH' -+} -+ -+@feature('cc', 'cxx') -+@before('init_cxx', 'init_cc') -+@before('apply_lib_vars', 'apply_obj_vars', 'apply_incpaths', 'init_cc') -+def add_extra_flags(self): -+ """case and plural insensitive -+ before apply_obj_vars for processing the library attributes -+ """ -+ for x in self.__dict__.keys(): -+ y = x.lower() -+ if y[-1] == 's': -+ y = y[:-1] -+ if c_attrs.get(y, None): -+ self.env.append_unique(c_attrs[y], getattr(self, x)) -+ -+# ============ the code above must not know anything about import libs ========== -+ -+@feature('cshlib') -+@after('apply_link', 'default_cc') -+@before('apply_lib_vars', 'apply_objdeps', 'default_link_install') -+def apply_implib(self): -+ """On mswindows, handle dlls and their import libs -+ the .dll.a is the import lib and it is required for linking so it is installed too -+ """ -+ if not self.env.DEST_BINFMT == 'pe': -+ return -+ -+ self.meths.remove('default_link_install') -+ -+ bindir = self.install_path -+ if not bindir: return -+ -+ # install the dll in the bin dir -+ dll = self.link_task.outputs[0] -+ self.bld.install_files(bindir, dll, self.env, self.chmod) -+ -+ # add linker flags to generate the import lib -+ implib = self.env['implib_PATTERN'] % os.path.split(self.target)[1] -+ -+ implib = dll.parent.find_or_declare(implib) -+ self.link_task.outputs.append(implib) -+ self.bld.install_as('${LIBDIR}/%s' % implib.name, implib, self.env) -+ -+ self.env.append_value('LINKFLAGS', (self.env['IMPLIB_ST'] % implib.bldpath(self.env)).split()) -+ -+# ============ the code above must not know anything about vnum processing on unix platforms ========= -+ -+@feature('cshlib') -+@after('apply_link') -+@before('apply_lib_vars', 'default_link_install') -+def apply_vnum(self): -+ """ -+ libfoo.so is installed as libfoo.so.1.2.3 -+ """ -+ if not getattr(self, 'vnum', '') or not 'cshlib' in self.features or os.name != 'posix' or self.env.DEST_BINFMT not in ('elf', 'mac-o'): -+ return -+ -+ self.meths.remove('default_link_install') -+ -+ link = self.link_task -+ nums = self.vnum.split('.') -+ node = link.outputs[0] -+ -+ libname = node.name -+ if libname.endswith('.dylib'): -+ name3 = libname.replace('.dylib', '.%s.dylib' % self.vnum) -+ name2 = libname.replace('.dylib', '.%s.dylib' % nums[0]) -+ else: -+ name3 = libname + '.' + self.vnum -+ name2 = libname + '.' + nums[0] -+ -+ if self.env.SONAME_ST: -+ v = self.env.SONAME_ST % name2 -+ self.env.append_value('LINKFLAGS', v.split()) -+ -+ bld = self.bld -+ nums = self.vnum.split('.') -+ -+ path = self.install_path -+ if not path: return -+ -+ bld.install_as(path + os.sep + name3, node, env=self.env) -+ bld.symlink_as(path + os.sep + name2, name3) -+ bld.symlink_as(path + os.sep + libname, name3) -+ -+ # the following task is just to enable execution from the build dir :-/ -+ self.create_task('vnum', node, [node.parent.find_or_declare(name2), node.parent.find_or_declare(name3)]) -+ -+def exec_vnum_link(self): -+ for x in self.outputs: -+ path = x.abspath(self.env) -+ try: -+ os.remove(path) -+ except OSError: -+ pass -+ -+ try: -+ os.symlink(self.inputs[0].name, path) -+ except OSError: -+ return 1 -+ -+cls = Task.task_type_from_func('vnum', func=exec_vnum_link, ext_in='.bin', color='CYAN') -+cls.quiet = 1 -+ -+# ============ the --as-needed flag should added during the configuration, not at runtime ========= -+ -+@conftest -+def add_as_needed(conf): -+ if conf.env.DEST_BINFMT == 'elf' and 'gcc' in (conf.env.CXX_NAME, conf.env.CC_NAME): -+ conf.env.append_unique('LINKFLAGS', '--as-needed') -+ -diff --git a/buildtools/wafadmin/Tools/compiler_cc.py b/buildtools/wafadmin/Tools/compiler_cc.py -new file mode 100644 -index 0000000..0421503 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/compiler_cc.py -@@ -0,0 +1,67 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Matthias Jahn jahn dôt matthias ât freenet dôt de, 2007 (pmarat) -+ -+import os, sys, imp, types, ccroot -+import optparse -+import Utils, Configure, Options -+from Logs import debug -+ -+c_compiler = { -+ 'win32': ['msvc', 'gcc'], -+ 'cygwin': ['gcc'], -+ 'darwin': ['gcc'], -+ 'aix': ['xlc', 'gcc'], -+ 'linux': ['gcc', 'icc', 'suncc'], -+ 'sunos': ['gcc', 'suncc'], -+ 'irix': ['gcc'], -+ 'hpux': ['gcc'], -+ 'gnu': ['gcc'], -+ 'default': ['gcc'] -+} -+ -+def __list_possible_compiler(platform): -+ try: -+ return c_compiler[platform] -+ except KeyError: -+ return c_compiler["default"] -+ -+def detect(conf): -+ """ -+ for each compiler for the platform, try to configure the compiler -+ in theory the tools should raise a configuration error if the compiler -+ pretends to be something it is not (setting CC=icc and trying to configure gcc) -+ """ -+ try: test_for_compiler = Options.options.check_c_compiler -+ except AttributeError: conf.fatal("Add set_options(opt): opt.tool_options('compiler_cc')") -+ orig = conf.env -+ for compiler in test_for_compiler.split(): -+ conf.env = orig.copy() -+ try: -+ conf.check_tool(compiler) -+ except Configure.ConfigurationError, e: -+ debug('compiler_cc: %r' % e) -+ else: -+ if conf.env['CC']: -+ orig.table = conf.env.get_merged_dict() -+ conf.env = orig -+ conf.check_message(compiler, '', True) -+ conf.env['COMPILER_CC'] = compiler -+ break -+ conf.check_message(compiler, '', False) -+ break -+ else: -+ conf.fatal('could not configure a c compiler!') -+ -+def set_options(opt): -+ build_platform = Utils.unversioned_sys_platform() -+ possible_compiler_list = __list_possible_compiler(build_platform) -+ test_for_compiler = ' '.join(possible_compiler_list) -+ cc_compiler_opts = opt.add_option_group("C Compiler Options") -+ cc_compiler_opts.add_option('--check-c-compiler', default="%s" % test_for_compiler, -+ help='On this platform (%s) the following C-Compiler will be checked by default: "%s"' % (build_platform, test_for_compiler), -+ dest="check_c_compiler") -+ -+ for c_compiler in test_for_compiler.split(): -+ opt.tool_options('%s' % c_compiler, option_group=cc_compiler_opts) -+ -diff --git a/buildtools/wafadmin/Tools/compiler_cxx.py b/buildtools/wafadmin/Tools/compiler_cxx.py -new file mode 100644 -index 0000000..5308ea9 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/compiler_cxx.py -@@ -0,0 +1,62 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Matthias Jahn jahn dôt matthias ât freenet dôt de 2007 (pmarat) -+ -+import os, sys, imp, types, ccroot -+import optparse -+import Utils, Configure, Options -+from Logs import debug -+ -+cxx_compiler = { -+'win32': ['msvc', 'g++'], -+'cygwin': ['g++'], -+'darwin': ['g++'], -+'aix': ['xlc++', 'g++'], -+'linux': ['g++', 'icpc', 'sunc++'], -+'sunos': ['g++', 'sunc++'], -+'irix': ['g++'], -+'hpux': ['g++'], -+'gnu': ['g++'], -+'default': ['g++'] -+} -+ -+def __list_possible_compiler(platform): -+ try: -+ return cxx_compiler[platform] -+ except KeyError: -+ return cxx_compiler["default"] -+ -+def detect(conf): -+ try: test_for_compiler = Options.options.check_cxx_compiler -+ except AttributeError: raise Configure.ConfigurationError("Add set_options(opt): opt.tool_options('compiler_cxx')") -+ orig = conf.env -+ for compiler in test_for_compiler.split(): -+ try: -+ conf.env = orig.copy() -+ conf.check_tool(compiler) -+ except Configure.ConfigurationError, e: -+ debug('compiler_cxx: %r' % e) -+ else: -+ if conf.env['CXX']: -+ orig.table = conf.env.get_merged_dict() -+ conf.env = orig -+ conf.check_message(compiler, '', True) -+ conf.env['COMPILER_CXX'] = compiler -+ break -+ conf.check_message(compiler, '', False) -+ break -+ else: -+ conf.fatal('could not configure a cxx compiler!') -+ -+def set_options(opt): -+ build_platform = Utils.unversioned_sys_platform() -+ possible_compiler_list = __list_possible_compiler(build_platform) -+ test_for_compiler = ' '.join(possible_compiler_list) -+ cxx_compiler_opts = opt.add_option_group('C++ Compiler Options') -+ cxx_compiler_opts.add_option('--check-cxx-compiler', default="%s" % test_for_compiler, -+ help='On this platform (%s) the following C++ Compiler will be checked by default: "%s"' % (build_platform, test_for_compiler), -+ dest="check_cxx_compiler") -+ -+ for cxx_compiler in test_for_compiler.split(): -+ opt.tool_options('%s' % cxx_compiler, option_group=cxx_compiler_opts) -+ -diff --git a/buildtools/wafadmin/Tools/compiler_d.py b/buildtools/wafadmin/Tools/compiler_d.py -new file mode 100644 -index 0000000..1ea5efa ---- /dev/null -+++ b/buildtools/wafadmin/Tools/compiler_d.py -@@ -0,0 +1,33 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Carlos Rafael Giani, 2007 (dv) -+ -+import os, sys, imp, types -+import Utils, Configure, Options -+ -+def detect(conf): -+ if getattr(Options.options, 'check_dmd_first', None): -+ test_for_compiler = ['dmd', 'gdc'] -+ else: -+ test_for_compiler = ['gdc', 'dmd'] -+ -+ for d_compiler in test_for_compiler: -+ try: -+ conf.check_tool(d_compiler) -+ except: -+ pass -+ else: -+ break -+ else: -+ conf.fatal('no suitable d compiler was found') -+ -+def set_options(opt): -+ d_compiler_opts = opt.add_option_group('D Compiler Options') -+ d_compiler_opts.add_option('--check-dmd-first', action='store_true', -+ help='checks for the gdc compiler before dmd (default is the other way round)', -+ dest='check_dmd_first', -+ default=False) -+ -+ for d_compiler in ['gdc', 'dmd']: -+ opt.tool_options('%s' % d_compiler, option_group=d_compiler_opts) -+ -diff --git a/buildtools/wafadmin/Tools/config_c.py b/buildtools/wafadmin/Tools/config_c.py -new file mode 100644 -index 0000000..a32d8aa ---- /dev/null -+++ b/buildtools/wafadmin/Tools/config_c.py -@@ -0,0 +1,736 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2005-2008 (ita) -+ -+""" -+c/c++ configuration routines -+""" -+ -+import os, imp, sys, shlex, shutil -+from Utils import md5 -+import Build, Utils, Configure, Task, Options, Logs, TaskGen -+from Constants import * -+from Configure import conf, conftest -+ -+cfg_ver = { -+ 'atleast-version': '>=', -+ 'exact-version': '==', -+ 'max-version': '<=', -+} -+ -+SNIP1 = ''' -+ int main() { -+ void *p; -+ p=(void*)(%s); -+ return 0; -+} -+''' -+ -+SNIP2 = ''' -+int main() { -+ if ((%(type_name)s *) 0) return 0; -+ if (sizeof (%(type_name)s)) return 0; -+} -+''' -+ -+SNIP3 = ''' -+int main() { -+ return 0; -+} -+''' -+ -+def parse_flags(line, uselib, env): -+ """pkg-config still has bugs on some platforms, and there are many -config programs, parsing flags is necessary :-/""" -+ -+ lst = shlex.split(line) -+ while lst: -+ x = lst.pop(0) -+ st = x[:2] -+ ot = x[2:] -+ app = env.append_value -+ if st == '-I' or st == '/I': -+ if not ot: ot = lst.pop(0) -+ app('CPPPATH_' + uselib, ot) -+ elif st == '-D': -+ if not ot: ot = lst.pop(0) -+ app('CXXDEFINES_' + uselib, ot) -+ app('CCDEFINES_' + uselib, ot) -+ elif st == '-l': -+ if not ot: ot = lst.pop(0) -+ app('LIB_' + uselib, ot) -+ elif st == '-L': -+ if not ot: ot = lst.pop(0) -+ app('LIBPATH_' + uselib, ot) -+ elif x == '-pthread' or x.startswith('+'): -+ app('CCFLAGS_' + uselib, x) -+ app('CXXFLAGS_' + uselib, x) -+ app('LINKFLAGS_' + uselib, x) -+ elif x == '-framework': -+ app('FRAMEWORK_' + uselib, lst.pop(0)) -+ elif x.startswith('-F'): -+ app('FRAMEWORKPATH_' + uselib, x[2:]) -+ elif x.startswith('-std'): -+ app('CCFLAGS_' + uselib, x) -+ app('CXXFLAGS_' + uselib, x) -+ app('LINKFLAGS_' + uselib, x) -+ elif x.startswith('-Wl'): -+ app('LINKFLAGS_' + uselib, x) -+ elif x.startswith('-m') or x.startswith('-f'): -+ app('CCFLAGS_' + uselib, x) -+ app('CXXFLAGS_' + uselib, x) -+ -+@conf -+def ret_msg(self, f, kw): -+ """execute a function, when provided""" -+ if isinstance(f, str): -+ return f -+ return f(kw) -+ -+@conf -+def validate_cfg(self, kw): -+ if not 'path' in kw: -+ kw['path'] = 'pkg-config --errors-to-stdout --print-errors' -+ -+ # pkg-config version -+ if 'atleast_pkgconfig_version' in kw: -+ if not 'msg' in kw: -+ kw['msg'] = 'Checking for pkg-config version >= %s' % kw['atleast_pkgconfig_version'] -+ return -+ -+ # pkg-config --modversion -+ if 'modversion' in kw: -+ return -+ -+ if 'variables' in kw: -+ if not 'msg' in kw: -+ kw['msg'] = 'Checking for %s variables' % kw['package'] -+ return -+ -+ # checking for the version of a module, for the moment, one thing at a time -+ for x in cfg_ver.keys(): -+ y = x.replace('-', '_') -+ if y in kw: -+ if not 'package' in kw: -+ raise ValueError('%s requires a package' % x) -+ -+ if not 'msg' in kw: -+ kw['msg'] = 'Checking for %s %s %s' % (kw['package'], cfg_ver[x], kw[y]) -+ return -+ -+ if not 'msg' in kw: -+ kw['msg'] = 'Checking for %s' % (kw['package'] or kw['path']) -+ if not 'okmsg' in kw: -+ kw['okmsg'] = 'yes' -+ if not 'errmsg' in kw: -+ kw['errmsg'] = 'not found' -+ -+@conf -+def cmd_and_log(self, cmd, kw): -+ Logs.debug('runner: %s\n' % cmd) -+ if self.log: -+ self.log.write('%s\n' % cmd) -+ -+ try: -+ p = Utils.pproc.Popen(cmd, stdout=Utils.pproc.PIPE, stderr=Utils.pproc.PIPE, shell=True) -+ (out, err) = p.communicate() -+ except OSError, e: -+ self.log.write('error %r' % e) -+ self.fatal(str(e)) -+ -+ # placeholder, don't touch -+ out = str(out) -+ err = str(err) -+ -+ if self.log: -+ self.log.write(out) -+ self.log.write(err) -+ -+ if p.returncode: -+ if not kw.get('errmsg', ''): -+ if kw.get('mandatory', False): -+ kw['errmsg'] = out.strip() -+ else: -+ kw['errmsg'] = 'no' -+ self.fatal('fail') -+ return out -+ -+@conf -+def exec_cfg(self, kw): -+ -+ # pkg-config version -+ if 'atleast_pkgconfig_version' in kw: -+ cmd = '%s --atleast-pkgconfig-version=%s' % (kw['path'], kw['atleast_pkgconfig_version']) -+ self.cmd_and_log(cmd, kw) -+ if not 'okmsg' in kw: -+ kw['okmsg'] = 'yes' -+ return -+ -+ # checking for the version of a module -+ for x in cfg_ver: -+ y = x.replace('-', '_') -+ if y in kw: -+ self.cmd_and_log('%s --%s=%s %s' % (kw['path'], x, kw[y], kw['package']), kw) -+ if not 'okmsg' in kw: -+ kw['okmsg'] = 'yes' -+ self.define(self.have_define(kw.get('uselib_store', kw['package'])), 1, 0) -+ break -+ -+ # retrieving the version of a module -+ if 'modversion' in kw: -+ version = self.cmd_and_log('%s --modversion %s' % (kw['path'], kw['modversion']), kw).strip() -+ self.define('%s_VERSION' % Utils.quote_define_name(kw.get('uselib_store', kw['modversion'])), version) -+ return version -+ -+ # retrieving variables of a module -+ if 'variables' in kw: -+ env = kw.get('env', self.env) -+ uselib = kw.get('uselib_store', kw['package'].upper()) -+ vars = Utils.to_list(kw['variables']) -+ for v in vars: -+ val = self.cmd_and_log('%s --variable=%s %s' % (kw['path'], v, kw['package']), kw).strip() -+ var = '%s_%s' % (uselib, v) -+ env[var] = val -+ if not 'okmsg' in kw: -+ kw['okmsg'] = 'yes' -+ return -+ -+ lst = [kw['path']] -+ -+ -+ defi = kw.get('define_variable', None) -+ if not defi: -+ defi = self.env.PKG_CONFIG_DEFINES or {} -+ for key, val in defi.iteritems(): -+ lst.append('--define-variable=%s=%s' % (key, val)) -+ -+ lst.append(kw.get('args', '')) -+ lst.append(kw['package']) -+ -+ # so we assume the command-line will output flags to be parsed afterwards -+ cmd = ' '.join(lst) -+ ret = self.cmd_and_log(cmd, kw) -+ if not 'okmsg' in kw: -+ kw['okmsg'] = 'yes' -+ -+ self.define(self.have_define(kw.get('uselib_store', kw['package'])), 1, 0) -+ parse_flags(ret, kw.get('uselib_store', kw['package'].upper()), kw.get('env', self.env)) -+ return ret -+ -+@conf -+def check_cfg(self, *k, **kw): -+ """ -+ for pkg-config mostly, but also all the -config tools -+ conf.check_cfg(path='mpicc', args='--showme:compile --showme:link', package='', uselib_store='OPEN_MPI') -+ conf.check_cfg(package='dbus-1', variables='system_bus_default_address session_bus_services_dir') -+ """ -+ -+ self.validate_cfg(kw) -+ if 'msg' in kw: -+ self.check_message_1(kw['msg']) -+ ret = None -+ try: -+ ret = self.exec_cfg(kw) -+ except Configure.ConfigurationError, e: -+ if 'errmsg' in kw: -+ self.check_message_2(kw['errmsg'], 'YELLOW') -+ if 'mandatory' in kw and kw['mandatory']: -+ if Logs.verbose > 1: -+ raise -+ else: -+ self.fatal('the configuration failed (see %r)' % self.log.name) -+ else: -+ kw['success'] = ret -+ if 'okmsg' in kw: -+ self.check_message_2(self.ret_msg(kw['okmsg'], kw)) -+ -+ return ret -+ -+# the idea is the following: now that we are certain -+# that all the code here is only for c or c++, it is -+# easy to put all the logic in one function -+# -+# this should prevent code duplication (ita) -+ -+# env: an optional environment (modified -> provide a copy) -+# compiler: cc or cxx - it tries to guess what is best -+# type: cprogram, cshlib, cstaticlib -+# code: a c code to execute -+# uselib_store: where to add the variables -+# uselib: parameters to use for building -+# define: define to set, like FOO in #define FOO, if not set, add /* #undef FOO */ -+# execute: True or False - will return the result of the execution -+ -+@conf -+def validate_c(self, kw): -+ """validate the parameters for the test method""" -+ -+ if not 'env' in kw: -+ kw['env'] = self.env.copy() -+ -+ env = kw['env'] -+ if not 'compiler' in kw: -+ kw['compiler'] = 'cc' -+ if env['CXX_NAME'] and Task.TaskBase.classes.get('cxx', None): -+ kw['compiler'] = 'cxx' -+ if not self.env['CXX']: -+ self.fatal('a c++ compiler is required') -+ else: -+ if not self.env['CC']: -+ self.fatal('a c compiler is required') -+ -+ if not 'type' in kw: -+ kw['type'] = 'cprogram' -+ -+ assert not(kw['type'] != 'cprogram' and kw.get('execute', 0)), 'can only execute programs' -+ -+ -+ #if kw['type'] != 'program' and kw.get('execute', 0): -+ # raise ValueError, 'can only execute programs' -+ -+ def to_header(dct): -+ if 'header_name' in dct: -+ dct = Utils.to_list(dct['header_name']) -+ return ''.join(['#include <%s>\n' % x for x in dct]) -+ return '' -+ -+ # set the file name -+ if not 'compile_mode' in kw: -+ kw['compile_mode'] = (kw['compiler'] == 'cxx') and 'cxx' or 'cc' -+ -+ if not 'compile_filename' in kw: -+ kw['compile_filename'] = 'test.c' + ((kw['compile_mode'] == 'cxx') and 'pp' or '') -+ -+ #OSX -+ if 'framework_name' in kw: -+ try: TaskGen.task_gen.create_task_macapp -+ except AttributeError: self.fatal('frameworks require the osx tool') -+ -+ fwkname = kw['framework_name'] -+ if not 'uselib_store' in kw: -+ kw['uselib_store'] = fwkname.upper() -+ -+ if not kw.get('no_header', False): -+ if not 'header_name' in kw: -+ kw['header_name'] = [] -+ fwk = '%s/%s.h' % (fwkname, fwkname) -+ if kw.get('remove_dot_h', None): -+ fwk = fwk[:-2] -+ kw['header_name'] = Utils.to_list(kw['header_name']) + [fwk] -+ -+ kw['msg'] = 'Checking for framework %s' % fwkname -+ kw['framework'] = fwkname -+ #kw['frameworkpath'] = set it yourself -+ -+ if 'function_name' in kw: -+ fu = kw['function_name'] -+ if not 'msg' in kw: -+ kw['msg'] = 'Checking for function %s' % fu -+ kw['code'] = to_header(kw) + SNIP1 % fu -+ if not 'uselib_store' in kw: -+ kw['uselib_store'] = fu.upper() -+ if not 'define_name' in kw: -+ kw['define_name'] = self.have_define(fu) -+ -+ elif 'type_name' in kw: -+ tu = kw['type_name'] -+ if not 'msg' in kw: -+ kw['msg'] = 'Checking for type %s' % tu -+ if not 'header_name' in kw: -+ kw['header_name'] = 'stdint.h' -+ kw['code'] = to_header(kw) + SNIP2 % {'type_name' : tu} -+ if not 'define_name' in kw: -+ kw['define_name'] = self.have_define(tu.upper()) -+ -+ elif 'header_name' in kw: -+ if not 'msg' in kw: -+ kw['msg'] = 'Checking for header %s' % kw['header_name'] -+ -+ l = Utils.to_list(kw['header_name']) -+ assert len(l)>0, 'list of headers in header_name is empty' -+ -+ kw['code'] = to_header(kw) + SNIP3 -+ -+ if not 'uselib_store' in kw: -+ kw['uselib_store'] = l[0].upper() -+ -+ if not 'define_name' in kw: -+ kw['define_name'] = self.have_define(l[0]) -+ -+ if 'lib' in kw: -+ if not 'msg' in kw: -+ kw['msg'] = 'Checking for library %s' % kw['lib'] -+ if not 'uselib_store' in kw: -+ kw['uselib_store'] = kw['lib'].upper() -+ -+ if 'staticlib' in kw: -+ if not 'msg' in kw: -+ kw['msg'] = 'Checking for static library %s' % kw['staticlib'] -+ if not 'uselib_store' in kw: -+ kw['uselib_store'] = kw['staticlib'].upper() -+ -+ if 'fragment' in kw: -+ # an additional code fragment may be provided to replace the predefined code -+ # in custom headers -+ kw['code'] = kw['fragment'] -+ if not 'msg' in kw: -+ kw['msg'] = 'Checking for custom code' -+ if not 'errmsg' in kw: -+ kw['errmsg'] = 'no' -+ -+ for (flagsname,flagstype) in [('cxxflags','compiler'), ('cflags','compiler'), ('linkflags','linker')]: -+ if flagsname in kw: -+ if not 'msg' in kw: -+ kw['msg'] = 'Checking for %s flags %s' % (flagstype, kw[flagsname]) -+ if not 'errmsg' in kw: -+ kw['errmsg'] = 'no' -+ -+ if not 'execute' in kw: -+ kw['execute'] = False -+ -+ if not 'errmsg' in kw: -+ kw['errmsg'] = 'not found' -+ -+ if not 'okmsg' in kw: -+ kw['okmsg'] = 'yes' -+ -+ if not 'code' in kw: -+ kw['code'] = SNIP3 -+ -+ if not kw.get('success'): kw['success'] = None -+ -+ assert 'msg' in kw, 'invalid parameters, read http://freehackers.org/~tnagy/wafbook/single.html#config_helpers_c' -+ -+@conf -+def post_check(self, *k, **kw): -+ "set the variables after a test was run successfully" -+ -+ is_success = False -+ if kw['execute']: -+ if kw['success'] is not None: -+ is_success = True -+ else: -+ is_success = (kw['success'] == 0) -+ -+ if 'define_name' in kw: -+ if 'header_name' in kw or 'function_name' in kw or 'type_name' in kw or 'fragment' in kw: -+ if kw['execute']: -+ key = kw['success'] -+ if isinstance(key, str): -+ if key: -+ self.define(kw['define_name'], key, quote=kw.get('quote', 1)) -+ else: -+ self.define_cond(kw['define_name'], True) -+ else: -+ self.define_cond(kw['define_name'], False) -+ else: -+ self.define_cond(kw['define_name'], is_success) -+ -+ if is_success and 'uselib_store' in kw: -+ import cc, cxx -+ for k in set(cc.g_cc_flag_vars).union(cxx.g_cxx_flag_vars): -+ lk = k.lower() -+ # inconsistency: includes -> CPPPATH -+ if k == 'CPPPATH': lk = 'includes' -+ if k == 'CXXDEFINES': lk = 'defines' -+ if k == 'CCDEFINES': lk = 'defines' -+ if lk in kw: -+ val = kw[lk] -+ # remove trailing slash -+ if isinstance(val, str): -+ val = val.rstrip(os.path.sep) -+ self.env.append_unique(k + '_' + kw['uselib_store'], val) -+ -+@conf -+def check(self, *k, **kw): -+ # so this will be the generic function -+ # it will be safer to use check_cxx or check_cc -+ self.validate_c(kw) -+ self.check_message_1(kw['msg']) -+ ret = None -+ try: -+ ret = self.run_c_code(*k, **kw) -+ except Configure.ConfigurationError, e: -+ self.check_message_2(kw['errmsg'], 'YELLOW') -+ if 'mandatory' in kw and kw['mandatory']: -+ if Logs.verbose > 1: -+ raise -+ else: -+ self.fatal('the configuration failed (see %r)' % self.log.name) -+ else: -+ kw['success'] = ret -+ self.check_message_2(self.ret_msg(kw['okmsg'], kw)) -+ -+ self.post_check(*k, **kw) -+ if not kw.get('execute', False): -+ return ret == 0 -+ return ret -+ -+@conf -+def run_c_code(self, *k, **kw): -+ test_f_name = kw['compile_filename'] -+ -+ k = 0 -+ while k < 10000: -+ # make certain to use a fresh folder - necessary for win32 -+ dir = os.path.join(self.blddir, '.conf_check_%d' % k) -+ -+ # if the folder already exists, remove it -+ try: -+ shutil.rmtree(dir) -+ except OSError: -+ pass -+ -+ try: -+ os.stat(dir) -+ except OSError: -+ break -+ -+ k += 1 -+ -+ try: -+ os.makedirs(dir) -+ except: -+ self.fatal('cannot create a configuration test folder %r' % dir) -+ -+ try: -+ os.stat(dir) -+ except: -+ self.fatal('cannot use the configuration test folder %r' % dir) -+ -+ bdir = os.path.join(dir, 'testbuild') -+ -+ if not os.path.exists(bdir): -+ os.makedirs(bdir) -+ -+ env = kw['env'] -+ -+ dest = open(os.path.join(dir, test_f_name), 'w') -+ dest.write(kw['code']) -+ dest.close() -+ -+ back = os.path.abspath('.') -+ -+ bld = Build.BuildContext() -+ bld.log = self.log -+ bld.all_envs.update(self.all_envs) -+ bld.all_envs['default'] = env -+ bld.lst_variants = bld.all_envs.keys() -+ bld.load_dirs(dir, bdir) -+ -+ os.chdir(dir) -+ -+ bld.rescan(bld.srcnode) -+ -+ if not 'features' in kw: -+ # conf.check(features='cc cprogram pyext', ...) -+ kw['features'] = [kw['compile_mode'], kw['type']] # "cprogram cc" -+ -+ o = bld(features=kw['features'], source=test_f_name, target='testprog') -+ -+ for k, v in kw.iteritems(): -+ setattr(o, k, v) -+ -+ self.log.write("==>\n%s\n<==\n" % kw['code']) -+ -+ # compile the program -+ try: -+ bld.compile() -+ except Utils.WafError: -+ ret = Utils.ex_stack() -+ else: -+ ret = 0 -+ -+ # chdir before returning -+ os.chdir(back) -+ -+ if ret: -+ self.log.write('command returned %r' % ret) -+ self.fatal(str(ret)) -+ -+ # if we need to run the program, try to get its result -+ # keep the name of the program to execute -+ if kw['execute']: -+ lastprog = o.link_task.outputs[0].abspath(env) -+ -+ args = Utils.to_list(kw.get('exec_args', [])) -+ proc = Utils.pproc.Popen([lastprog] + args, stdout=Utils.pproc.PIPE, stderr=Utils.pproc.PIPE) -+ (out, err) = proc.communicate() -+ w = self.log.write -+ w(str(out)) -+ w('\n') -+ w(str(err)) -+ w('\n') -+ w('returncode %r' % proc.returncode) -+ w('\n') -+ if proc.returncode: -+ self.fatal(Utils.ex_stack()) -+ ret = out -+ -+ return ret -+ -+@conf -+def check_cxx(self, *k, **kw): -+ kw['compiler'] = 'cxx' -+ return self.check(*k, **kw) -+ -+@conf -+def check_cc(self, *k, **kw): -+ kw['compiler'] = 'cc' -+ return self.check(*k, **kw) -+ -+@conf -+def define(self, define, value, quote=1): -+ """store a single define and its state into an internal list for later -+ writing to a config header file. Value can only be -+ a string or int; other types not supported. String -+ values will appear properly quoted in the generated -+ header file.""" -+ assert define and isinstance(define, str) -+ -+ # ordered_dict is for writing the configuration header in order -+ tbl = self.env[DEFINES] or Utils.ordered_dict() -+ -+ # the user forgot to tell if the value is quoted or not -+ if isinstance(value, str): -+ if quote: -+ tbl[define] = '"%s"' % repr('"'+value)[2:-1].replace('"', '\\"') -+ else: -+ tbl[define] = value -+ elif isinstance(value, int): -+ tbl[define] = value -+ else: -+ raise TypeError('define %r -> %r must be a string or an int' % (define, value)) -+ -+ # add later to make reconfiguring faster -+ self.env[DEFINES] = tbl -+ self.env[define] = value # <- not certain this is necessary -+ -+@conf -+def undefine(self, define): -+ """store a single define and its state into an internal list -+ for later writing to a config header file""" -+ assert define and isinstance(define, str) -+ -+ tbl = self.env[DEFINES] or Utils.ordered_dict() -+ -+ value = UNDEFINED -+ tbl[define] = value -+ -+ # add later to make reconfiguring faster -+ self.env[DEFINES] = tbl -+ self.env[define] = value -+ -+@conf -+def define_cond(self, name, value): -+ """Conditionally define a name. -+ Formally equivalent to: if value: define(name, 1) else: undefine(name)""" -+ if value: -+ self.define(name, 1) -+ else: -+ self.undefine(name) -+ -+@conf -+def is_defined(self, key): -+ defines = self.env[DEFINES] -+ if not defines: -+ return False -+ try: -+ value = defines[key] -+ except KeyError: -+ return False -+ else: -+ return value != UNDEFINED -+ -+@conf -+def get_define(self, define): -+ "get the value of a previously stored define" -+ try: return self.env[DEFINES][define] -+ except KeyError: return None -+ -+@conf -+def have_define(self, name): -+ "prefix the define with 'HAVE_' and make sure it has valid characters." -+ return self.__dict__.get('HAVE_PAT', 'HAVE_%s') % Utils.quote_define_name(name) -+ -+@conf -+def write_config_header(self, configfile='', env='', guard='', top=False): -+ "save the defines into a file" -+ if not configfile: configfile = WAF_CONFIG_H -+ waf_guard = guard or '_%s_WAF' % Utils.quote_define_name(configfile) -+ -+ # configfile -> absolute path -+ # there is a good reason to concatenate first and to split afterwards -+ if not env: env = self.env -+ if top: -+ diff = '' -+ else: -+ diff = Utils.diff_path(self.srcdir, self.curdir) -+ full = os.sep.join([self.blddir, env.variant(), diff, configfile]) -+ full = os.path.normpath(full) -+ (dir, base) = os.path.split(full) -+ -+ try: os.makedirs(dir) -+ except: pass -+ -+ dest = open(full, 'w') -+ dest.write('/* Configuration header created by Waf - do not edit */\n') -+ dest.write('#ifndef %s\n#define %s\n\n' % (waf_guard, waf_guard)) -+ -+ dest.write(self.get_config_header()) -+ -+ # config files are not removed on "waf clean" -+ env.append_unique(CFG_FILES, os.path.join(diff, configfile)) -+ -+ dest.write('\n#endif /* %s */\n' % waf_guard) -+ dest.close() -+ -+@conf -+def get_config_header(self): -+ """Fill-in the contents of the config header. Override when you need to write your own config header.""" -+ config_header = [] -+ -+ tbl = self.env[DEFINES] or Utils.ordered_dict() -+ for key in tbl.allkeys: -+ value = tbl[key] -+ if value is None: -+ config_header.append('#define %s' % key) -+ elif value is UNDEFINED: -+ config_header.append('/* #undef %s */' % key) -+ else: -+ config_header.append('#define %s %s' % (key, value)) -+ return "\n".join(config_header) -+ -+@conftest -+def find_cpp(conf): -+ v = conf.env -+ cpp = [] -+ if v['CPP']: cpp = v['CPP'] -+ elif 'CPP' in conf.environ: cpp = conf.environ['CPP'] -+ if not cpp: cpp = conf.find_program('cpp', var='CPP') -+ #if not cpp: cpp = v['CC'] -+ #if not cpp: cpp = v['CXX'] -+ v['CPP'] = cpp -+ -+@conftest -+def cc_add_flags(conf): -+ conf.add_os_flags('CFLAGS', 'CCFLAGS') -+ conf.add_os_flags('CPPFLAGS') -+ -+@conftest -+def cxx_add_flags(conf): -+ conf.add_os_flags('CXXFLAGS') -+ conf.add_os_flags('CPPFLAGS') -+ -+@conftest -+def link_add_flags(conf): -+ conf.add_os_flags('LINKFLAGS') -+ conf.add_os_flags('LDFLAGS', 'LINKFLAGS') -+ -+@conftest -+def cc_load_tools(conf): -+ conf.check_tool('cc') -+ -+@conftest -+def cxx_load_tools(conf): -+ conf.check_tool('cxx') -+ -diff --git a/buildtools/wafadmin/Tools/cs.py b/buildtools/wafadmin/Tools/cs.py -new file mode 100644 -index 0000000..4354485 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/cs.py -@@ -0,0 +1,68 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006 (ita) -+ -+"C# support" -+ -+import TaskGen, Utils, Task, Options -+from Logs import error -+from TaskGen import before, after, taskgen, feature -+ -+flag_vars= ['FLAGS', 'ASSEMBLIES'] -+ -+@feature('cs') -+def init_cs(self): -+ Utils.def_attrs(self, -+ flags = '', -+ assemblies = '', -+ resources = '', -+ uselib = '') -+ -+@feature('cs') -+@after('init_cs') -+def apply_uselib_cs(self): -+ if not self.uselib: -+ return -+ global flag_vars -+ for var in self.to_list(self.uselib): -+ for v in self.flag_vars: -+ val = self.env[v+'_'+var] -+ if val: self.env.append_value(v, val) -+ -+@feature('cs') -+@after('apply_uselib_cs') -+@before('apply_core') -+def apply_cs(self): -+ try: self.meths.remove('apply_core') -+ except ValueError: pass -+ -+ # process the flags for the assemblies -+ for i in self.to_list(self.assemblies) + self.env['ASSEMBLIES']: -+ self.env.append_unique('_ASSEMBLIES', '/r:'+i) -+ -+ # process the flags for the resources -+ for i in self.to_list(self.resources): -+ self.env.append_unique('_RESOURCES', '/resource:'+i) -+ -+ # what kind of assembly are we generating? -+ self.env['_TYPE'] = getattr(self, 'type', 'exe') -+ -+ # additional flags -+ self.env.append_unique('_FLAGS', self.to_list(self.flags)) -+ self.env.append_unique('_FLAGS', self.env.FLAGS) -+ -+ # process the sources -+ nodes = [self.path.find_resource(i) for i in self.to_list(self.source)] -+ self.create_task('mcs', nodes, self.path.find_or_declare(self.target)) -+ -+Task.simple_task_type('mcs', '${MCS} ${SRC} /target:${_TYPE} /out:${TGT} ${_FLAGS} ${_ASSEMBLIES} ${_RESOURCES}', color='YELLOW') -+ -+def detect(conf): -+ csc = getattr(Options.options, 'cscbinary', None) -+ if csc: -+ conf.env.MCS = csc -+ conf.find_program(['gmcs', 'mcs'], var='MCS') -+ -+def set_options(opt): -+ opt.add_option('--with-csc-binary', type='string', dest='cscbinary') -+ -diff --git a/buildtools/wafadmin/Tools/cxx.py b/buildtools/wafadmin/Tools/cxx.py -new file mode 100644 -index 0000000..719b821 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/cxx.py -@@ -0,0 +1,104 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2005 (ita) -+ -+"Base for c++ programs and libraries" -+ -+import TaskGen, Task, Utils -+from Logs import debug -+import ccroot # <- do not remove -+from TaskGen import feature, before, extension, after -+ -+g_cxx_flag_vars = [ -+'CXXDEPS', 'FRAMEWORK', 'FRAMEWORKPATH', -+'STATICLIB', 'LIB', 'LIBPATH', 'LINKFLAGS', 'RPATH', -+'CXXFLAGS', 'CCFLAGS', 'CPPPATH', 'CPPFLAGS', 'CXXDEFINES'] -+"main cpp variables" -+ -+EXT_CXX = ['.cpp', '.cc', '.cxx', '.C', '.c++'] -+ -+g_cxx_type_vars=['CXXFLAGS', 'LINKFLAGS'] -+ -+# TODO remove in waf 1.6 -+class cxx_taskgen(ccroot.ccroot_abstract): -+ pass -+ -+@feature('cxx') -+@before('apply_type_vars') -+@after('default_cc') -+def init_cxx(self): -+ if not 'cc' in self.features: -+ self.mappings['.c'] = TaskGen.task_gen.mappings['.cxx'] -+ -+ self.p_flag_vars = set(self.p_flag_vars).union(g_cxx_flag_vars) -+ self.p_type_vars = set(self.p_type_vars).union(g_cxx_type_vars) -+ -+ if not self.env['CXX_NAME']: -+ raise Utils.WafError("At least one compiler (g++, ..) must be selected") -+ -+@feature('cxx') -+@after('apply_incpaths') -+def apply_obj_vars_cxx(self): -+ """after apply_incpaths for INC_PATHS""" -+ env = self.env -+ app = env.append_unique -+ cxxpath_st = env['CPPPATH_ST'] -+ -+ # local flags come first -+ # set the user-defined includes paths -+ for i in env['INC_PATHS']: -+ app('_CXXINCFLAGS', cxxpath_st % i.bldpath(env)) -+ app('_CXXINCFLAGS', cxxpath_st % i.srcpath(env)) -+ -+ # set the library include paths -+ for i in env['CPPPATH']: -+ app('_CXXINCFLAGS', cxxpath_st % i) -+ -+@feature('cxx') -+@after('apply_lib_vars') -+def apply_defines_cxx(self): -+ """after uselib is set for CXXDEFINES""" -+ self.defines = getattr(self, 'defines', []) -+ lst = self.to_list(self.defines) + self.to_list(self.env['CXXDEFINES']) -+ milst = [] -+ -+ # now process the local defines -+ for defi in lst: -+ if not defi in milst: -+ milst.append(defi) -+ -+ # CXXDEFINES_USELIB -+ libs = self.to_list(self.uselib) -+ for l in libs: -+ val = self.env['CXXDEFINES_'+l] -+ if val: milst += self.to_list(val) -+ -+ self.env['DEFLINES'] = ["%s %s" % (x[0], Utils.trimquotes('='.join(x[1:]))) for x in [y.split('=') for y in milst]] -+ y = self.env['CXXDEFINES_ST'] -+ self.env.append_unique('_CXXDEFFLAGS', [y%x for x in milst]) -+ -+@extension(EXT_CXX) -+def cxx_hook(self, node): -+ # create the compilation task: cpp or cc -+ if getattr(self, 'obj_ext', None): -+ obj_ext = self.obj_ext -+ else: -+ obj_ext = '_%d.o' % self.idx -+ -+ task = self.create_task('cxx', node, node.change_ext(obj_ext)) -+ try: -+ self.compiled_tasks.append(task) -+ except AttributeError: -+ raise Utils.WafError('Have you forgotten to set the feature "cxx" on %s?' % str(self)) -+ return task -+ -+cxx_str = '${CXX} ${CXXFLAGS} ${CPPFLAGS} ${_CXXINCFLAGS} ${_CXXDEFFLAGS} ${CXX_SRC_F}${SRC} ${CXX_TGT_F}${TGT}' -+cls = Task.simple_task_type('cxx', cxx_str, color='GREEN', ext_out='.o', ext_in='.cxx', shell=False) -+cls.scan = ccroot.scan -+cls.vars.append('CXXDEPS') -+ -+link_str = '${LINK_CXX} ${CXXLNK_SRC_F}${SRC} ${CXXLNK_TGT_F}${TGT[0].abspath(env)} ${LINKFLAGS}' -+cls = Task.simple_task_type('cxx_link', link_str, color='YELLOW', ext_in='.o', ext_out='.bin', shell=False) -+cls.maxjobs = 1 -+cls.install = Utils.nada -+ -diff --git a/buildtools/wafadmin/Tools/d.py b/buildtools/wafadmin/Tools/d.py -new file mode 100644 -index 0000000..1a22821 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/d.py -@@ -0,0 +1,535 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Carlos Rafael Giani, 2007 (dv) -+# Thomas Nagy, 2007-2008 (ita) -+ -+import os, sys, re, optparse -+import ccroot # <- leave this -+import TaskGen, Utils, Task, Configure, Logs, Build -+from Logs import debug, error -+from TaskGen import taskgen, feature, after, before, extension -+from Configure import conftest -+ -+EXT_D = ['.d', '.di', '.D'] -+D_METHS = ['apply_core', 'apply_vnum', 'apply_objdeps'] # additional d methods -+ -+DLIB = """ -+version(D_Version2) { -+ import std.stdio; -+ int main() { -+ writefln("phobos2"); -+ return 0; -+ } -+} else { -+ version(Tango) { -+ import tango.stdc.stdio; -+ int main() { -+ printf("tango"); -+ return 0; -+ } -+ } else { -+ import std.stdio; -+ int main() { -+ writefln("phobos1"); -+ return 0; -+ } -+ } -+} -+""" -+ -+def filter_comments(filename): -+ txt = Utils.readf(filename) -+ i = 0 -+ buf = [] -+ max = len(txt) -+ begin = 0 -+ while i < max: -+ c = txt[i] -+ if c == '"' or c == "'": # skip a string or character literal -+ buf.append(txt[begin:i]) -+ delim = c -+ i += 1 -+ while i < max: -+ c = txt[i] -+ if c == delim: break -+ elif c == '\\': # skip the character following backslash -+ i += 1 -+ i += 1 -+ i += 1 -+ begin = i -+ elif c == '/': # try to replace a comment with whitespace -+ buf.append(txt[begin:i]) -+ i += 1 -+ if i == max: break -+ c = txt[i] -+ if c == '+': # eat nesting /+ +/ comment -+ i += 1 -+ nesting = 1 -+ c = None -+ while i < max: -+ prev = c -+ c = txt[i] -+ if prev == '/' and c == '+': -+ nesting += 1 -+ c = None -+ elif prev == '+' and c == '/': -+ nesting -= 1 -+ if nesting == 0: break -+ c = None -+ i += 1 -+ elif c == '*': # eat /* */ comment -+ i += 1 -+ c = None -+ while i < max: -+ prev = c -+ c = txt[i] -+ if prev == '*' and c == '/': break -+ i += 1 -+ elif c == '/': # eat // comment -+ i += 1 -+ while i < max and txt[i] != '\n': -+ i += 1 -+ else: # no comment -+ begin = i - 1 -+ continue -+ i += 1 -+ begin = i -+ buf.append(' ') -+ else: -+ i += 1 -+ buf.append(txt[begin:]) -+ return buf -+ -+class d_parser(object): -+ def __init__(self, env, incpaths): -+ #self.code = '' -+ #self.module = '' -+ #self.imports = [] -+ -+ self.allnames = [] -+ -+ self.re_module = re.compile("module\s+([^;]+)") -+ self.re_import = re.compile("import\s+([^;]+)") -+ self.re_import_bindings = re.compile("([^:]+):(.*)") -+ self.re_import_alias = re.compile("[^=]+=(.+)") -+ -+ self.env = env -+ -+ self.nodes = [] -+ self.names = [] -+ -+ self.incpaths = incpaths -+ -+ def tryfind(self, filename): -+ found = 0 -+ for n in self.incpaths: -+ found = n.find_resource(filename.replace('.', '/') + '.d') -+ if found: -+ self.nodes.append(found) -+ self.waiting.append(found) -+ break -+ if not found: -+ if not filename in self.names: -+ self.names.append(filename) -+ -+ def get_strings(self, code): -+ #self.imports = [] -+ self.module = '' -+ lst = [] -+ -+ # get the module name (if present) -+ -+ mod_name = self.re_module.search(code) -+ if mod_name: -+ self.module = re.sub('\s+', '', mod_name.group(1)) # strip all whitespaces -+ -+ # go through the code, have a look at all import occurrences -+ -+ # first, lets look at anything beginning with "import" and ending with ";" -+ import_iterator = self.re_import.finditer(code) -+ if import_iterator: -+ for import_match in import_iterator: -+ import_match_str = re.sub('\s+', '', import_match.group(1)) # strip all whitespaces -+ -+ # does this end with an import bindings declaration? -+ # (import bindings always terminate the list of imports) -+ bindings_match = self.re_import_bindings.match(import_match_str) -+ if bindings_match: -+ import_match_str = bindings_match.group(1) -+ # if so, extract the part before the ":" (since the module declaration(s) is/are located there) -+ -+ # split the matching string into a bunch of strings, separated by a comma -+ matches = import_match_str.split(',') -+ -+ for match in matches: -+ alias_match = self.re_import_alias.match(match) -+ if alias_match: -+ # is this an alias declaration? (alias = module name) if so, extract the module name -+ match = alias_match.group(1) -+ -+ lst.append(match) -+ return lst -+ -+ def start(self, node): -+ self.waiting = [node] -+ # while the stack is not empty, add the dependencies -+ while self.waiting: -+ nd = self.waiting.pop(0) -+ self.iter(nd) -+ -+ def iter(self, node): -+ path = node.abspath(self.env) # obtain the absolute path -+ code = "".join(filter_comments(path)) # read the file and filter the comments -+ names = self.get_strings(code) # obtain the import strings -+ for x in names: -+ # optimization -+ if x in self.allnames: continue -+ self.allnames.append(x) -+ -+ # for each name, see if it is like a node or not -+ self.tryfind(x) -+ -+def scan(self): -+ "look for .d/.di the .d source need" -+ env = self.env -+ gruik = d_parser(env, env['INC_PATHS']) -+ gruik.start(self.inputs[0]) -+ -+ if Logs.verbose: -+ debug('deps: nodes found for %s: %s %s' % (str(self.inputs[0]), str(gruik.nodes), str(gruik.names))) -+ #debug("deps found for %s: %s" % (str(node), str(gruik.deps)), 'deps') -+ return (gruik.nodes, gruik.names) -+ -+def get_target_name(self): -+ "for d programs and libs" -+ v = self.env -+ tp = 'program' -+ for x in self.features: -+ if x in ['dshlib', 'dstaticlib']: -+ tp = x.lstrip('d') -+ return v['D_%s_PATTERN' % tp] % self.target -+ -+d_params = { -+'dflags': '', -+'importpaths':'', -+'libs':'', -+'libpaths':'', -+'generate_headers':False, -+} -+ -+@feature('d') -+@before('apply_type_vars') -+def init_d(self): -+ for x in d_params: -+ setattr(self, x, getattr(self, x, d_params[x])) -+ -+class d_taskgen(TaskGen.task_gen): -+ def __init__(self, *k, **kw): -+ TaskGen.task_gen.__init__(self, *k, **kw) -+ -+ # COMPAT -+ if len(k) > 1: -+ self.features.append('d' + k[1]) -+ -+# okay, we borrow a few methods from ccroot -+TaskGen.bind_feature('d', D_METHS) -+ -+@feature('d') -+@before('apply_d_libs') -+def init_d(self): -+ Utils.def_attrs(self, -+ dflags='', -+ importpaths='', -+ libs='', -+ libpaths='', -+ uselib='', -+ uselib_local='', -+ generate_headers=False, # set to true if you want .di files as well as .o -+ compiled_tasks=[], -+ add_objects=[], -+ link_task=None) -+ -+@feature('d') -+@after('apply_d_link', 'init_d') -+@before('apply_vnum', 'apply_d_vars') -+def apply_d_libs(self): -+ """after apply_link because of 'link_task' -+ after default_cc because of the attribute 'uselib'""" -+ env = self.env -+ -+ # 1. the case of the libs defined in the project (visit ancestors first) -+ # the ancestors external libraries (uselib) will be prepended -+ self.uselib = self.to_list(self.uselib) -+ names = self.to_list(self.uselib_local) -+ -+ seen = set([]) -+ tmp = Utils.deque(names) # consume a copy of the list of names -+ while tmp: -+ lib_name = tmp.popleft() -+ # visit dependencies only once -+ if lib_name in seen: -+ continue -+ -+ y = self.name_to_obj(lib_name) -+ if not y: -+ raise Utils.WafError('object %r was not found in uselib_local (required by %r)' % (lib_name, self.name)) -+ y.post() -+ seen.add(lib_name) -+ -+ # object has ancestors to process (shared libraries): add them to the end of the list -+ if getattr(y, 'uselib_local', None): -+ lst = y.to_list(y.uselib_local) -+ if 'dshlib' in y.features or 'dprogram' in y.features: -+ lst = [x for x in lst if not 'dstaticlib' in self.name_to_obj(x).features] -+ tmp.extend(lst) -+ -+ # link task and flags -+ if getattr(y, 'link_task', None): -+ -+ link_name = y.target[y.target.rfind(os.sep) + 1:] -+ if 'dstaticlib' in y.features or 'dshlib' in y.features: -+ env.append_unique('DLINKFLAGS', env.DLIB_ST % link_name) -+ env.append_unique('DLINKFLAGS', env.DLIBPATH_ST % y.link_task.outputs[0].parent.bldpath(env)) -+ -+ # the order -+ self.link_task.set_run_after(y.link_task) -+ -+ # for the recompilation -+ dep_nodes = getattr(self.link_task, 'dep_nodes', []) -+ self.link_task.dep_nodes = dep_nodes + y.link_task.outputs -+ -+ # add ancestors uselib too - but only propagate those that have no staticlib -+ for v in self.to_list(y.uselib): -+ if not v in self.uselib: -+ self.uselib.insert(0, v) -+ -+ # if the library task generator provides 'export_incdirs', add to the include path -+ # the export_incdirs must be a list of paths relative to the other library -+ if getattr(y, 'export_incdirs', None): -+ for x in self.to_list(y.export_incdirs): -+ node = y.path.find_dir(x) -+ if not node: -+ raise Utils.WafError('object %r: invalid folder %r in export_incdirs' % (y.target, x)) -+ self.env.append_unique('INC_PATHS', node) -+ -+@feature('dprogram', 'dshlib', 'dstaticlib') -+@after('apply_core') -+def apply_d_link(self): -+ link = getattr(self, 'link', None) -+ if not link: -+ if 'dstaticlib' in self.features: link = 'static_link' -+ else: link = 'd_link' -+ -+ outputs = [t.outputs[0] for t in self.compiled_tasks] -+ self.link_task = self.create_task(link, outputs, self.path.find_or_declare(get_target_name(self))) -+ -+@feature('d') -+@after('apply_core') -+def apply_d_vars(self): -+ env = self.env -+ dpath_st = env['DPATH_ST'] -+ lib_st = env['DLIB_ST'] -+ libpath_st = env['DLIBPATH_ST'] -+ -+ importpaths = self.to_list(self.importpaths) -+ libpaths = [] -+ libs = [] -+ uselib = self.to_list(self.uselib) -+ -+ for i in uselib: -+ if env['DFLAGS_' + i]: -+ env.append_unique('DFLAGS', env['DFLAGS_' + i]) -+ -+ for x in self.features: -+ if not x in ['dprogram', 'dstaticlib', 'dshlib']: -+ continue -+ x.lstrip('d') -+ d_shlib_dflags = env['D_' + x + '_DFLAGS'] -+ if d_shlib_dflags: -+ env.append_unique('DFLAGS', d_shlib_dflags) -+ -+ # add import paths -+ for i in uselib: -+ if env['DPATH_' + i]: -+ for entry in self.to_list(env['DPATH_' + i]): -+ if not entry in importpaths: -+ importpaths.append(entry) -+ -+ # now process the import paths -+ for path in importpaths: -+ if os.path.isabs(path): -+ env.append_unique('_DIMPORTFLAGS', dpath_st % path) -+ else: -+ node = self.path.find_dir(path) -+ self.env.append_unique('INC_PATHS', node) -+ env.append_unique('_DIMPORTFLAGS', dpath_st % node.srcpath(env)) -+ env.append_unique('_DIMPORTFLAGS', dpath_st % node.bldpath(env)) -+ -+ # add library paths -+ for i in uselib: -+ if env['LIBPATH_' + i]: -+ for entry in self.to_list(env['LIBPATH_' + i]): -+ if not entry in libpaths: -+ libpaths.append(entry) -+ libpaths = self.to_list(self.libpaths) + libpaths -+ -+ # now process the library paths -+ # apply same path manipulation as used with import paths -+ for path in libpaths: -+ if not os.path.isabs(path): -+ node = self.path.find_resource(path) -+ if not node: -+ raise Utils.WafError('could not find libpath %r from %r' % (path, self)) -+ path = node.abspath(self.env) -+ -+ env.append_unique('DLINKFLAGS', libpath_st % path) -+ -+ # add libraries -+ for i in uselib: -+ if env['LIB_' + i]: -+ for entry in self.to_list(env['LIB_' + i]): -+ if not entry in libs: -+ libs.append(entry) -+ libs.extend(self.to_list(self.libs)) -+ -+ # process user flags -+ for flag in self.to_list(self.dflags): -+ env.append_unique('DFLAGS', flag) -+ -+ # now process the libraries -+ for lib in libs: -+ env.append_unique('DLINKFLAGS', lib_st % lib) -+ -+ # add linker flags -+ for i in uselib: -+ dlinkflags = env['DLINKFLAGS_' + i] -+ if dlinkflags: -+ for linkflag in dlinkflags: -+ env.append_unique('DLINKFLAGS', linkflag) -+ -+@feature('dshlib') -+@after('apply_d_vars') -+def add_shlib_d_flags(self): -+ for linkflag in self.env['D_shlib_LINKFLAGS']: -+ self.env.append_unique('DLINKFLAGS', linkflag) -+ -+@extension(EXT_D) -+def d_hook(self, node): -+ # create the compilation task: cpp or cc -+ task = self.create_task(self.generate_headers and 'd_with_header' or 'd') -+ try: obj_ext = self.obj_ext -+ except AttributeError: obj_ext = '_%d.o' % self.idx -+ -+ task.inputs = [node] -+ task.outputs = [node.change_ext(obj_ext)] -+ self.compiled_tasks.append(task) -+ -+ if self.generate_headers: -+ header_node = node.change_ext(self.env['DHEADER_ext']) -+ task.outputs += [header_node] -+ -+d_str = '${D_COMPILER} ${DFLAGS} ${_DIMPORTFLAGS} ${D_SRC_F}${SRC} ${D_TGT_F}${TGT}' -+d_with_header_str = '${D_COMPILER} ${DFLAGS} ${_DIMPORTFLAGS} \ -+${D_HDR_F}${TGT[1].bldpath(env)} \ -+${D_SRC_F}${SRC} \ -+${D_TGT_F}${TGT[0].bldpath(env)}' -+link_str = '${D_LINKER} ${DLNK_SRC_F}${SRC} ${DLNK_TGT_F}${TGT} ${DLINKFLAGS}' -+ -+def override_exec(cls): -+ """stupid dmd wants -of stuck to the file name""" -+ old_exec = cls.exec_command -+ def exec_command(self, *k, **kw): -+ if isinstance(k[0], list): -+ lst = k[0] -+ for i in xrange(len(lst)): -+ if lst[i] == '-of': -+ del lst[i] -+ lst[i] = '-of' + lst[i] -+ break -+ return old_exec(self, *k, **kw) -+ cls.exec_command = exec_command -+ -+cls = Task.simple_task_type('d', d_str, 'GREEN', before='static_link d_link', shell=False) -+cls.scan = scan -+override_exec(cls) -+ -+cls = Task.simple_task_type('d_with_header', d_with_header_str, 'GREEN', before='static_link d_link', shell=False) -+override_exec(cls) -+ -+cls = Task.simple_task_type('d_link', link_str, color='YELLOW', shell=False) -+override_exec(cls) -+ -+# for feature request #104 -+@taskgen -+def generate_header(self, filename, install_path): -+ if not hasattr(self, 'header_lst'): self.header_lst = [] -+ self.meths.append('process_header') -+ self.header_lst.append([filename, install_path]) -+ -+@before('apply_core') -+def process_header(self): -+ env = self.env -+ for i in getattr(self, 'header_lst', []): -+ node = self.path.find_resource(i[0]) -+ -+ if not node: -+ raise Utils.WafError('file not found on d obj '+i[0]) -+ -+ task = self.create_task('d_header') -+ task.set_inputs(node) -+ task.set_outputs(node.change_ext('.di')) -+ -+d_header_str = '${D_COMPILER} ${D_HEADER} ${SRC}' -+Task.simple_task_type('d_header', d_header_str, color='BLUE', shell=False) -+ -+@conftest -+def d_platform_flags(conf): -+ v = conf.env -+ binfmt = v.DEST_BINFMT or Utils.unversioned_sys_platform_to_binary_format( -+ v.DEST_OS or Utils.unversioned_sys_platform()) -+ if binfmt == 'pe': -+ v['D_program_PATTERN'] = '%s.exe' -+ v['D_shlib_PATTERN'] = 'lib%s.dll' -+ v['D_staticlib_PATTERN'] = 'lib%s.a' -+ else: -+ v['D_program_PATTERN'] = '%s' -+ v['D_shlib_PATTERN'] = 'lib%s.so' -+ v['D_staticlib_PATTERN'] = 'lib%s.a' -+ -+@conftest -+def check_dlibrary(conf): -+ ret = conf.check_cc(features='d dprogram', fragment=DLIB, mandatory=True, compile_filename='test.d', execute=True) -+ conf.env.DLIBRARY = ret.strip() -+ -+# quick test # -+if __name__ == "__main__": -+ #Logs.verbose = 2 -+ -+ try: arg = sys.argv[1] -+ except IndexError: arg = "file.d" -+ -+ print("".join(filter_comments(arg))) -+ # TODO -+ paths = ['.'] -+ -+ #gruik = filter() -+ #gruik.start(arg) -+ -+ #code = "".join(gruik.buf) -+ -+ #print "we have found the following code" -+ #print code -+ -+ #print "now parsing" -+ #print "-------------------------------------------" -+ """ -+ parser_ = d_parser() -+ parser_.start(arg) -+ -+ print "module: %s" % parser_.module -+ print "imports: ", -+ for imp in parser_.imports: -+ print imp + " ", -+ print -+""" -+ -diff --git a/buildtools/wafadmin/Tools/dbus.py b/buildtools/wafadmin/Tools/dbus.py -new file mode 100644 -index 0000000..3179999 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/dbus.py -@@ -0,0 +1,34 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Ali Sabil, 2007 -+ -+import Task, Utils -+from TaskGen import taskgen, before, after, feature -+ -+@taskgen -+def add_dbus_file(self, filename, prefix, mode): -+ if not hasattr(self, 'dbus_lst'): -+ self.dbus_lst = [] -+ self.meths.append('process_dbus') -+ self.dbus_lst.append([filename, prefix, mode]) -+ -+@before('apply_core') -+def process_dbus(self): -+ for filename, prefix, mode in getattr(self, 'dbus_lst', []): -+ node = self.path.find_resource(filename) -+ -+ if not node: -+ raise Utils.WafError('file not found ' + filename) -+ -+ tsk = self.create_task('dbus_binding_tool', node, node.change_ext('.h')) -+ -+ tsk.env.DBUS_BINDING_TOOL_PREFIX = prefix -+ tsk.env.DBUS_BINDING_TOOL_MODE = mode -+ -+Task.simple_task_type('dbus_binding_tool', -+ '${DBUS_BINDING_TOOL} --prefix=${DBUS_BINDING_TOOL_PREFIX} --mode=${DBUS_BINDING_TOOL_MODE} --output=${TGT} ${SRC}', -+ color='BLUE', before='cc') -+ -+def detect(conf): -+ dbus_binding_tool = conf.find_program('dbus-binding-tool', var='DBUS_BINDING_TOOL') -+ -diff --git a/buildtools/wafadmin/Tools/dmd.py b/buildtools/wafadmin/Tools/dmd.py -new file mode 100644 -index 0000000..9c74908 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/dmd.py -@@ -0,0 +1,64 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Carlos Rafael Giani, 2007 (dv) -+# Thomas Nagy, 2008 (ita) -+ -+import sys -+import Utils, ar -+from Configure import conftest -+ -+@conftest -+def find_dmd(conf): -+ conf.find_program(['dmd', 'ldc'], var='D_COMPILER', mandatory=True) -+ -+@conftest -+def common_flags_ldc(conf): -+ v = conf.env -+ v['DFLAGS'] = ['-d-version=Posix'] -+ v['DLINKFLAGS'] = [] -+ v['D_shlib_DFLAGS'] = ['-relocation-model=pic'] -+ -+@conftest -+def common_flags_dmd(conf): -+ v = conf.env -+ -+ # _DFLAGS _DIMPORTFLAGS -+ -+ # Compiler is dmd so 'gdc' part will be ignored, just -+ # ensure key is there, so wscript can append flags to it -+ v['DFLAGS'] = ['-version=Posix'] -+ -+ v['D_SRC_F'] = '' -+ v['D_TGT_F'] = ['-c', '-of'] -+ v['DPATH_ST'] = '-I%s' # template for adding import paths -+ -+ # linker -+ v['D_LINKER'] = v['D_COMPILER'] -+ v['DLNK_SRC_F'] = '' -+ v['DLNK_TGT_F'] = '-of' -+ -+ v['DLIB_ST'] = '-L-l%s' # template for adding libs -+ v['DLIBPATH_ST'] = '-L-L%s' # template for adding libpaths -+ -+ # linker debug levels -+ v['DFLAGS_OPTIMIZED'] = ['-O'] -+ v['DFLAGS_DEBUG'] = ['-g', '-debug'] -+ v['DFLAGS_ULTRADEBUG'] = ['-g', '-debug'] -+ v['DLINKFLAGS'] = ['-quiet'] -+ -+ v['D_shlib_DFLAGS'] = ['-fPIC'] -+ v['D_shlib_LINKFLAGS'] = ['-L-shared'] -+ -+ v['DHEADER_ext'] = '.di' -+ v['D_HDR_F'] = ['-H', '-Hf'] -+ -+def detect(conf): -+ conf.find_dmd() -+ conf.check_tool('ar') -+ conf.check_tool('d') -+ conf.common_flags_dmd() -+ conf.d_platform_flags() -+ -+ if conf.env.D_COMPILER.find('ldc') > -1: -+ conf.common_flags_ldc() -+ -diff --git a/buildtools/wafadmin/Tools/flex.py b/buildtools/wafadmin/Tools/flex.py -new file mode 100644 -index 0000000..5ce9f22 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/flex.py -@@ -0,0 +1,25 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# John O'Meara, 2006 -+# Thomas Nagy, 2006-2008 -+ -+"Flex processing" -+ -+import TaskGen -+ -+def decide_ext(self, node): -+ if 'cxx' in self.features: return '.lex.cc' -+ else: return '.lex.c' -+ -+TaskGen.declare_chain( -+ name = 'flex', -+ rule = '${FLEX} -o${TGT} ${FLEXFLAGS} ${SRC}', -+ ext_in = '.l', -+ ext_out = '.c .cxx', -+ decider = decide_ext -+) -+ -+def detect(conf): -+ conf.find_program('flex', var='FLEX', mandatory=True) -+ conf.env['FLEXFLAGS'] = '' -+ -diff --git a/buildtools/wafadmin/Tools/gas.py b/buildtools/wafadmin/Tools/gas.py -new file mode 100644 -index 0000000..c983b0a ---- /dev/null -+++ b/buildtools/wafadmin/Tools/gas.py -@@ -0,0 +1,38 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2008 (ita) -+ -+"as and gas" -+ -+import os, sys -+import Task -+from TaskGen import extension, taskgen, after, before -+ -+EXT_ASM = ['.s', '.S', '.asm', '.ASM', '.spp', '.SPP'] -+ -+as_str = '${AS} ${ASFLAGS} ${_ASINCFLAGS} ${SRC} -o ${TGT}' -+Task.simple_task_type('asm', as_str, 'PINK', ext_out='.o', shell=False) -+ -+@extension(EXT_ASM) -+def asm_hook(self, node): -+ # create the compilation task: cpp or cc -+ try: obj_ext = self.obj_ext -+ except AttributeError: obj_ext = '_%d.o' % self.idx -+ -+ task = self.create_task('asm', node, node.change_ext(obj_ext)) -+ self.compiled_tasks.append(task) -+ self.meths.append('asm_incflags') -+ -+@after('apply_obj_vars_cc') -+@after('apply_obj_vars_cxx') -+@before('apply_link') -+def asm_incflags(self): -+ self.env.append_value('_ASINCFLAGS', self.env.ASINCFLAGS) -+ var = ('cxx' in self.features) and 'CXX' or 'CC' -+ self.env.append_value('_ASINCFLAGS', self.env['_%sINCFLAGS' % var]) -+ -+def detect(conf): -+ conf.find_program(['gas', 'as'], var='AS') -+ if not conf.env.AS: conf.env.AS = conf.env.CC -+ #conf.env.ASFLAGS = ['-c'] <- may be necesary for .S files -+ -diff --git a/buildtools/wafadmin/Tools/gcc.py b/buildtools/wafadmin/Tools/gcc.py -new file mode 100644 -index 0000000..420b44f ---- /dev/null -+++ b/buildtools/wafadmin/Tools/gcc.py -@@ -0,0 +1,135 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006-2008 (ita) -+# Ralf Habacker, 2006 (rh) -+# Yinon Ehrlich, 2009 -+ -+import os, sys -+import Configure, Options, Utils -+import ccroot, ar -+from Configure import conftest -+ -+@conftest -+def find_gcc(conf): -+ cc = conf.find_program(['gcc', 'cc'], var='CC', mandatory=True) -+ cc = conf.cmd_to_list(cc) -+ ccroot.get_cc_version(conf, cc, gcc=True) -+ conf.env.CC_NAME = 'gcc' -+ conf.env.CC = cc -+ -+@conftest -+def gcc_common_flags(conf): -+ v = conf.env -+ -+ # CPPFLAGS CCDEFINES _CCINCFLAGS _CCDEFFLAGS -+ -+ v['CCFLAGS_DEBUG'] = ['-g'] -+ -+ v['CCFLAGS_RELEASE'] = ['-O2'] -+ -+ v['CC_SRC_F'] = '' -+ v['CC_TGT_F'] = ['-c', '-o', ''] # shell hack for -MD -+ v['CPPPATH_ST'] = '-I%s' # template for adding include paths -+ -+ # linker -+ if not v['LINK_CC']: v['LINK_CC'] = v['CC'] -+ v['CCLNK_SRC_F'] = '' -+ v['CCLNK_TGT_F'] = ['-o', ''] # shell hack for -MD -+ -+ v['LIB_ST'] = '-l%s' # template for adding libs -+ v['LIBPATH_ST'] = '-L%s' # template for adding libpaths -+ v['STATICLIB_ST'] = '-l%s' -+ v['STATICLIBPATH_ST'] = '-L%s' -+ v['RPATH_ST'] = '-Wl,-rpath,%s' -+ v['CCDEFINES_ST'] = '-D%s' -+ -+ v['SONAME_ST'] = '-Wl,-h,%s' -+ v['SHLIB_MARKER'] = '-Wl,-Bdynamic' -+ v['STATICLIB_MARKER'] = '-Wl,-Bstatic' -+ v['FULLSTATIC_MARKER'] = '-static' -+ -+ # program -+ v['program_PATTERN'] = '%s' -+ -+ # shared library -+ v['shlib_CCFLAGS'] = ['-fPIC', '-DPIC'] # avoid using -DPIC, -fPIC aleady defines the __PIC__ macro -+ v['shlib_LINKFLAGS'] = ['-shared'] -+ v['shlib_PATTERN'] = 'lib%s.so' -+ -+ # static lib -+ v['staticlib_LINKFLAGS'] = ['-Wl,-Bstatic'] -+ v['staticlib_PATTERN'] = 'lib%s.a' -+ -+ # osx stuff -+ v['LINKFLAGS_MACBUNDLE'] = ['-bundle', '-undefined', 'dynamic_lookup'] -+ v['CCFLAGS_MACBUNDLE'] = ['-fPIC'] -+ v['macbundle_PATTERN'] = '%s.bundle' -+ -+@conftest -+def gcc_modifier_win32(conf): -+ v = conf.env -+ v['program_PATTERN'] = '%s.exe' -+ -+ v['shlib_PATTERN'] = '%s.dll' -+ v['implib_PATTERN'] = 'lib%s.dll.a' -+ v['IMPLIB_ST'] = '-Wl,--out-implib,%s' -+ -+ dest_arch = v['DEST_CPU'] -+ v['shlib_CCFLAGS'] = ['-DPIC'] -+ -+ v.append_value('shlib_CCFLAGS', '-DDLL_EXPORT') # TODO adding nonstandard defines like this DLL_EXPORT is not a good idea -+ -+ # Auto-import is enabled by default even without this option, -+ # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages -+ # that the linker emits otherwise. -+ v.append_value('LINKFLAGS', '-Wl,--enable-auto-import') -+ -+@conftest -+def gcc_modifier_cygwin(conf): -+ gcc_modifier_win32(conf) -+ v = conf.env -+ v['shlib_PATTERN'] = 'cyg%s.dll' -+ v.append_value('shlib_LINKFLAGS', '-Wl,--enable-auto-image-base') -+ -+@conftest -+def gcc_modifier_darwin(conf): -+ v = conf.env -+ v['shlib_CCFLAGS'] = ['-fPIC', '-compatibility_version', '1', '-current_version', '1'] -+ v['shlib_LINKFLAGS'] = ['-dynamiclib'] -+ v['shlib_PATTERN'] = 'lib%s.dylib' -+ -+ v['staticlib_LINKFLAGS'] = [] -+ -+ v['SHLIB_MARKER'] = '' -+ v['STATICLIB_MARKER'] = '' -+ v['SONAME_ST'] = '' -+ -+@conftest -+def gcc_modifier_aix(conf): -+ v = conf.env -+ v['program_LINKFLAGS'] = ['-Wl,-brtl'] -+ -+ v['shlib_LINKFLAGS'] = ['-shared','-Wl,-brtl,-bexpfull'] -+ -+ v['SHLIB_MARKER'] = '' -+ -+@conftest -+def gcc_modifier_platform(conf): -+ # * set configurations specific for a platform. -+ # * the destination platform is detected automatically by looking at the macros the compiler predefines, -+ # and if it's not recognised, it fallbacks to sys.platform. -+ dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() -+ gcc_modifier_func = globals().get('gcc_modifier_' + dest_os) -+ if gcc_modifier_func: -+ gcc_modifier_func(conf) -+ -+def detect(conf): -+ conf.find_gcc() -+ conf.find_cpp() -+ conf.find_ar() -+ conf.gcc_common_flags() -+ conf.gcc_modifier_platform() -+ conf.cc_load_tools() -+ conf.cc_add_flags() -+ conf.link_add_flags() -+ -diff --git a/buildtools/wafadmin/Tools/gdc.py b/buildtools/wafadmin/Tools/gdc.py -new file mode 100644 -index 0000000..4d2a321 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/gdc.py -@@ -0,0 +1,52 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Carlos Rafael Giani, 2007 (dv) -+ -+import sys -+import Utils, ar -+from Configure import conftest -+ -+@conftest -+def find_gdc(conf): -+ conf.find_program('gdc', var='D_COMPILER', mandatory=True) -+ -+@conftest -+def common_flags_gdc(conf): -+ v = conf.env -+ -+ # _DFLAGS _DIMPORTFLAGS -+ -+ # for mory info about the meaning of this dict see dmd.py -+ v['DFLAGS'] = [] -+ -+ v['D_SRC_F'] = '' -+ v['D_TGT_F'] = ['-c', '-o', ''] -+ v['DPATH_ST'] = '-I%s' # template for adding import paths -+ -+ # linker -+ v['D_LINKER'] = v['D_COMPILER'] -+ v['DLNK_SRC_F'] = '' -+ v['DLNK_TGT_F'] = ['-o', ''] -+ -+ v['DLIB_ST'] = '-l%s' # template for adding libs -+ v['DLIBPATH_ST'] = '-L%s' # template for adding libpaths -+ -+ # debug levels -+ v['DLINKFLAGS'] = [] -+ v['DFLAGS_OPTIMIZED'] = ['-O3'] -+ v['DFLAGS_DEBUG'] = ['-O0'] -+ v['DFLAGS_ULTRADEBUG'] = ['-O0'] -+ -+ v['D_shlib_DFLAGS'] = [] -+ v['D_shlib_LINKFLAGS'] = ['-shared'] -+ -+ v['DHEADER_ext'] = '.di' -+ v['D_HDR_F'] = '-fintfc -fintfc-file=' -+ -+def detect(conf): -+ conf.find_gdc() -+ conf.check_tool('ar') -+ conf.check_tool('d') -+ conf.common_flags_gdc() -+ conf.d_platform_flags() -+ -diff --git a/buildtools/wafadmin/Tools/glib2.py b/buildtools/wafadmin/Tools/glib2.py -new file mode 100644 -index 0000000..042d612 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/glib2.py -@@ -0,0 +1,164 @@ -+#! /usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006-2008 (ita) -+ -+"GLib2 support" -+ -+import Task, Utils -+from TaskGen import taskgen, before, after, feature -+ -+# -+# glib-genmarshal -+# -+ -+@taskgen -+def add_marshal_file(self, filename, prefix): -+ if not hasattr(self, 'marshal_list'): -+ self.marshal_list = [] -+ self.meths.append('process_marshal') -+ self.marshal_list.append((filename, prefix)) -+ -+@before('apply_core') -+def process_marshal(self): -+ for f, prefix in getattr(self, 'marshal_list', []): -+ node = self.path.find_resource(f) -+ -+ if not node: -+ raise Utils.WafError('file not found %r' % f) -+ -+ h_node = node.change_ext('.h') -+ c_node = node.change_ext('.c') -+ -+ task = self.create_task('glib_genmarshal', node, [h_node, c_node]) -+ task.env.GLIB_GENMARSHAL_PREFIX = prefix -+ self.allnodes.append(c_node) -+ -+def genmarshal_func(self): -+ -+ bld = self.inputs[0].__class__.bld -+ -+ get = self.env.get_flat -+ cmd1 = "%s %s --prefix=%s --header > %s" % ( -+ get('GLIB_GENMARSHAL'), -+ self.inputs[0].srcpath(self.env), -+ get('GLIB_GENMARSHAL_PREFIX'), -+ self.outputs[0].abspath(self.env) -+ ) -+ -+ ret = bld.exec_command(cmd1) -+ if ret: return ret -+ -+ #print self.outputs[1].abspath(self.env) -+ f = open(self.outputs[1].abspath(self.env), 'wb') -+ c = '''#include "%s"\n''' % self.outputs[0].name -+ f.write(c) -+ f.close() -+ -+ cmd2 = "%s %s --prefix=%s --body >> %s" % ( -+ get('GLIB_GENMARSHAL'), -+ self.inputs[0].srcpath(self.env), -+ get('GLIB_GENMARSHAL_PREFIX'), -+ self.outputs[1].abspath(self.env) -+ ) -+ ret = Utils.exec_command(cmd2) -+ if ret: return ret -+ -+# -+# glib-mkenums -+# -+ -+@taskgen -+def add_enums_from_template(self, source='', target='', template='', comments=''): -+ if not hasattr(self, 'enums_list'): -+ self.enums_list = [] -+ self.meths.append('process_enums') -+ self.enums_list.append({'source': source, -+ 'target': target, -+ 'template': template, -+ 'file-head': '', -+ 'file-prod': '', -+ 'file-tail': '', -+ 'enum-prod': '', -+ 'value-head': '', -+ 'value-prod': '', -+ 'value-tail': '', -+ 'comments': comments}) -+ -+@taskgen -+def add_enums(self, source='', target='', -+ file_head='', file_prod='', file_tail='', enum_prod='', -+ value_head='', value_prod='', value_tail='', comments=''): -+ if not hasattr(self, 'enums_list'): -+ self.enums_list = [] -+ self.meths.append('process_enums') -+ self.enums_list.append({'source': source, -+ 'template': '', -+ 'target': target, -+ 'file-head': file_head, -+ 'file-prod': file_prod, -+ 'file-tail': file_tail, -+ 'enum-prod': enum_prod, -+ 'value-head': value_head, -+ 'value-prod': value_prod, -+ 'value-tail': value_tail, -+ 'comments': comments}) -+ -+@before('apply_core') -+def process_enums(self): -+ for enum in getattr(self, 'enums_list', []): -+ task = self.create_task('glib_mkenums') -+ env = task.env -+ -+ inputs = [] -+ -+ # process the source -+ source_list = self.to_list(enum['source']) -+ if not source_list: -+ raise Utils.WafError('missing source ' + str(enum)) -+ source_list = [self.path.find_resource(k) for k in source_list] -+ inputs += source_list -+ env['GLIB_MKENUMS_SOURCE'] = [k.srcpath(env) for k in source_list] -+ -+ # find the target -+ if not enum['target']: -+ raise Utils.WafError('missing target ' + str(enum)) -+ tgt_node = self.path.find_or_declare(enum['target']) -+ if tgt_node.name.endswith('.c'): -+ self.allnodes.append(tgt_node) -+ env['GLIB_MKENUMS_TARGET'] = tgt_node.abspath(env) -+ -+ -+ options = [] -+ -+ if enum['template']: # template, if provided -+ template_node = self.path.find_resource(enum['template']) -+ options.append('--template %s' % (template_node.abspath(env))) -+ inputs.append(template_node) -+ params = {'file-head' : '--fhead', -+ 'file-prod' : '--fprod', -+ 'file-tail' : '--ftail', -+ 'enum-prod' : '--eprod', -+ 'value-head' : '--vhead', -+ 'value-prod' : '--vprod', -+ 'value-tail' : '--vtail', -+ 'comments': '--comments'} -+ for param, option in params.iteritems(): -+ if enum[param]: -+ options.append('%s %r' % (option, enum[param])) -+ -+ env['GLIB_MKENUMS_OPTIONS'] = ' '.join(options) -+ -+ # update the task instance -+ task.set_inputs(inputs) -+ task.set_outputs(tgt_node) -+ -+Task.task_type_from_func('glib_genmarshal', func=genmarshal_func, vars=['GLIB_GENMARSHAL_PREFIX', 'GLIB_GENMARSHAL'], -+ color='BLUE', before='cc cxx') -+Task.simple_task_type('glib_mkenums', -+ '${GLIB_MKENUMS} ${GLIB_MKENUMS_OPTIONS} ${GLIB_MKENUMS_SOURCE} > ${GLIB_MKENUMS_TARGET}', -+ color='PINK', before='cc cxx') -+ -+def detect(conf): -+ glib_genmarshal = conf.find_program('glib-genmarshal', var='GLIB_GENMARSHAL') -+ mk_enums_tool = conf.find_program('glib-mkenums', var='GLIB_MKENUMS') -+ -diff --git a/buildtools/wafadmin/Tools/gnome.py b/buildtools/wafadmin/Tools/gnome.py -new file mode 100644 -index 0000000..c098a41 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/gnome.py -@@ -0,0 +1,223 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006-2008 (ita) -+ -+"Gnome support" -+ -+import os, re -+import TaskGen, Utils, Runner, Task, Build, Options, Logs -+import cc -+from Logs import error -+from TaskGen import taskgen, before, after, feature -+ -+n1_regexp = re.compile('(.*)', re.M) -+n2_regexp = re.compile('(.*)', re.M) -+ -+def postinstall_schemas(prog_name): -+ if Build.bld.is_install: -+ dir = Build.bld.get_install_path('${PREFIX}/etc/gconf/schemas/%s.schemas' % prog_name) -+ if not Options.options.destdir: -+ # add the gconf schema -+ Utils.pprint('YELLOW', 'Installing GConf schema') -+ command = 'gconftool-2 --install-schema-file=%s 1> /dev/null' % dir -+ ret = Utils.exec_command(command) -+ else: -+ Utils.pprint('YELLOW', 'GConf schema not installed. After install, run this:') -+ Utils.pprint('YELLOW', 'gconftool-2 --install-schema-file=%s' % dir) -+ -+def postinstall_icons(): -+ dir = Build.bld.get_install_path('${DATADIR}/icons/hicolor') -+ if Build.bld.is_install: -+ if not Options.options.destdir: -+ # update the pixmap cache directory -+ Utils.pprint('YELLOW', "Updating Gtk icon cache.") -+ command = 'gtk-update-icon-cache -q -f -t %s' % dir -+ ret = Utils.exec_command(command) -+ else: -+ Utils.pprint('YELLOW', 'Icon cache not updated. After install, run this:') -+ Utils.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % dir) -+ -+def postinstall_scrollkeeper(prog_name): -+ if Build.bld.is_install: -+ # now the scrollkeeper update if we can write to the log file -+ if os.access('/var/log/scrollkeeper.log', os.W_OK): -+ dir1 = Build.bld.get_install_path('${PREFIX}/var/scrollkeeper') -+ dir2 = Build.bld.get_install_path('${DATADIR}/omf/%s' % prog_name) -+ command = 'scrollkeeper-update -q -p %s -o %s' % (dir1, dir2) -+ ret = Utils.exec_command(command) -+ -+def postinstall(prog_name='myapp', schemas=1, icons=1, scrollkeeper=1): -+ if schemas: postinstall_schemas(prog_name) -+ if icons: postinstall_icons() -+ if scrollkeeper: postinstall_scrollkeeper(prog_name) -+ -+# OBSOLETE -+class gnome_doc_taskgen(TaskGen.task_gen): -+ def __init__(self, *k, **kw): -+ TaskGen.task_gen.__init__(self, *k, **kw) -+ -+@feature('gnome_doc') -+def init_gnome_doc(self): -+ self.default_install_path = '${PREFIX}/share' -+ -+@feature('gnome_doc') -+@after('init_gnome_doc') -+def apply_gnome_doc(self): -+ self.env['APPNAME'] = self.doc_module -+ lst = self.to_list(self.doc_linguas) -+ bld = self.bld -+ lst.append('C') -+ -+ for x in lst: -+ if not x == 'C': -+ tsk = self.create_task('xml2po') -+ node = self.path.find_resource(x+'/'+x+'.po') -+ src = self.path.find_resource('C/%s.xml' % self.doc_module) -+ out = self.path.find_or_declare('%s/%s.xml' % (x, self.doc_module)) -+ tsk.set_inputs([node, src]) -+ tsk.set_outputs(out) -+ else: -+ out = self.path.find_resource('%s/%s.xml' % (x, self.doc_module)) -+ -+ tsk2 = self.create_task('xsltproc2po') -+ out2 = self.path.find_or_declare('%s/%s-%s.omf' % (x, self.doc_module, x)) -+ tsk2.set_outputs(out2) -+ node = self.path.find_resource(self.doc_module+".omf.in") -+ tsk2.inputs = [node, out] -+ -+ tsk2.run_after.append(tsk) -+ -+ if bld.is_install: -+ path = self.install_path + '/gnome/help/%s/%s' % (self.doc_module, x) -+ bld.install_files(self.install_path + '/omf', out2, env=self.env) -+ for y in self.to_list(self.doc_figures): -+ try: -+ os.stat(self.path.abspath() + '/' + x + '/' + y) -+ bld.install_as(path + '/' + y, self.path.abspath() + '/' + x + '/' + y) -+ except: -+ bld.install_as(path + '/' + y, self.path.abspath() + '/C/' + y) -+ bld.install_as(path + '/%s.xml' % self.doc_module, out.abspath(self.env)) -+ if x == 'C': -+ xmls = self.to_list(self.doc_includes) -+ xmls.append(self.doc_entities) -+ for z in xmls: -+ out = self.path.find_resource('%s/%s' % (x, z)) -+ bld.install_as(path + '/%s' % z, out.abspath(self.env)) -+ -+# OBSOLETE -+class xml_to_taskgen(TaskGen.task_gen): -+ def __init__(self, *k, **kw): -+ TaskGen.task_gen.__init__(self, *k, **kw) -+ -+@feature('xml_to') -+def init_xml_to(self): -+ Utils.def_attrs(self, -+ source = 'xmlfile', -+ xslt = 'xlsltfile', -+ target = 'hey', -+ default_install_path = '${PREFIX}', -+ task_created = None) -+ -+@feature('xml_to') -+@after('init_xml_to') -+def apply_xml_to(self): -+ xmlfile = self.path.find_resource(self.source) -+ xsltfile = self.path.find_resource(self.xslt) -+ tsk = self.create_task('xmlto', [xmlfile, xsltfile], xmlfile.change_ext('html')) -+ tsk.install_path = self.install_path -+ -+def sgml_scan(self): -+ node = self.inputs[0] -+ -+ env = self.env -+ variant = node.variant(env) -+ -+ fi = open(node.abspath(env), 'r') -+ content = fi.read() -+ fi.close() -+ -+ # we should use a sgml parser :-/ -+ name = n1_regexp.findall(content)[0] -+ num = n2_regexp.findall(content)[0] -+ -+ doc_name = name+'.'+num -+ -+ if not self.outputs: -+ self.outputs = [self.generator.path.find_or_declare(doc_name)] -+ -+ return ([], [doc_name]) -+ -+class gnome_sgml2man_taskgen(TaskGen.task_gen): -+ def __init__(self, *k, **kw): -+ TaskGen.task_gen.__init__(self, *k, **kw) -+ -+@feature('gnome_sgml2man') -+def apply_gnome_sgml2man(self): -+ """ -+ we could make it more complicated, but for now we just scan the document each time -+ """ -+ assert(getattr(self, 'appname', None)) -+ -+ def install_result(task): -+ out = task.outputs[0] -+ name = out.name -+ ext = name[-1] -+ env = task.env -+ self.bld.install_files('${DATADIR}/man/man%s/' % ext, out, env) -+ -+ self.bld.rescan(self.path) -+ for name in self.bld.cache_dir_contents[self.path.id]: -+ base, ext = os.path.splitext(name) -+ if ext != '.sgml': continue -+ -+ task = self.create_task('sgml2man') -+ task.set_inputs(self.path.find_resource(name)) -+ task.task_generator = self -+ if self.bld.is_install: task.install = install_result -+ # no outputs, the scanner does it -+ # no caching for now, this is not a time-critical feature -+ # in the future the scanner can be used to do more things (find dependencies, etc) -+ task.scan() -+ -+cls = Task.simple_task_type('sgml2man', '${SGML2MAN} -o ${TGT[0].bld_dir(env)} ${SRC} > /dev/null', color='BLUE') -+cls.scan = sgml_scan -+cls.quiet = 1 -+ -+Task.simple_task_type('xmlto', '${XMLTO} html -m ${SRC[1].abspath(env)} ${SRC[0].abspath(env)}') -+ -+Task.simple_task_type('xml2po', '${XML2PO} ${XML2POFLAGS} ${SRC} > ${TGT}', color='BLUE') -+ -+# how do you expect someone to understand this?! -+xslt_magic = """${XSLTPROC2PO} -o ${TGT[0].abspath(env)} \ -+--stringparam db2omf.basename ${APPNAME} \ -+--stringparam db2omf.format docbook \ -+--stringparam db2omf.lang ${TGT[0].abspath(env)[:-4].split('-')[-1]} \ -+--stringparam db2omf.dtd '-//OASIS//DTD DocBook XML V4.3//EN' \ -+--stringparam db2omf.omf_dir ${PREFIX}/share/omf \ -+--stringparam db2omf.help_dir ${PREFIX}/share/gnome/help \ -+--stringparam db2omf.omf_in ${SRC[0].abspath(env)} \ -+--stringparam db2omf.scrollkeeper_cl ${SCROLLKEEPER_DATADIR}/Templates/C/scrollkeeper_cl.xml \ -+${DB2OMF} ${SRC[1].abspath(env)}""" -+ -+#--stringparam db2omf.dtd '-//OASIS//DTD DocBook XML V4.3//EN' \ -+Task.simple_task_type('xsltproc2po', xslt_magic, color='BLUE') -+ -+def detect(conf): -+ conf.check_tool('gnu_dirs glib2 dbus') -+ sgml2man = conf.find_program('docbook2man', var='SGML2MAN') -+ -+ def getstr(varname): -+ return getattr(Options.options, varname, '') -+ -+ # addefine also sets the variable to the env -+ conf.define('GNOMELOCALEDIR', os.path.join(conf.env['DATADIR'], 'locale')) -+ -+ xml2po = conf.find_program('xml2po', var='XML2PO') -+ xsltproc2po = conf.find_program('xsltproc', var='XSLTPROC2PO') -+ conf.env['XML2POFLAGS'] = '-e -p' -+ conf.env['SCROLLKEEPER_DATADIR'] = Utils.cmd_output("scrollkeeper-config --pkgdatadir", silent=1).strip() -+ conf.env['DB2OMF'] = Utils.cmd_output("/usr/bin/pkg-config --variable db2omf gnome-doc-utils", silent=1).strip() -+ -+def set_options(opt): -+ opt.add_option('--want-rpath', type='int', default=1, dest='want_rpath', help='set rpath to 1 or 0 [Default 1]') -+ -diff --git a/buildtools/wafadmin/Tools/gnu_dirs.py b/buildtools/wafadmin/Tools/gnu_dirs.py -new file mode 100644 -index 0000000..856e4a7 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/gnu_dirs.py -@@ -0,0 +1,111 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Ali Sabil, 2007 -+ -+""" -+To use this module do not forget to call -+opt.tool_options('gnu_dirs') -+AND -+conf.check_tool('gnu_dirs') -+ -+Add options for the standard GNU directories, this tool will add the options -+found in autotools, and will update the environment with the following -+installation variables: -+ -+ * PREFIX : architecture-independent files [/usr/local] -+ * EXEC_PREFIX : architecture-dependent files [PREFIX] -+ * BINDIR : user executables [EXEC_PREFIX/bin] -+ * SBINDIR : user executables [EXEC_PREFIX/sbin] -+ * LIBEXECDIR : program executables [EXEC_PREFIX/libexec] -+ * SYSCONFDIR : read-only single-machine data [PREFIX/etc] -+ * SHAREDSTATEDIR : modifiable architecture-independent data [PREFIX/com] -+ * LOCALSTATEDIR : modifiable single-machine data [PREFIX/var] -+ * LIBDIR : object code libraries [EXEC_PREFIX/lib] -+ * INCLUDEDIR : C header files [PREFIX/include] -+ * OLDINCLUDEDIR : C header files for non-gcc [/usr/include] -+ * DATAROOTDIR : read-only arch.-independent data root [PREFIX/share] -+ * DATADIR : read-only architecture-independent data [DATAROOTDIR] -+ * INFODIR : info documentation [DATAROOTDIR/info] -+ * LOCALEDIR : locale-dependent data [DATAROOTDIR/locale] -+ * MANDIR : man documentation [DATAROOTDIR/man] -+ * DOCDIR : documentation root [DATAROOTDIR/doc/telepathy-glib] -+ * HTMLDIR : html documentation [DOCDIR] -+ * DVIDIR : dvi documentation [DOCDIR] -+ * PDFDIR : pdf documentation [DOCDIR] -+ * PSDIR : ps documentation [DOCDIR] -+""" -+ -+import Utils, Options -+ -+_options = [x.split(', ') for x in ''' -+bindir, user executables, ${EXEC_PREFIX}/bin -+sbindir, system admin executables, ${EXEC_PREFIX}/sbin -+libexecdir, program executables, ${EXEC_PREFIX}/libexec -+sysconfdir, read-only single-machine data, ${PREFIX}/etc -+sharedstatedir, modifiable architecture-independent data, ${PREFIX}/com -+localstatedir, modifiable single-machine data, ${PREFIX}/var -+libdir, object code libraries, ${EXEC_PREFIX}/lib -+includedir, C header files, ${PREFIX}/include -+oldincludedir, C header files for non-gcc, /usr/include -+datarootdir, read-only arch.-independent data root, ${PREFIX}/share -+datadir, read-only architecture-independent data, ${DATAROOTDIR} -+infodir, info documentation, ${DATAROOTDIR}/info -+localedir, locale-dependent data, ${DATAROOTDIR}/locale -+mandir, man documentation, ${DATAROOTDIR}/man -+docdir, documentation root, ${DATAROOTDIR}/doc/${PACKAGE} -+htmldir, html documentation, ${DOCDIR} -+dvidir, dvi documentation, ${DOCDIR} -+pdfdir, pdf documentation, ${DOCDIR} -+psdir, ps documentation, ${DOCDIR} -+'''.split('\n') if x] -+ -+def detect(conf): -+ def get_param(varname, default): -+ return getattr(Options.options, varname, '') or default -+ -+ env = conf.env -+ env['EXEC_PREFIX'] = get_param('EXEC_PREFIX', env['PREFIX']) -+ env['PACKAGE'] = Utils.g_module.APPNAME -+ -+ complete = False -+ iter = 0 -+ while not complete and iter < len(_options) + 1: -+ iter += 1 -+ complete = True -+ for name, help, default in _options: -+ name = name.upper() -+ if not env[name]: -+ try: -+ env[name] = Utils.subst_vars(get_param(name, default), env) -+ except TypeError: -+ complete = False -+ if not complete: -+ lst = [name for name, _, _ in _options if not env[name.upper()]] -+ raise Utils.WafError('Variable substitution failure %r' % lst) -+ -+def set_options(opt): -+ -+ inst_dir = opt.add_option_group('Installation directories', -+'By default, "waf install" will put the files in\ -+ "/usr/local/bin", "/usr/local/lib" etc. An installation prefix other\ -+ than "/usr/local" can be given using "--prefix", for example "--prefix=$HOME"') -+ -+ for k in ('--prefix', '--destdir'): -+ option = opt.parser.get_option(k) -+ if option: -+ opt.parser.remove_option(k) -+ inst_dir.add_option(option) -+ -+ inst_dir.add_option('--exec-prefix', -+ help = 'installation prefix [Default: ${PREFIX}]', -+ default = '', -+ dest = 'EXEC_PREFIX') -+ -+ dirs_options = opt.add_option_group('Pre-defined installation directories', '') -+ -+ for name, help, default in _options: -+ option_name = '--' + name -+ str_default = default -+ str_help = '%s [Default: %s]' % (help, str_default) -+ dirs_options.add_option(option_name, help=str_help, default='', dest=name.upper()) -+ -diff --git a/buildtools/wafadmin/Tools/gob2.py b/buildtools/wafadmin/Tools/gob2.py -new file mode 100644 -index 0000000..00aaa32 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/gob2.py -@@ -0,0 +1,18 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Ali Sabil, 2007 -+ -+import TaskGen -+ -+TaskGen.declare_chain( -+ name = 'gob2', -+ rule = '${GOB2} -o ${TGT[0].bld_dir(env)} ${GOB2FLAGS} ${SRC}', -+ ext_in = '.gob', -+ ext_out = '.c' -+) -+ -+def detect(conf): -+ gob2 = conf.find_program('gob2', var='GOB2', mandatory=True) -+ conf.env['GOB2'] = gob2 -+ conf.env['GOB2FLAGS'] = '' -+ -diff --git a/buildtools/wafadmin/Tools/gxx.py b/buildtools/wafadmin/Tools/gxx.py -new file mode 100644 -index 0000000..8f4a0bf ---- /dev/null -+++ b/buildtools/wafadmin/Tools/gxx.py -@@ -0,0 +1,133 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006 (ita) -+# Ralf Habacker, 2006 (rh) -+# Yinon Ehrlich, 2009 -+ -+import os, sys -+import Configure, Options, Utils -+import ccroot, ar -+from Configure import conftest -+ -+@conftest -+def find_gxx(conf): -+ cxx = conf.find_program(['g++', 'c++'], var='CXX', mandatory=True) -+ cxx = conf.cmd_to_list(cxx) -+ ccroot.get_cc_version(conf, cxx, gcc=True) -+ conf.env.CXX_NAME = 'gcc' -+ conf.env.CXX = cxx -+ -+@conftest -+def gxx_common_flags(conf): -+ v = conf.env -+ -+ # CPPFLAGS CXXDEFINES _CXXINCFLAGS _CXXDEFFLAGS -+ v['CXXFLAGS_DEBUG'] = ['-g'] -+ v['CXXFLAGS_RELEASE'] = ['-O2'] -+ -+ v['CXX_SRC_F'] = '' -+ v['CXX_TGT_F'] = ['-c', '-o', ''] # shell hack for -MD -+ v['CPPPATH_ST'] = '-I%s' # template for adding include paths -+ -+ # linker -+ if not v['LINK_CXX']: v['LINK_CXX'] = v['CXX'] -+ v['CXXLNK_SRC_F'] = '' -+ v['CXXLNK_TGT_F'] = ['-o', ''] # shell hack for -MD -+ -+ v['LIB_ST'] = '-l%s' # template for adding libs -+ v['LIBPATH_ST'] = '-L%s' # template for adding libpaths -+ v['STATICLIB_ST'] = '-l%s' -+ v['STATICLIBPATH_ST'] = '-L%s' -+ v['RPATH_ST'] = '-Wl,-rpath,%s' -+ v['CXXDEFINES_ST'] = '-D%s' -+ -+ v['SONAME_ST'] = '-Wl,-h,%s' -+ v['SHLIB_MARKER'] = '-Wl,-Bdynamic' -+ v['STATICLIB_MARKER'] = '-Wl,-Bstatic' -+ v['FULLSTATIC_MARKER'] = '-static' -+ -+ # program -+ v['program_PATTERN'] = '%s' -+ -+ # shared library -+ v['shlib_CXXFLAGS'] = ['-fPIC', '-DPIC'] # avoid using -DPIC, -fPIC aleady defines the __PIC__ macro -+ v['shlib_LINKFLAGS'] = ['-shared'] -+ v['shlib_PATTERN'] = 'lib%s.so' -+ -+ # static lib -+ v['staticlib_LINKFLAGS'] = ['-Wl,-Bstatic'] -+ v['staticlib_PATTERN'] = 'lib%s.a' -+ -+ # osx stuff -+ v['LINKFLAGS_MACBUNDLE'] = ['-bundle', '-undefined', 'dynamic_lookup'] -+ v['CCFLAGS_MACBUNDLE'] = ['-fPIC'] -+ v['macbundle_PATTERN'] = '%s.bundle' -+ -+@conftest -+def gxx_modifier_win32(conf): -+ v = conf.env -+ v['program_PATTERN'] = '%s.exe' -+ -+ v['shlib_PATTERN'] = '%s.dll' -+ v['implib_PATTERN'] = 'lib%s.dll.a' -+ v['IMPLIB_ST'] = '-Wl,--out-implib,%s' -+ -+ dest_arch = v['DEST_CPU'] -+ v['shlib_CXXFLAGS'] = [] -+ -+ v.append_value('shlib_CXXFLAGS', '-DDLL_EXPORT') # TODO adding nonstandard defines like this DLL_EXPORT is not a good idea -+ -+ # Auto-import is enabled by default even without this option, -+ # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages -+ # that the linker emits otherwise. -+ v.append_value('LINKFLAGS', '-Wl,--enable-auto-import') -+ -+@conftest -+def gxx_modifier_cygwin(conf): -+ gxx_modifier_win32(conf) -+ v = conf.env -+ v['shlib_PATTERN'] = 'cyg%s.dll' -+ v.append_value('shlib_LINKFLAGS', '-Wl,--enable-auto-image-base') -+ -+@conftest -+def gxx_modifier_darwin(conf): -+ v = conf.env -+ v['shlib_CXXFLAGS'] = ['-fPIC', '-compatibility_version', '1', '-current_version', '1'] -+ v['shlib_LINKFLAGS'] = ['-dynamiclib'] -+ v['shlib_PATTERN'] = 'lib%s.dylib' -+ -+ v['staticlib_LINKFLAGS'] = [] -+ -+ v['SHLIB_MARKER'] = '' -+ v['STATICLIB_MARKER'] = '' -+ v['SONAME_ST'] = '' -+ -+@conftest -+def gxx_modifier_aix(conf): -+ v = conf.env -+ v['program_LINKFLAGS'] = ['-Wl,-brtl'] -+ -+ v['shlib_LINKFLAGS'] = ['-shared', '-Wl,-brtl,-bexpfull'] -+ -+ v['SHLIB_MARKER'] = '' -+ -+@conftest -+def gxx_modifier_platform(conf): -+ # * set configurations specific for a platform. -+ # * the destination platform is detected automatically by looking at the macros the compiler predefines, -+ # and if it's not recognised, it fallbacks to sys.platform. -+ dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() -+ gxx_modifier_func = globals().get('gxx_modifier_' + dest_os) -+ if gxx_modifier_func: -+ gxx_modifier_func(conf) -+ -+def detect(conf): -+ conf.find_gxx() -+ conf.find_cpp() -+ conf.find_ar() -+ conf.gxx_common_flags() -+ conf.gxx_modifier_platform() -+ conf.cxx_load_tools() -+ conf.cxx_add_flags() -+ conf.link_add_flags() -+ -diff --git a/buildtools/wafadmin/Tools/icc.py b/buildtools/wafadmin/Tools/icc.py -new file mode 100644 -index 0000000..9c9a926 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/icc.py -@@ -0,0 +1,37 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Stian Selnes, 2008 -+# Thomas Nagy 2009 -+ -+import os, sys -+import Configure, Options, Utils -+import ccroot, ar, gcc -+from Configure import conftest -+ -+@conftest -+def find_icc(conf): -+ if sys.platform == 'cygwin': -+ conf.fatal('The Intel compiler does not work on Cygwin') -+ -+ v = conf.env -+ cc = None -+ if v['CC']: cc = v['CC'] -+ elif 'CC' in conf.environ: cc = conf.environ['CC'] -+ if not cc: cc = conf.find_program('icc', var='CC') -+ if not cc: cc = conf.find_program('ICL', var='CC') -+ if not cc: conf.fatal('Intel C Compiler (icc) was not found') -+ cc = conf.cmd_to_list(cc) -+ -+ ccroot.get_cc_version(conf, cc, icc=True) -+ v['CC'] = cc -+ v['CC_NAME'] = 'icc' -+ -+detect = ''' -+find_icc -+find_ar -+gcc_common_flags -+gcc_modifier_platform -+cc_load_tools -+cc_add_flags -+link_add_flags -+''' -diff --git a/buildtools/wafadmin/Tools/icpc.py b/buildtools/wafadmin/Tools/icpc.py -new file mode 100644 -index 0000000..7d79c57 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/icpc.py -@@ -0,0 +1,35 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy 2009 -+ -+import os, sys -+import Configure, Options, Utils -+import ccroot, ar, gxx -+from Configure import conftest -+ -+@conftest -+def find_icpc(conf): -+ if sys.platform == 'cygwin': -+ conf.fatal('The Intel compiler does not work on Cygwin') -+ -+ v = conf.env -+ cxx = None -+ if v['CXX']: cxx = v['CXX'] -+ elif 'CXX' in conf.environ: cxx = conf.environ['CXX'] -+ if not cxx: cxx = conf.find_program('icpc', var='CXX') -+ if not cxx: conf.fatal('Intel C++ Compiler (icpc) was not found') -+ cxx = conf.cmd_to_list(cxx) -+ -+ ccroot.get_cc_version(conf, cxx, icc=True) -+ v['CXX'] = cxx -+ v['CXX_NAME'] = 'icc' -+ -+detect = ''' -+find_icpc -+find_ar -+gxx_common_flags -+gxx_modifier_platform -+cxx_load_tools -+cxx_add_flags -+link_add_flags -+''' -diff --git a/buildtools/wafadmin/Tools/intltool.py b/buildtools/wafadmin/Tools/intltool.py -new file mode 100644 -index 0000000..deb8f4a ---- /dev/null -+++ b/buildtools/wafadmin/Tools/intltool.py -@@ -0,0 +1,139 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006 (ita) -+ -+"intltool support" -+ -+import os, re -+import Configure, TaskGen, Task, Utils, Runner, Options, Build, config_c -+from TaskGen import feature, before, taskgen -+from Logs import error -+ -+""" -+Usage: -+ -+bld(features='intltool_in', source='a.po b.po', podir='po', cache='.intlcache', flags='') -+ -+""" -+ -+class intltool_in_taskgen(TaskGen.task_gen): -+ """deprecated""" -+ def __init__(self, *k, **kw): -+ TaskGen.task_gen.__init__(self, *k, **kw) -+ -+@before('apply_core') -+@feature('intltool_in') -+def iapply_intltool_in_f(self): -+ try: self.meths.remove('apply_core') -+ except ValueError: pass -+ -+ for i in self.to_list(self.source): -+ node = self.path.find_resource(i) -+ -+ podir = getattr(self, 'podir', 'po') -+ podirnode = self.path.find_dir(podir) -+ if not podirnode: -+ error("could not find the podir %r" % podir) -+ continue -+ -+ cache = getattr(self, 'intlcache', '.intlcache') -+ self.env['INTLCACHE'] = os.path.join(self.path.bldpath(self.env), podir, cache) -+ self.env['INTLPODIR'] = podirnode.srcpath(self.env) -+ self.env['INTLFLAGS'] = getattr(self, 'flags', ['-q', '-u', '-c']) -+ -+ task = self.create_task('intltool', node, node.change_ext('')) -+ task.install_path = self.install_path -+ -+class intltool_po_taskgen(TaskGen.task_gen): -+ """deprecated""" -+ def __init__(self, *k, **kw): -+ TaskGen.task_gen.__init__(self, *k, **kw) -+ -+ -+@feature('intltool_po') -+def apply_intltool_po(self): -+ try: self.meths.remove('apply_core') -+ except ValueError: pass -+ -+ self.default_install_path = '${LOCALEDIR}' -+ appname = getattr(self, 'appname', 'set_your_app_name') -+ podir = getattr(self, 'podir', '') -+ -+ def install_translation(task): -+ out = task.outputs[0] -+ filename = out.name -+ (langname, ext) = os.path.splitext(filename) -+ inst_file = langname + os.sep + 'LC_MESSAGES' + os.sep + appname + '.mo' -+ self.bld.install_as(os.path.join(self.install_path, inst_file), out, self.env, self.chmod) -+ -+ linguas = self.path.find_resource(os.path.join(podir, 'LINGUAS')) -+ if linguas: -+ # scan LINGUAS file for locales to process -+ file = open(linguas.abspath()) -+ langs = [] -+ for line in file.readlines(): -+ # ignore lines containing comments -+ if not line.startswith('#'): -+ langs += line.split() -+ file.close() -+ re_linguas = re.compile('[-a-zA-Z_@.]+') -+ for lang in langs: -+ # Make sure that we only process lines which contain locales -+ if re_linguas.match(lang): -+ node = self.path.find_resource(os.path.join(podir, re_linguas.match(lang).group() + '.po')) -+ task = self.create_task('po') -+ task.set_inputs(node) -+ task.set_outputs(node.change_ext('.mo')) -+ if self.bld.is_install: task.install = install_translation -+ else: -+ Utils.pprint('RED', "Error no LINGUAS file found in po directory") -+ -+Task.simple_task_type('po', '${POCOM} -o ${TGT} ${SRC}', color='BLUE', shell=False) -+Task.simple_task_type('intltool', -+ '${INTLTOOL} ${INTLFLAGS} ${INTLCACHE} ${INTLPODIR} ${SRC} ${TGT}', -+ color='BLUE', after="cc_link cxx_link", shell=False) -+ -+def detect(conf): -+ pocom = conf.find_program('msgfmt') -+ if not pocom: -+ # if msgfmt should not be mandatory, catch the thrown exception in your wscript -+ conf.fatal('The program msgfmt (gettext) is mandatory!') -+ conf.env['POCOM'] = pocom -+ -+ # NOTE: it is possible to set INTLTOOL in the environment, but it must not have spaces in it -+ -+ intltool = conf.find_program('intltool-merge', var='INTLTOOL') -+ if not intltool: -+ # if intltool-merge should not be mandatory, catch the thrown exception in your wscript -+ if Options.platform == 'win32': -+ perl = conf.find_program('perl', var='PERL') -+ if not perl: -+ conf.fatal('The program perl (required by intltool) could not be found') -+ -+ intltooldir = Configure.find_file('intltool-merge', os.environ['PATH'].split(os.pathsep)) -+ if not intltooldir: -+ conf.fatal('The program intltool-merge (intltool, gettext-devel) is mandatory!') -+ -+ conf.env['INTLTOOL'] = Utils.to_list(conf.env['PERL']) + [intltooldir + os.sep + 'intltool-merge'] -+ conf.check_message('intltool', '', True, ' '.join(conf.env['INTLTOOL'])) -+ else: -+ conf.fatal('The program intltool-merge (intltool, gettext-devel) is mandatory!') -+ -+ def getstr(varname): -+ return getattr(Options.options, varname, '') -+ -+ prefix = conf.env['PREFIX'] -+ datadir = getstr('datadir') -+ if not datadir: datadir = os.path.join(prefix,'share') -+ -+ conf.define('LOCALEDIR', os.path.join(datadir, 'locale')) -+ conf.define('DATADIR', datadir) -+ -+ if conf.env['CC'] or conf.env['CXX']: -+ # Define to 1 if is present -+ conf.check(header_name='locale.h') -+ -+def set_options(opt): -+ opt.add_option('--want-rpath', type='int', default=1, dest='want_rpath', help='set rpath to 1 or 0 [Default 1]') -+ opt.add_option('--datadir', type='string', default='', dest='datadir', help='read-only application data') -+ -diff --git a/buildtools/wafadmin/Tools/javaw.py b/buildtools/wafadmin/Tools/javaw.py -new file mode 100644 -index 0000000..301ebc4 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/javaw.py -@@ -0,0 +1,255 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006-2008 (ita) -+ -+""" -+Java support -+ -+Javac is one of the few compilers that behaves very badly: -+* it outputs files where it wants to (-d is only for the package root) -+* it recompiles files silently behind your back -+* it outputs an undefined amount of files (inner classes) -+ -+Fortunately, the convention makes it possible to use the build dir without -+too many problems for the moment -+ -+Inner classes must be located and cleaned when a problem arise, -+for the moment waf does not track the production of inner classes. -+ -+Adding all the files to a task and executing it if any of the input files -+change is only annoying for the compilation times -+ -+Compilation can be run using Jython[1] rather than regular Python. Instead of -+running one of the following commands: -+ ./waf configure -+ python waf configure -+You would have to run: -+ java -jar /path/to/jython.jar waf configure -+ -+[1] http://www.jython.org/ -+""" -+ -+import os, re -+from Configure import conf -+import TaskGen, Task, Utils, Options, Build -+from TaskGen import feature, before, taskgen -+ -+class_check_source = ''' -+public class Test { -+ public static void main(String[] argv) { -+ Class lib; -+ if (argv.length < 1) { -+ System.err.println("Missing argument"); -+ System.exit(77); -+ } -+ try { -+ lib = Class.forName(argv[0]); -+ } catch (ClassNotFoundException e) { -+ System.err.println("ClassNotFoundException"); -+ System.exit(1); -+ } -+ lib = null; -+ System.exit(0); -+ } -+} -+''' -+ -+@feature('jar') -+@before('apply_core') -+def jar_files(self): -+ basedir = getattr(self, 'basedir', '.') -+ destfile = getattr(self, 'destfile', 'test.jar') -+ jaropts = getattr(self, 'jaropts', []) -+ jarcreate = getattr(self, 'jarcreate', 'cf') -+ -+ dir = self.path.find_dir(basedir) -+ if not dir: raise -+ -+ jaropts.append('-C') -+ jaropts.append(dir.abspath(self.env)) -+ jaropts.append('.') -+ -+ out = self.path.find_or_declare(destfile) -+ -+ tsk = self.create_task('jar_create') -+ tsk.set_outputs(out) -+ tsk.inputs = [x for x in dir.find_iter(src=0, bld=1) if x.id != out.id] -+ tsk.env['JAROPTS'] = jaropts -+ tsk.env['JARCREATE'] = jarcreate -+ -+@feature('javac') -+@before('apply_core') -+def apply_java(self): -+ Utils.def_attrs(self, jarname='', jaropts='', classpath='', -+ sourcepath='.', srcdir='.', source_re='**/*.java', -+ jar_mf_attributes={}, jar_mf_classpath=[]) -+ -+ if getattr(self, 'source_root', None): -+ # old stuff -+ self.srcdir = self.source_root -+ -+ -+ nodes_lst = [] -+ -+ if not self.classpath: -+ if not self.env['CLASSPATH']: -+ self.env['CLASSPATH'] = '..' + os.pathsep + '.' -+ else: -+ self.env['CLASSPATH'] = self.classpath -+ -+ srcdir_node = self.path.find_dir(self.srcdir) -+ if not srcdir_node: -+ raise Utils.WafError('could not find srcdir %r' % self.srcdir) -+ -+ src_nodes = [x for x in srcdir_node.ant_glob(self.source_re, flat=False)] -+ bld_nodes = [x.change_ext('.class') for x in src_nodes] -+ -+ self.env['OUTDIR'] = [srcdir_node.bldpath(self.env)] -+ -+ tsk = self.create_task('javac') -+ tsk.set_inputs(src_nodes) -+ tsk.set_outputs(bld_nodes) -+ -+ if getattr(self, 'compat', None): -+ tsk.env.append_value('JAVACFLAGS', ['-source', self.compat]) -+ -+ if hasattr(self, 'sourcepath'): -+ fold = [self.path.find_dir(x) for x in self.to_list(self.sourcepath)] -+ names = os.pathsep.join([x.srcpath() for x in fold]) -+ else: -+ names = srcdir_node.srcpath() -+ -+ if names: -+ tsk.env.append_value('JAVACFLAGS', ['-sourcepath', names]) -+ -+ if self.jarname: -+ jtsk = self.create_task('jar_create', bld_nodes, self.path.find_or_declare(self.jarname)) -+ jtsk.set_run_after(tsk) -+ -+ if not self.env.JAROPTS: -+ if self.jaropts: -+ self.env.JAROPTS = self.jaropts -+ else: -+ dirs = '.' -+ self.env.JAROPTS = ['-C', ''.join(self.env['OUTDIR']), dirs] -+ -+Task.simple_task_type('jar_create', '${JAR} ${JARCREATE} ${TGT} ${JAROPTS}', color='GREEN', shell=False) -+cls = Task.simple_task_type('javac', '${JAVAC} -classpath ${CLASSPATH} -d ${OUTDIR} ${JAVACFLAGS} ${SRC}', shell=False) -+cls.color = 'BLUE' -+def post_run_javac(self): -+ """this is for cleaning the folder -+ javac creates single files for inner classes -+ but it is not possible to know which inner classes in advance""" -+ -+ par = {} -+ for x in self.inputs: -+ par[x.parent.id] = x.parent -+ -+ inner = {} -+ for k in par.values(): -+ path = k.abspath(self.env) -+ lst = os.listdir(path) -+ -+ for u in lst: -+ if u.find('$') >= 0: -+ inner_class_node = k.find_or_declare(u) -+ inner[inner_class_node.id] = inner_class_node -+ -+ to_add = set(inner.keys()) - set([x.id for x in self.outputs]) -+ for x in to_add: -+ self.outputs.append(inner[x]) -+ -+ self.cached = True # disable the cache here - inner classes are a problem -+ return Task.Task.post_run(self) -+cls.post_run = post_run_javac -+ -+def detect(conf): -+ # If JAVA_PATH is set, we prepend it to the path list -+ java_path = conf.environ['PATH'].split(os.pathsep) -+ v = conf.env -+ -+ if 'JAVA_HOME' in conf.environ: -+ java_path = [os.path.join(conf.environ['JAVA_HOME'], 'bin')] + java_path -+ conf.env['JAVA_HOME'] = [conf.environ['JAVA_HOME']] -+ -+ for x in 'javac java jar'.split(): -+ conf.find_program(x, var=x.upper(), path_list=java_path) -+ conf.env[x.upper()] = conf.cmd_to_list(conf.env[x.upper()]) -+ v['JAVA_EXT'] = ['.java'] -+ -+ if 'CLASSPATH' in conf.environ: -+ v['CLASSPATH'] = conf.environ['CLASSPATH'] -+ -+ if not v['JAR']: conf.fatal('jar is required for making java packages') -+ if not v['JAVAC']: conf.fatal('javac is required for compiling java classes') -+ v['JARCREATE'] = 'cf' # can use cvf -+ -+@conf -+def check_java_class(self, classname, with_classpath=None): -+ """Check if the specified java class is installed""" -+ -+ import shutil -+ -+ javatestdir = '.waf-javatest' -+ -+ classpath = javatestdir -+ if self.env['CLASSPATH']: -+ classpath += os.pathsep + self.env['CLASSPATH'] -+ if isinstance(with_classpath, str): -+ classpath += os.pathsep + with_classpath -+ -+ shutil.rmtree(javatestdir, True) -+ os.mkdir(javatestdir) -+ -+ java_file = open(os.path.join(javatestdir, 'Test.java'), 'w') -+ java_file.write(class_check_source) -+ java_file.close() -+ -+ # Compile the source -+ Utils.exec_command(self.env['JAVAC'] + [os.path.join(javatestdir, 'Test.java')], shell=False) -+ -+ # Try to run the app -+ cmd = self.env['JAVA'] + ['-cp', classpath, 'Test', classname] -+ self.log.write("%s\n" % str(cmd)) -+ found = Utils.exec_command(cmd, shell=False, log=self.log) -+ -+ self.check_message('Java class %s' % classname, "", not found) -+ -+ shutil.rmtree(javatestdir, True) -+ -+ return found -+ -+@conf -+def check_jni_headers(conf): -+ """ -+ Check for jni headers and libraries -+ -+ On success the environment variable xxx_JAVA is added for uselib -+ """ -+ -+ if not conf.env.CC_NAME and not conf.env.CXX_NAME: -+ conf.fatal('load a compiler first (gcc, g++, ..)') -+ -+ if not conf.env.JAVA_HOME: -+ conf.fatal('set JAVA_HOME in the system environment') -+ -+ # jni requires the jvm -+ javaHome = conf.env['JAVA_HOME'][0] -+ -+ b = Build.BuildContext() -+ b.load_dirs(conf.srcdir, conf.blddir) -+ dir = b.root.find_dir(conf.env.JAVA_HOME[0] + '/include') -+ f = dir.ant_glob('**/(jni|jni_md).h', flat=False) -+ incDirs = [x.parent.abspath() for x in f] -+ -+ dir = b.root.find_dir(conf.env.JAVA_HOME[0]) -+ f = dir.ant_glob('**/*jvm.(so|dll)', flat=False) -+ libDirs = [x.parent.abspath() for x in f] or [javaHome] -+ -+ for i, d in enumerate(libDirs): -+ if conf.check(header_name='jni.h', define_name='HAVE_JNI_H', lib='jvm', -+ libpath=d, includes=incDirs, uselib_store='JAVA', uselib='JAVA'): -+ break -+ else: -+ conf.fatal('could not find lib jvm in %r (see config.log)' % libDirs) -+ -diff --git a/buildtools/wafadmin/Tools/kde4.py b/buildtools/wafadmin/Tools/kde4.py -new file mode 100644 -index 0000000..f480929 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/kde4.py -@@ -0,0 +1,74 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006 (ita) -+ -+import os, sys, re -+import Options, TaskGen, Task, Utils -+from TaskGen import taskgen, feature, after -+ -+class msgfmt_taskgen(TaskGen.task_gen): -+ def __init__(self, *k, **kw): -+ TaskGen.task_gen.__init__(self, *k, **kw) -+ -+@feature('msgfmt') -+def init_msgfmt(self): -+ #langs = '' # for example "foo/fr foo/br" -+ self.default_install_path = '${KDE4_LOCALE_INSTALL_DIR}' -+ -+@feature('msgfmt') -+@after('init_msgfmt') -+def apply_msgfmt(self): -+ for lang in self.to_list(self.langs): -+ node = self.path.find_resource(lang+'.po') -+ task = self.create_task('msgfmt', node, node.change_ext('.mo')) -+ -+ if not self.bld.is_install: continue -+ langname = lang.split('/') -+ langname = langname[-1] -+ task.install_path = self.install_path + os.sep + langname + os.sep + 'LC_MESSAGES' -+ task.filename = getattr(self, 'appname', 'set_your_appname') + '.mo' -+ task.chmod = self.chmod -+ -+def detect(conf): -+ kdeconfig = conf.find_program('kde4-config') -+ if not kdeconfig: -+ conf.fatal('we need kde4-config') -+ prefix = Utils.cmd_output('%s --prefix' % kdeconfig, silent=True).strip() -+ file = '%s/share/apps/cmake/modules/KDELibsDependencies.cmake' % prefix -+ try: os.stat(file) -+ except OSError: -+ file = '%s/share/kde4/apps/cmake/modules/KDELibsDependencies.cmake' % prefix -+ try: os.stat(file) -+ except OSError: conf.fatal('could not open %s' % file) -+ -+ try: -+ txt = Utils.readf(file) -+ except (OSError, IOError): -+ conf.fatal('could not read %s' % file) -+ -+ txt = txt.replace('\\\n', '\n') -+ fu = re.compile('#(.*)\n') -+ txt = fu.sub('', txt) -+ -+ setregexp = re.compile('([sS][eE][tT]\s*\()\s*([^\s]+)\s+\"([^"]+)\"\)') -+ found = setregexp.findall(txt) -+ -+ for (_, key, val) in found: -+ #print key, val -+ conf.env[key] = val -+ -+ # well well, i could just write an interpreter for cmake files -+ conf.env['LIB_KDECORE']='kdecore' -+ conf.env['LIB_KDEUI'] ='kdeui' -+ conf.env['LIB_KIO'] ='kio' -+ conf.env['LIB_KHTML'] ='khtml' -+ conf.env['LIB_KPARTS'] ='kparts' -+ -+ conf.env['LIBPATH_KDECORE'] = conf.env['KDE4_LIB_INSTALL_DIR'] -+ conf.env['CPPPATH_KDECORE'] = conf.env['KDE4_INCLUDE_INSTALL_DIR'] -+ conf.env.append_value('CPPPATH_KDECORE', conf.env['KDE4_INCLUDE_INSTALL_DIR']+"/KDE") -+ -+ conf.env['MSGFMT'] = conf.find_program('msgfmt') -+ -+Task.simple_task_type('msgfmt', '${MSGFMT} ${SRC} -o ${TGT}', color='BLUE', shell=False) -+ -diff --git a/buildtools/wafadmin/Tools/libtool.py b/buildtools/wafadmin/Tools/libtool.py -new file mode 100644 -index 0000000..47fa906 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/libtool.py -@@ -0,0 +1,330 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Matthias Jahn, 2008, jahn matthias ath freenet punto de -+# Thomas Nagy, 2008 (ita) -+ -+import sys, re, os, optparse -+ -+import TaskGen, Task, Utils, preproc -+from Logs import error, debug, warn -+from TaskGen import taskgen, after, before, feature -+ -+REVISION="0.1.3" -+ -+""" -+if you want to use the code here, you must use something like this: -+obj = obj.create(...) -+obj.features.append("libtool") -+obj.vnum = "1.2.3" # optional, but versioned libraries are common -+""" -+ -+# fake libtool files -+fakelibtool_vardeps = ['CXX', 'PREFIX'] -+def fakelibtool_build(task): -+ # Writes a .la file, used by libtool -+ env = task.env -+ dest = open(task.outputs[0].abspath(env), 'w') -+ sname = task.inputs[0].name -+ fu = dest.write -+ fu("# Generated by ltmain.sh - GNU libtool 1.5.18 - (pwn3d by BKsys II code name WAF)\n") -+ if env['vnum']: -+ nums = env['vnum'].split('.') -+ libname = task.inputs[0].name -+ name3 = libname+'.'+env['vnum'] -+ name2 = libname+'.'+nums[0] -+ name1 = libname -+ fu("dlname='%s'\n" % name2) -+ strn = " ".join([name3, name2, name1]) -+ fu("library_names='%s'\n" % (strn) ) -+ else: -+ fu("dlname='%s'\n" % sname) -+ fu("library_names='%s %s %s'\n" % (sname, sname, sname) ) -+ fu("old_library=''\n") -+ vars = ' '.join(env['libtoolvars']+env['LINKFLAGS']) -+ fu("dependency_libs='%s'\n" % vars) -+ fu("current=0\n") -+ fu("age=0\nrevision=0\ninstalled=yes\nshouldnotlink=no\n") -+ fu("dlopen=''\ndlpreopen=''\n") -+ fu("libdir='%s/lib'\n" % env['PREFIX']) -+ dest.close() -+ return 0 -+ -+def read_la_file(path): -+ sp = re.compile(r'^([^=]+)=\'(.*)\'$') -+ dc={} -+ file = open(path, "r") -+ for line in file.readlines(): -+ try: -+ #print sp.split(line.strip()) -+ _, left, right, _ = sp.split(line.strip()) -+ dc[left]=right -+ except ValueError: -+ pass -+ file.close() -+ return dc -+ -+@feature("libtool") -+@after('apply_link') -+def apply_link_libtool(self): -+ if self.type != 'program': -+ linktask = self.link_task -+ self.latask = self.create_task('fakelibtool', linktask.outputs, linktask.outputs[0].change_ext('.la')) -+ -+ if self.bld.is_install: -+ self.bld.install_files('${PREFIX}/lib', linktask.outputs[0], self.env) -+ -+@feature("libtool") -+@before('apply_core') -+def apply_libtool(self): -+ self.env['vnum']=self.vnum -+ -+ paths=[] -+ libs=[] -+ libtool_files=[] -+ libtool_vars=[] -+ -+ for l in self.env['LINKFLAGS']: -+ if l[:2]=='-L': -+ paths.append(l[2:]) -+ elif l[:2]=='-l': -+ libs.append(l[2:]) -+ -+ for l in libs: -+ for p in paths: -+ dict = read_la_file(p+'/lib'+l+'.la') -+ linkflags2 = dict.get('dependency_libs', '') -+ for v in linkflags2.split(): -+ if v.endswith('.la'): -+ libtool_files.append(v) -+ libtool_vars.append(v) -+ continue -+ self.env.append_unique('LINKFLAGS', v) -+ break -+ -+ self.env['libtoolvars']=libtool_vars -+ -+ while libtool_files: -+ file = libtool_files.pop() -+ dict = read_la_file(file) -+ for v in dict['dependency_libs'].split(): -+ if v[-3:] == '.la': -+ libtool_files.append(v) -+ continue -+ self.env.append_unique('LINKFLAGS', v) -+ -+Task.task_type_from_func('fakelibtool', vars=fakelibtool_vardeps, func=fakelibtool_build, color='BLUE', after="cc_link cxx_link static_link") -+ -+class libtool_la_file: -+ def __init__ (self, la_filename): -+ self.__la_filename = la_filename -+ #remove path and .la suffix -+ self.linkname = str(os.path.split(la_filename)[-1])[:-3] -+ if self.linkname.startswith("lib"): -+ self.linkname = self.linkname[3:] -+ # The name that we can dlopen(3). -+ self.dlname = None -+ # Names of this library -+ self.library_names = None -+ # The name of the static archive. -+ self.old_library = None -+ # Libraries that this one depends upon. -+ self.dependency_libs = None -+ # Version information for libIlmImf. -+ self.current = None -+ self.age = None -+ self.revision = None -+ # Is this an already installed library? -+ self.installed = None -+ # Should we warn about portability when linking against -modules? -+ self.shouldnotlink = None -+ # Files to dlopen/dlpreopen -+ self.dlopen = None -+ self.dlpreopen = None -+ # Directory that this library needs to be installed in: -+ self.libdir = '/usr/lib' -+ if not self.__parse(): -+ raise ValueError("file %s not found!!" %(la_filename)) -+ -+ def __parse(self): -+ "Retrieve the variables from a file" -+ if not os.path.isfile(self.__la_filename): return 0 -+ la_file=open(self.__la_filename, 'r') -+ for line in la_file: -+ ln = line.strip() -+ if not ln: continue -+ if ln[0]=='#': continue -+ (key, value) = str(ln).split('=', 1) -+ key = key.strip() -+ value = value.strip() -+ if value == "no": value = False -+ elif value == "yes": value = True -+ else: -+ try: value = int(value) -+ except ValueError: value = value.strip("'") -+ setattr(self, key, value) -+ la_file.close() -+ return 1 -+ -+ def get_libs(self): -+ """return linkflags for this lib""" -+ libs = [] -+ if self.dependency_libs: -+ libs = str(self.dependency_libs).strip().split() -+ if libs == None: -+ libs = [] -+ # add la lib and libdir -+ libs.insert(0, "-l%s" % self.linkname.strip()) -+ libs.insert(0, "-L%s" % self.libdir.strip()) -+ return libs -+ -+ def __str__(self): -+ return '''\ -+dlname = "%(dlname)s" -+library_names = "%(library_names)s" -+old_library = "%(old_library)s" -+dependency_libs = "%(dependency_libs)s" -+version = %(current)s.%(age)s.%(revision)s -+installed = "%(installed)s" -+shouldnotlink = "%(shouldnotlink)s" -+dlopen = "%(dlopen)s" -+dlpreopen = "%(dlpreopen)s" -+libdir = "%(libdir)s"''' % self.__dict__ -+ -+class libtool_config: -+ def __init__ (self, la_filename): -+ self.__libtool_la_file = libtool_la_file(la_filename) -+ tmp = self.__libtool_la_file -+ self.__version = [int(tmp.current), int(tmp.age), int(tmp.revision)] -+ self.__sub_la_files = [] -+ self.__sub_la_files.append(la_filename) -+ self.__libs = None -+ -+ def __cmp__(self, other): -+ """make it compareable with X.Y.Z versions (Y and Z are optional)""" -+ if not other: -+ return 1 -+ othervers = [int(s) for s in str(other).split(".")] -+ selfvers = self.__version -+ return cmp(selfvers, othervers) -+ -+ def __str__(self): -+ return "\n".join([ -+ str(self.__libtool_la_file), -+ ' '.join(self.__libtool_la_file.get_libs()), -+ '* New getlibs:', -+ ' '.join(self.get_libs()) -+ ]) -+ -+ def __get_la_libs(self, la_filename): -+ return libtool_la_file(la_filename).get_libs() -+ -+ def get_libs(self): -+ """return the complete uniqe linkflags that do not -+ contain .la files anymore""" -+ libs_list = list(self.__libtool_la_file.get_libs()) -+ libs_map = {} -+ while len(libs_list) > 0: -+ entry = libs_list.pop(0) -+ if entry: -+ if str(entry).endswith(".la"): -+ ## prevents duplicate .la checks -+ if entry not in self.__sub_la_files: -+ self.__sub_la_files.append(entry) -+ libs_list.extend(self.__get_la_libs(entry)) -+ else: -+ libs_map[entry]=1 -+ self.__libs = libs_map.keys() -+ return self.__libs -+ -+ def get_libs_only_L(self): -+ if not self.__libs: self.get_libs() -+ libs = self.__libs -+ libs = [s for s in libs if str(s).startswith('-L')] -+ return libs -+ -+ def get_libs_only_l(self): -+ if not self.__libs: self.get_libs() -+ libs = self.__libs -+ libs = [s for s in libs if str(s).startswith('-l')] -+ return libs -+ -+ def get_libs_only_other(self): -+ if not self.__libs: self.get_libs() -+ libs = self.__libs -+ libs = [s for s in libs if not(str(s).startswith('-L')or str(s).startswith('-l'))] -+ return libs -+ -+def useCmdLine(): -+ """parse cmdline args and control build""" -+ usage = '''Usage: %prog [options] PathToFile.la -+example: %prog --atleast-version=2.0.0 /usr/lib/libIlmImf.la -+nor: %prog --libs /usr/lib/libamarok.la''' -+ parser = optparse.OptionParser(usage) -+ a = parser.add_option -+ a("--version", dest = "versionNumber", -+ action = "store_true", default = False, -+ help = "output version of libtool-config" -+ ) -+ a("--debug", dest = "debug", -+ action = "store_true", default = False, -+ help = "enable debug" -+ ) -+ a("--libs", dest = "libs", -+ action = "store_true", default = False, -+ help = "output all linker flags" -+ ) -+ a("--libs-only-l", dest = "libs_only_l", -+ action = "store_true", default = False, -+ help = "output -l flags" -+ ) -+ a("--libs-only-L", dest = "libs_only_L", -+ action = "store_true", default = False, -+ help = "output -L flags" -+ ) -+ a("--libs-only-other", dest = "libs_only_other", -+ action = "store_true", default = False, -+ help = "output other libs (e.g. -pthread)" -+ ) -+ a("--atleast-version", dest = "atleast_version", -+ default=None, -+ help = "return 0 if the module is at least version ATLEAST_VERSION" -+ ) -+ a("--exact-version", dest = "exact_version", -+ default=None, -+ help = "return 0 if the module is exactly version EXACT_VERSION" -+ ) -+ a("--max-version", dest = "max_version", -+ default=None, -+ help = "return 0 if the module is at no newer than version MAX_VERSION" -+ ) -+ -+ (options, args) = parser.parse_args() -+ if len(args) != 1 and not options.versionNumber: -+ parser.error("incorrect number of arguments") -+ if options.versionNumber: -+ print("libtool-config version %s" % REVISION) -+ return 0 -+ ltf = libtool_config(args[0]) -+ if options.debug: -+ print(ltf) -+ if options.atleast_version: -+ if ltf >= options.atleast_version: return 0 -+ sys.exit(1) -+ if options.exact_version: -+ if ltf == options.exact_version: return 0 -+ sys.exit(1) -+ if options.max_version: -+ if ltf <= options.max_version: return 0 -+ sys.exit(1) -+ -+ def p(x): -+ print(" ".join(x)) -+ if options.libs: p(ltf.get_libs()) -+ elif options.libs_only_l: p(ltf.get_libs_only_l()) -+ elif options.libs_only_L: p(ltf.get_libs_only_L()) -+ elif options.libs_only_other: p(ltf.get_libs_only_other()) -+ return 0 -+ -+if __name__ == '__main__': -+ useCmdLine() -+ -diff --git a/buildtools/wafadmin/Tools/lua.py b/buildtools/wafadmin/Tools/lua.py -new file mode 100644 -index 0000000..5b181e1 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/lua.py -@@ -0,0 +1,25 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Sebastian Schlingmann, 2008 -+# Thomas Nagy, 2008 (ita) -+ -+import TaskGen -+from TaskGen import taskgen, feature -+from Constants import * -+ -+TaskGen.declare_chain( -+ name = 'luac', -+ rule = '${LUAC} -s -o ${TGT} ${SRC}', -+ ext_in = '.lua', -+ ext_out = '.luac', -+ reentrant = False, -+ install = 'LUADIR', # env variable -+) -+ -+@feature('lua') -+def init_lua(self): -+ self.default_chmod = O755 -+ -+def detect(conf): -+ conf.find_program('luac', var='LUAC', mandatory = True) -+ -diff --git a/buildtools/wafadmin/Tools/misc.py b/buildtools/wafadmin/Tools/misc.py -new file mode 100644 -index 0000000..9903ee4 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/misc.py -@@ -0,0 +1,430 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006 (ita) -+ -+""" -+Custom objects: -+ - execute a function everytime -+ - copy a file somewhere else -+""" -+ -+import shutil, re, os -+import TaskGen, Node, Task, Utils, Build, Constants -+from TaskGen import feature, taskgen, after, before -+from Logs import debug -+ -+def copy_func(tsk): -+ "Make a file copy. This might be used to make other kinds of file processing (even calling a compiler is possible)" -+ env = tsk.env -+ infile = tsk.inputs[0].abspath(env) -+ outfile = tsk.outputs[0].abspath(env) -+ try: -+ shutil.copy2(infile, outfile) -+ except (OSError, IOError): -+ return 1 -+ else: -+ if tsk.chmod: os.chmod(outfile, tsk.chmod) -+ return 0 -+ -+def action_process_file_func(tsk): -+ "Ask the function attached to the task to process it" -+ if not tsk.fun: raise Utils.WafError('task must have a function attached to it for copy_func to work!') -+ return tsk.fun(tsk) -+ -+class cmd_taskgen(TaskGen.task_gen): -+ def __init__(self, *k, **kw): -+ TaskGen.task_gen.__init__(self, *k, **kw) -+ -+@feature('cmd') -+def apply_cmd(self): -+ "call a command everytime" -+ if not self.fun: raise Utils.WafError('cmdobj needs a function!') -+ tsk = Task.TaskBase() -+ tsk.fun = self.fun -+ tsk.env = self.env -+ self.tasks.append(tsk) -+ tsk.install_path = self.install_path -+ -+class copy_taskgen(TaskGen.task_gen): -+ "By default, make a file copy, if fun is provided, fun will make the copy (or call a compiler, etc)" -+ def __init__(self, *k, **kw): -+ TaskGen.task_gen.__init__(self, *k, **kw) -+ -+@feature('copy') -+@before('apply_core') -+def apply_copy(self): -+ Utils.def_attrs(self, fun=copy_func) -+ self.default_install_path = 0 -+ -+ lst = self.to_list(self.source) -+ self.meths.remove('apply_core') -+ -+ for filename in lst: -+ node = self.path.find_resource(filename) -+ if not node: raise Utils.WafError('cannot find input file %s for processing' % filename) -+ -+ target = self.target -+ if not target or len(lst)>1: target = node.name -+ -+ # TODO the file path may be incorrect -+ newnode = self.path.find_or_declare(target) -+ -+ tsk = self.create_task('copy', node, newnode) -+ tsk.fun = self.fun -+ tsk.chmod = self.chmod -+ tsk.install_path = self.install_path -+ -+ if not tsk.env: -+ tsk.debug() -+ raise Utils.WafError('task without an environment') -+ -+def subst_func(tsk): -+ "Substitutes variables in a .in file" -+ -+ m4_re = re.compile('@(\w+)@', re.M) -+ -+ env = tsk.env -+ infile = tsk.inputs[0].abspath(env) -+ outfile = tsk.outputs[0].abspath(env) -+ -+ code = Utils.readf(infile) -+ -+ # replace all % by %% to prevent errors by % signs in the input file while string formatting -+ code = code.replace('%', '%%') -+ -+ s = m4_re.sub(r'%(\1)s', code) -+ -+ di = tsk.dict or {} -+ if not di: -+ names = m4_re.findall(code) -+ for i in names: -+ di[i] = env.get_flat(i) or env.get_flat(i.upper()) -+ -+ file = open(outfile, 'w') -+ file.write(s % di) -+ file.close() -+ if tsk.chmod: os.chmod(outfile, tsk.chmod) -+ -+class subst_taskgen(TaskGen.task_gen): -+ def __init__(self, *k, **kw): -+ TaskGen.task_gen.__init__(self, *k, **kw) -+ -+@feature('subst') -+@before('apply_core') -+def apply_subst(self): -+ Utils.def_attrs(self, fun=subst_func) -+ self.default_install_path = 0 -+ lst = self.to_list(self.source) -+ self.meths.remove('apply_core') -+ -+ self.dict = getattr(self, 'dict', {}) -+ -+ for filename in lst: -+ node = self.path.find_resource(filename) -+ if not node: raise Utils.WafError('cannot find input file %s for processing' % filename) -+ -+ if self.target: -+ newnode = self.path.find_or_declare(self.target) -+ else: -+ newnode = node.change_ext('') -+ -+ try: -+ self.dict = self.dict.get_merged_dict() -+ except AttributeError: -+ pass -+ -+ if self.dict and not self.env['DICT_HASH']: -+ self.env = self.env.copy() -+ keys = list(self.dict.keys()) -+ keys.sort() -+ lst = [self.dict[x] for x in keys] -+ self.env['DICT_HASH'] = str(Utils.h_list(lst)) -+ -+ tsk = self.create_task('copy', node, newnode) -+ tsk.fun = self.fun -+ tsk.dict = self.dict -+ tsk.dep_vars = ['DICT_HASH'] -+ tsk.install_path = self.install_path -+ tsk.chmod = self.chmod -+ -+ if not tsk.env: -+ tsk.debug() -+ raise Utils.WafError('task without an environment') -+ -+#################### -+## command-output #### -+#################### -+ -+class cmd_arg(object): -+ """command-output arguments for representing files or folders""" -+ def __init__(self, name, template='%s'): -+ self.name = name -+ self.template = template -+ self.node = None -+ -+class input_file(cmd_arg): -+ def find_node(self, base_path): -+ assert isinstance(base_path, Node.Node) -+ self.node = base_path.find_resource(self.name) -+ if self.node is None: -+ raise Utils.WafError("Input file %s not found in " % (self.name, base_path)) -+ -+ def get_path(self, env, absolute): -+ if absolute: -+ return self.template % self.node.abspath(env) -+ else: -+ return self.template % self.node.srcpath(env) -+ -+class output_file(cmd_arg): -+ def find_node(self, base_path): -+ assert isinstance(base_path, Node.Node) -+ self.node = base_path.find_or_declare(self.name) -+ if self.node is None: -+ raise Utils.WafError("Output file %s not found in " % (self.name, base_path)) -+ -+ def get_path(self, env, absolute): -+ if absolute: -+ return self.template % self.node.abspath(env) -+ else: -+ return self.template % self.node.bldpath(env) -+ -+class cmd_dir_arg(cmd_arg): -+ def find_node(self, base_path): -+ assert isinstance(base_path, Node.Node) -+ self.node = base_path.find_dir(self.name) -+ if self.node is None: -+ raise Utils.WafError("Directory %s not found in " % (self.name, base_path)) -+ -+class input_dir(cmd_dir_arg): -+ def get_path(self, dummy_env, dummy_absolute): -+ return self.template % self.node.abspath() -+ -+class output_dir(cmd_dir_arg): -+ def get_path(self, env, dummy_absolute): -+ return self.template % self.node.abspath(env) -+ -+ -+class command_output(Task.Task): -+ color = "BLUE" -+ def __init__(self, env, command, command_node, command_args, stdin, stdout, cwd, os_env, stderr): -+ Task.Task.__init__(self, env, normal=1) -+ assert isinstance(command, (str, Node.Node)) -+ self.command = command -+ self.command_args = command_args -+ self.stdin = stdin -+ self.stdout = stdout -+ self.cwd = cwd -+ self.os_env = os_env -+ self.stderr = stderr -+ -+ if command_node is not None: self.dep_nodes = [command_node] -+ self.dep_vars = [] # additional environment variables to look -+ -+ def run(self): -+ task = self -+ #assert len(task.inputs) > 0 -+ -+ def input_path(node, template): -+ if task.cwd is None: -+ return template % node.bldpath(task.env) -+ else: -+ return template % node.abspath() -+ def output_path(node, template): -+ fun = node.abspath -+ if task.cwd is None: fun = node.bldpath -+ return template % fun(task.env) -+ -+ if isinstance(task.command, Node.Node): -+ argv = [input_path(task.command, '%s')] -+ else: -+ argv = [task.command] -+ -+ for arg in task.command_args: -+ if isinstance(arg, str): -+ argv.append(arg) -+ else: -+ assert isinstance(arg, cmd_arg) -+ argv.append(arg.get_path(task.env, (task.cwd is not None))) -+ -+ if task.stdin: -+ stdin = open(input_path(task.stdin, '%s')) -+ else: -+ stdin = None -+ -+ if task.stdout: -+ stdout = open(output_path(task.stdout, '%s'), "w") -+ else: -+ stdout = None -+ -+ if task.stderr: -+ stderr = open(output_path(task.stderr, '%s'), "w") -+ else: -+ stderr = None -+ -+ if task.cwd is None: -+ cwd = ('None (actually %r)' % os.getcwd()) -+ else: -+ cwd = repr(task.cwd) -+ debug("command-output: cwd=%s, stdin=%r, stdout=%r, argv=%r" % -+ (cwd, stdin, stdout, argv)) -+ -+ if task.os_env is None: -+ os_env = os.environ -+ else: -+ os_env = task.os_env -+ command = Utils.pproc.Popen(argv, stdin=stdin, stdout=stdout, stderr=stderr, cwd=task.cwd, env=os_env) -+ return command.wait() -+ -+class cmd_output_taskgen(TaskGen.task_gen): -+ def __init__(self, *k, **kw): -+ TaskGen.task_gen.__init__(self, *k, **kw) -+ -+@feature('command-output') -+def init_cmd_output(self): -+ Utils.def_attrs(self, -+ stdin = None, -+ stdout = None, -+ stderr = None, -+ # the command to execute -+ command = None, -+ -+ # whether it is an external command; otherwise it is assumed -+ # to be an executable binary or script that lives in the -+ # source or build tree. -+ command_is_external = False, -+ -+ # extra parameters (argv) to pass to the command (excluding -+ # the command itself) -+ argv = [], -+ -+ # dependencies to other objects -> this is probably not what you want (ita) -+ # values must be 'task_gen' instances (not names!) -+ dependencies = [], -+ -+ # dependencies on env variable contents -+ dep_vars = [], -+ -+ # input files that are implicit, i.e. they are not -+ # stdin, nor are they mentioned explicitly in argv -+ hidden_inputs = [], -+ -+ # output files that are implicit, i.e. they are not -+ # stdout, nor are they mentioned explicitly in argv -+ hidden_outputs = [], -+ -+ # change the subprocess to this cwd (must use obj.input_dir() or output_dir() here) -+ cwd = None, -+ -+ # OS environment variables to pass to the subprocess -+ # if None, use the default environment variables unchanged -+ os_env = None) -+ -+@feature('command-output') -+@after('init_cmd_output') -+def apply_cmd_output(self): -+ if self.command is None: -+ raise Utils.WafError("command-output missing command") -+ if self.command_is_external: -+ cmd = self.command -+ cmd_node = None -+ else: -+ cmd_node = self.path.find_resource(self.command) -+ assert cmd_node is not None, ('''Could not find command '%s' in source tree. -+Hint: if this is an external command, -+use command_is_external=True''') % (self.command,) -+ cmd = cmd_node -+ -+ if self.cwd is None: -+ cwd = None -+ else: -+ assert isinstance(cwd, CmdDirArg) -+ self.cwd.find_node(self.path) -+ -+ args = [] -+ inputs = [] -+ outputs = [] -+ -+ for arg in self.argv: -+ if isinstance(arg, cmd_arg): -+ arg.find_node(self.path) -+ if isinstance(arg, input_file): -+ inputs.append(arg.node) -+ if isinstance(arg, output_file): -+ outputs.append(arg.node) -+ -+ if self.stdout is None: -+ stdout = None -+ else: -+ assert isinstance(self.stdout, str) -+ stdout = self.path.find_or_declare(self.stdout) -+ if stdout is None: -+ raise Utils.WafError("File %s not found" % (self.stdout,)) -+ outputs.append(stdout) -+ -+ if self.stderr is None: -+ stderr = None -+ else: -+ assert isinstance(self.stderr, str) -+ stderr = self.path.find_or_declare(self.stderr) -+ if stderr is None: -+ raise Utils.WafError("File %s not found" % (self.stderr,)) -+ outputs.append(stderr) -+ -+ if self.stdin is None: -+ stdin = None -+ else: -+ assert isinstance(self.stdin, str) -+ stdin = self.path.find_resource(self.stdin) -+ if stdin is None: -+ raise Utils.WafError("File %s not found" % (self.stdin,)) -+ inputs.append(stdin) -+ -+ for hidden_input in self.to_list(self.hidden_inputs): -+ node = self.path.find_resource(hidden_input) -+ if node is None: -+ raise Utils.WafError("File %s not found in dir %s" % (hidden_input, self.path)) -+ inputs.append(node) -+ -+ for hidden_output in self.to_list(self.hidden_outputs): -+ node = self.path.find_or_declare(hidden_output) -+ if node is None: -+ raise Utils.WafError("File %s not found in dir %s" % (hidden_output, self.path)) -+ outputs.append(node) -+ -+ if not (inputs or getattr(self, 'no_inputs', None)): -+ raise Utils.WafError('command-output objects must have at least one input file or give self.no_inputs') -+ if not (outputs or getattr(self, 'no_outputs', None)): -+ raise Utils.WafError('command-output objects must have at least one output file or give self.no_outputs') -+ -+ task = command_output(self.env, cmd, cmd_node, self.argv, stdin, stdout, cwd, self.os_env, stderr) -+ Utils.copy_attrs(self, task, 'before after ext_in ext_out', only_if_set=True) -+ self.tasks.append(task) -+ -+ task.inputs = inputs -+ task.outputs = outputs -+ task.dep_vars = self.to_list(self.dep_vars) -+ -+ for dep in self.dependencies: -+ assert dep is not self -+ dep.post() -+ for dep_task in dep.tasks: -+ task.set_run_after(dep_task) -+ -+ if not task.inputs: -+ # the case for svnversion, always run, and update the output nodes -+ task.runnable_status = type(Task.TaskBase.run)(runnable_status, task, task.__class__) # always run -+ task.post_run = type(Task.TaskBase.run)(post_run, task, task.__class__) -+ -+ # TODO the case with no outputs? -+ -+def post_run(self): -+ for x in self.outputs: -+ h = Utils.h_file(x.abspath(self.env)) -+ self.generator.bld.node_sigs[self.env.variant()][x.id] = h -+ -+def runnable_status(self): -+ return Constants.RUN_ME -+ -+Task.task_type_from_func('copy', vars=[], func=action_process_file_func) -+TaskGen.task_gen.classes['command-output'] = cmd_output_taskgen -+ -diff --git a/buildtools/wafadmin/Tools/msvc.py b/buildtools/wafadmin/Tools/msvc.py -new file mode 100644 -index 0000000..4fde8b1 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/msvc.py -@@ -0,0 +1,797 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Carlos Rafael Giani, 2006 (dv) -+# Tamas Pal, 2007 (folti) -+# Nicolas Mercier, 2009 -+# Microsoft Visual C++/Intel C++ compiler support - beta, needs more testing -+ -+# usage: -+# -+# conf.env['MSVC_VERSIONS'] = ['msvc 9.0', 'msvc 8.0', 'wsdk 7.0', 'intel 11', 'PocketPC 9.0', 'Smartphone 8.0'] -+# conf.env['MSVC_TARGETS'] = ['x64'] -+# conf.check_tool('msvc') -+# OR conf.check_tool('msvc', funs='no_autodetect') -+# conf.check_lib_msvc('gdi32') -+# conf.check_libs_msvc('kernel32 user32', mandatory=true) -+# ... -+# obj.uselib = 'KERNEL32 USER32 GDI32' -+# -+# platforms and targets will be tested in the order they appear; -+# the first good configuration will be used -+# supported platforms : -+# ia64, x64, x86, x86_amd64, x86_ia64 -+ -+# compilers supported : -+# msvc => Visual Studio, versions 7.1 (2003), 8,0 (2005), 9.0 (2008) -+# wsdk => Windows SDK, versions 6.0, 6.1, 7.0 -+# icl => Intel compiler, versions 9,10,11 -+# Smartphone => Compiler/SDK for Smartphone devices (armv4/v4i) -+# PocketPC => Compiler/SDK for PocketPC devices (armv4/v4i) -+ -+ -+import os, sys, re, string, optparse -+import Utils, TaskGen, Runner, Configure, Task, Options -+from Logs import debug, info, warn, error -+from TaskGen import after, before, feature -+ -+from Configure import conftest, conf -+import ccroot, cc, cxx, ar, winres -+from libtool import read_la_file -+ -+try: -+ import _winreg -+except: -+ import winreg as _winreg -+ -+pproc = Utils.pproc -+ -+# importlibs provided by MSVC/Platform SDK. Do NOT search them.... -+g_msvc_systemlibs = """ -+aclui activeds ad1 adptif adsiid advapi32 asycfilt authz bhsupp bits bufferoverflowu cabinet -+cap certadm certidl ciuuid clusapi comctl32 comdlg32 comsupp comsuppd comsuppw comsuppwd comsvcs -+credui crypt32 cryptnet cryptui d3d8thk daouuid dbgeng dbghelp dciman32 ddao35 ddao35d -+ddao35u ddao35ud delayimp dhcpcsvc dhcpsapi dlcapi dnsapi dsprop dsuiext dtchelp -+faultrep fcachdll fci fdi framedyd framedyn gdi32 gdiplus glauxglu32 gpedit gpmuuid -+gtrts32w gtrtst32hlink htmlhelp httpapi icm32 icmui imagehlp imm32 iphlpapi iprop -+kernel32 ksguid ksproxy ksuser libcmt libcmtd libcpmt libcpmtd loadperf lz32 mapi -+mapi32 mgmtapi minidump mmc mobsync mpr mprapi mqoa mqrt msacm32 mscms mscoree -+msdasc msimg32 msrating mstask msvcmrt msvcurt msvcurtd mswsock msxml2 mtx mtxdm -+netapi32 nmapinmsupp npptools ntdsapi ntdsbcli ntmsapi ntquery odbc32 odbcbcp -+odbccp32 oldnames ole32 oleacc oleaut32 oledb oledlgolepro32 opends60 opengl32 -+osptk parser pdh penter pgobootrun pgort powrprof psapi ptrustm ptrustmd ptrustu -+ptrustud qosname rasapi32 rasdlg rassapi resutils riched20 rpcndr rpcns4 rpcrt4 rtm -+rtutils runtmchk scarddlg scrnsave scrnsavw secur32 sensapi setupapi sfc shell32 -+shfolder shlwapi sisbkup snmpapi sporder srclient sti strsafe svcguid tapi32 thunk32 -+traffic unicows url urlmon user32 userenv usp10 uuid uxtheme vcomp vcompd vdmdbg -+version vfw32 wbemuuid webpost wiaguid wininet winmm winscard winspool winstrm -+wintrust wldap32 wmiutils wow32 ws2_32 wsnmp32 wsock32 wst wtsapi32 xaswitch xolehlp -+""".split() -+ -+ -+all_msvc_platforms = [ ('x64', 'amd64'), ('x86', 'x86'), ('ia64', 'ia64'), ('x86_amd64', 'amd64'), ('x86_ia64', 'ia64') ] -+all_wince_platforms = [ ('armv4', 'arm'), ('armv4i', 'arm'), ('mipsii', 'mips'), ('mipsii_fp', 'mips'), ('mipsiv', 'mips'), ('mipsiv_fp', 'mips'), ('sh4', 'sh'), ('x86', 'cex86') ] -+all_icl_platforms = [ ('intel64', 'amd64'), ('em64t', 'amd64'), ('ia32', 'x86'), ('Itanium', 'ia64')] -+ -+def setup_msvc(conf, versions): -+ platforms = Utils.to_list(conf.env['MSVC_TARGETS']) or [i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms] -+ desired_versions = conf.env['MSVC_VERSIONS'] or [v for v,_ in versions][::-1] -+ versiondict = dict(versions) -+ -+ for version in desired_versions: -+ try: -+ targets = dict(versiondict [version]) -+ for target in platforms: -+ try: -+ arch,(p1,p2,p3) = targets[target] -+ compiler,revision = version.split() -+ return compiler,revision,p1,p2,p3 -+ except KeyError: continue -+ except KeyError: continue -+ conf.fatal('msvc: Impossible to find a valid architecture for building (in setup_msvc)') -+ -+@conf -+def get_msvc_version(conf, compiler, version, target, vcvars): -+ debug('msvc: get_msvc_version: %r %r %r', compiler, version, target) -+ batfile = os.path.join(conf.blddir, 'waf-print-msvc.bat') -+ f = open(batfile, 'w') -+ f.write("""@echo off -+set INCLUDE= -+set LIB= -+call "%s" %s -+echo PATH=%%PATH%% -+echo INCLUDE=%%INCLUDE%% -+echo LIB=%%LIB%% -+""" % (vcvars,target)) -+ f.close() -+ sout = Utils.cmd_output(['cmd', '/E:on', '/V:on', '/C', batfile]) -+ lines = sout.splitlines() -+ -+ for x in ('Setting environment', 'Setting SDK environment', 'Intel(R) C++ Compiler'): -+ if lines[0].find(x) != -1: -+ break -+ else: -+ debug('msvc: get_msvc_version: %r %r %r -> not found', compiler, version, target) -+ conf.fatal('msvc: Impossible to find a valid architecture for building (in get_msvc_version)') -+ -+ for line in lines[1:]: -+ if line.startswith('PATH='): -+ path = line[5:] -+ MSVC_PATH = path.split(';') -+ elif line.startswith('INCLUDE='): -+ MSVC_INCDIR = [i for i in line[8:].split(';') if i] -+ elif line.startswith('LIB='): -+ MSVC_LIBDIR = [i for i in line[4:].split(';') if i] -+ -+ # Check if the compiler is usable at all. -+ # The detection may return 64-bit versions even on 32-bit systems, and these would fail to run. -+ env = {} -+ env.update(os.environ) -+ env.update(PATH = path) -+ compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) -+ cxx = conf.find_program(compiler_name, path_list=MSVC_PATH) -+ # delete CL if exists. because it could contain parameters wich can change cl's behaviour rather catastrophically. -+ if env.has_key('CL'): -+ del(env['CL']) -+ -+ try: -+ p = pproc.Popen([cxx, '/help'], env=env, stdout=pproc.PIPE, stderr=pproc.PIPE) -+ out, err = p.communicate() -+ if p.returncode != 0: -+ raise Exception('return code: %r: %r' % (p.returncode, err)) -+ except Exception, e: -+ debug('msvc: get_msvc_version: %r %r %r -> failure', compiler, version, target) -+ debug(str(e)) -+ conf.fatal('msvc: cannot run the compiler (in get_msvc_version)') -+ else: -+ debug('msvc: get_msvc_version: %r %r %r -> OK', compiler, version, target) -+ -+ return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR) -+ -+@conf -+def gather_wsdk_versions(conf, versions): -+ version_pattern = re.compile('^v..?.?\...?.?') -+ try: -+ all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows') -+ except WindowsError: -+ try: -+ all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows') -+ except WindowsError: -+ return -+ index = 0 -+ while 1: -+ try: -+ version = _winreg.EnumKey(all_versions, index) -+ except WindowsError: -+ break -+ index = index + 1 -+ if not version_pattern.match(version): -+ continue -+ try: -+ msvc_version = _winreg.OpenKey(all_versions, version) -+ path,type = _winreg.QueryValueEx(msvc_version,'InstallationFolder') -+ except WindowsError: -+ continue -+ if os.path.isfile(os.path.join(path, 'bin', 'SetEnv.cmd')): -+ targets = [] -+ for target,arch in all_msvc_platforms: -+ try: -+ targets.append((target, (arch, conf.get_msvc_version('wsdk', version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd'))))) -+ except Configure.ConfigurationError: -+ pass -+ versions.append(('wsdk ' + version[1:], targets)) -+ -+@conf -+def gather_msvc_versions(conf, versions): -+ # checks SmartPhones SDKs -+ try: -+ ce_sdk = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs') -+ except WindowsError: -+ try: -+ ce_sdk = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs') -+ except WindowsError: -+ ce_sdk = '' -+ if ce_sdk: -+ supported_wince_platforms = [] -+ ce_index = 0 -+ while 1: -+ try: -+ sdk_device = _winreg.EnumKey(ce_sdk, ce_index) -+ except WindowsError: -+ break -+ ce_index = ce_index + 1 -+ sdk = _winreg.OpenKey(ce_sdk, sdk_device) -+ path,type = _winreg.QueryValueEx(sdk, 'SDKRootDir') -+ path=str(path) -+ path,device = os.path.split(path) -+ if not device: -+ path,device = os.path.split(path) -+ for arch,compiler in all_wince_platforms: -+ platforms = [] -+ if os.path.isdir(os.path.join(path, device, 'Lib', arch)): -+ platforms.append((arch, compiler, os.path.join(path, device, 'Include', arch), os.path.join(path, device, 'Lib', arch))) -+ if platforms: -+ supported_wince_platforms.append((device, platforms)) -+ # checks MSVC -+ version_pattern = re.compile('^..?\...?') -+ for vcver,vcvar in [('VCExpress','exp'), ('VisualStudio','')]: -+ try: -+ all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\'+vcver) -+ except WindowsError: -+ try: -+ all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\'+vcver) -+ except WindowsError: -+ continue -+ index = 0 -+ while 1: -+ try: -+ version = _winreg.EnumKey(all_versions, index) -+ except WindowsError: -+ break -+ index = index + 1 -+ if not version_pattern.match(version): -+ continue -+ try: -+ msvc_version = _winreg.OpenKey(all_versions, version + "\\Setup\\VS") -+ path,type = _winreg.QueryValueEx(msvc_version, 'ProductDir') -+ path=str(path) -+ targets = [] -+ if ce_sdk: -+ for device,platforms in supported_wince_platforms: -+ cetargets = [] -+ for platform,compiler,include,lib in platforms: -+ winCEpath = os.path.join(path, 'VC', 'ce') -+ if os.path.isdir(winCEpath): -+ common_bindirs,_1,_2 = conf.get_msvc_version('msvc', version, 'x86', os.path.join(path, 'Common7', 'Tools', 'vsvars32.bat')) -+ if os.path.isdir(os.path.join(winCEpath, 'lib', platform)): -+ bindirs = [os.path.join(winCEpath, 'bin', compiler), os.path.join(winCEpath, 'bin', 'x86_'+compiler)] + common_bindirs -+ incdirs = [include, os.path.join(winCEpath, 'include'), os.path.join(winCEpath, 'atlmfc', 'include')] -+ libdirs = [lib, os.path.join(winCEpath, 'lib', platform), os.path.join(winCEpath, 'atlmfc', 'lib', platform)] -+ cetargets.append((platform, (platform, (bindirs,incdirs,libdirs)))) -+ versions.append((device+' '+version, cetargets)) -+ if os.path.isfile(os.path.join(path, 'VC', 'vcvarsall.bat')): -+ for target,realtarget in all_msvc_platforms[::-1]: -+ try: -+ targets.append((target, (realtarget, conf.get_msvc_version('msvc', version, target, os.path.join(path, 'VC', 'vcvarsall.bat'))))) -+ except: -+ pass -+ elif os.path.isfile(os.path.join(path, 'Common7', 'Tools', 'vsvars32.bat')): -+ try: -+ targets.append(('x86', ('x86', conf.get_msvc_version('msvc', version, 'x86', os.path.join(path, 'Common7', 'Tools', 'vsvars32.bat'))))) -+ except Configure.ConfigurationError: -+ pass -+ versions.append(('msvc '+version, targets)) -+ -+ except WindowsError: -+ continue -+ -+@conf -+def gather_icl_versions(conf, versions): -+ version_pattern = re.compile('^...?.?\....?.?') -+ try: -+ all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++') -+ except WindowsError: -+ try: -+ all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Compilers\\C++') -+ except WindowsError: -+ return -+ index = 0 -+ while 1: -+ try: -+ version = _winreg.EnumKey(all_versions, index) -+ except WindowsError: -+ break -+ index = index + 1 -+ if not version_pattern.match(version): -+ continue -+ targets = [] -+ for target,arch in all_icl_platforms: -+ try: -+ icl_version = _winreg.OpenKey(all_versions, version+'\\'+target) -+ path,type = _winreg.QueryValueEx(icl_version,'ProductDir') -+ if os.path.isfile(os.path.join(path, 'bin', 'iclvars.bat')): -+ try: -+ targets.append((target, (arch, conf.get_msvc_version('intel', version, target, os.path.join(path, 'bin', 'iclvars.bat'))))) -+ except Configure.ConfigurationError: -+ pass -+ except WindowsError: -+ continue -+ major = version[0:2] -+ versions.append(('intel ' + major, targets)) -+ -+@conf -+def get_msvc_versions(conf): -+ if not conf.env.MSVC_INSTALLED_VERSIONS: -+ lst = [] -+ conf.gather_msvc_versions(lst) -+ conf.gather_wsdk_versions(lst) -+ conf.gather_icl_versions(lst) -+ conf.env.MSVC_INSTALLED_VERSIONS = lst -+ return conf.env.MSVC_INSTALLED_VERSIONS -+ -+@conf -+def print_all_msvc_detected(conf): -+ for version,targets in conf.env['MSVC_INSTALLED_VERSIONS']: -+ info(version) -+ for target,l in targets: -+ info("\t"+target) -+ -+def detect_msvc(conf): -+ versions = get_msvc_versions(conf) -+ return setup_msvc(conf, versions) -+ -+@conf -+def find_lt_names_msvc(self, libname, is_static=False): -+ """ -+ Win32/MSVC specific code to glean out information from libtool la files. -+ this function is not attached to the task_gen class -+ """ -+ lt_names=[ -+ 'lib%s.la' % libname, -+ '%s.la' % libname, -+ ] -+ -+ for path in self.env['LIBPATH']: -+ for la in lt_names: -+ laf=os.path.join(path,la) -+ dll=None -+ if os.path.exists(laf): -+ ltdict=read_la_file(laf) -+ lt_libdir=None -+ if ltdict.get('libdir', ''): -+ lt_libdir = ltdict['libdir'] -+ if not is_static and ltdict.get('library_names', ''): -+ dllnames=ltdict['library_names'].split() -+ dll=dllnames[0].lower() -+ dll=re.sub('\.dll$', '', dll) -+ return (lt_libdir, dll, False) -+ elif ltdict.get('old_library', ''): -+ olib=ltdict['old_library'] -+ if os.path.exists(os.path.join(path,olib)): -+ return (path, olib, True) -+ elif lt_libdir != '' and os.path.exists(os.path.join(lt_libdir,olib)): -+ return (lt_libdir, olib, True) -+ else: -+ return (None, olib, True) -+ else: -+ raise Utils.WafError('invalid libtool object file: %s' % laf) -+ return (None, None, None) -+ -+@conf -+def libname_msvc(self, libname, is_static=False, mandatory=False): -+ lib = libname.lower() -+ lib = re.sub('\.lib$','',lib) -+ -+ if lib in g_msvc_systemlibs: -+ return lib -+ -+ lib=re.sub('^lib','',lib) -+ -+ if lib == 'm': -+ return None -+ -+ (lt_path, lt_libname, lt_static) = self.find_lt_names_msvc(lib, is_static) -+ -+ if lt_path != None and lt_libname != None: -+ if lt_static == True: -+ # file existance check has been made by find_lt_names -+ return os.path.join(lt_path,lt_libname) -+ -+ if lt_path != None: -+ _libpaths=[lt_path] + self.env['LIBPATH'] -+ else: -+ _libpaths=self.env['LIBPATH'] -+ -+ static_libs=[ -+ 'lib%ss.lib' % lib, -+ 'lib%s.lib' % lib, -+ '%ss.lib' % lib, -+ '%s.lib' %lib, -+ ] -+ -+ dynamic_libs=[ -+ 'lib%s.dll.lib' % lib, -+ 'lib%s.dll.a' % lib, -+ '%s.dll.lib' % lib, -+ '%s.dll.a' % lib, -+ 'lib%s_d.lib' % lib, -+ '%s_d.lib' % lib, -+ '%s.lib' %lib, -+ ] -+ -+ libnames=static_libs -+ if not is_static: -+ libnames=dynamic_libs + static_libs -+ -+ for path in _libpaths: -+ for libn in libnames: -+ if os.path.exists(os.path.join(path, libn)): -+ debug('msvc: lib found: %s', os.path.join(path,libn)) -+ return re.sub('\.lib$', '',libn) -+ -+ #if no lib can be found, just return the libname as msvc expects it -+ if mandatory: -+ self.fatal("The library %r could not be found" % libname) -+ return re.sub('\.lib$', '', libname) -+ -+@conf -+def check_lib_msvc(self, libname, is_static=False, uselib_store=None, mandatory=False): -+ "This is the api to use" -+ libn = self.libname_msvc(libname, is_static, mandatory) -+ -+ if not uselib_store: -+ uselib_store = libname.upper() -+ -+ # Note: ideally we should be able to place the lib in the right env var, either STATICLIB or LIB, -+ # but we don't distinguish static libs from shared libs. -+ # This is ok since msvc doesn't have any special linker flag to select static libs (no env['STATICLIB_MARKER']) -+ if False and is_static: # disabled -+ self.env['STATICLIB_' + uselib_store] = [libn] -+ else: -+ self.env['LIB_' + uselib_store] = [libn] -+ -+@conf -+def check_libs_msvc(self, libnames, is_static=False, mandatory=False): -+ for libname in Utils.to_list(libnames): -+ self.check_lib_msvc(libname, is_static, mandatory=mandatory) -+ -+@conftest -+def no_autodetect(conf): -+ conf.eval_rules(detect.replace('autodetect', '')) -+ -+ -+detect = ''' -+autodetect -+find_msvc -+msvc_common_flags -+cc_load_tools -+cxx_load_tools -+cc_add_flags -+cxx_add_flags -+link_add_flags -+''' -+ -+@conftest -+def autodetect(conf): -+ v = conf.env -+ compiler, version, path, includes, libdirs = detect_msvc(conf) -+ v['PATH'] = path -+ v['CPPPATH'] = includes -+ v['LIBPATH'] = libdirs -+ v['MSVC_COMPILER'] = compiler -+ -+def _get_prog_names(conf, compiler): -+ if compiler=='intel': -+ compiler_name = 'ICL' -+ linker_name = 'XILINK' -+ lib_name = 'XILIB' -+ else: -+ # assumes CL.exe -+ compiler_name = 'CL' -+ linker_name = 'LINK' -+ lib_name = 'LIB' -+ return compiler_name, linker_name, lib_name -+ -+@conftest -+def find_msvc(conf): -+ # due to path format limitations, limit operation only to native Win32. Yeah it sucks. -+ if sys.platform != 'win32': -+ conf.fatal('MSVC module only works under native Win32 Python! cygwin is not supported yet') -+ -+ v = conf.env -+ -+ compiler, version, path, includes, libdirs = detect_msvc(conf) -+ -+ compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) -+ has_msvc_manifest = (compiler == 'msvc' and float(version) >= 8) or (compiler == 'wsdk' and float(version) >= 6) or (compiler == 'intel' and float(version) >= 11) -+ -+ # compiler -+ cxx = None -+ if v.CXX: cxx = v.CXX -+ elif 'CXX' in conf.environ: cxx = conf.environ['CXX'] -+ if not cxx: cxx = conf.find_program(compiler_name, var='CXX', path_list=path, mandatory=True) -+ cxx = conf.cmd_to_list(cxx) -+ -+ # before setting anything, check if the compiler is really msvc -+ env = dict(conf.environ) -+ env.update(PATH = ';'.join(path)) -+ if not Utils.cmd_output([cxx, '/nologo', '/?'], silent=True, env=env): -+ conf.fatal('the msvc compiler could not be identified') -+ -+ link = v.LINK_CXX -+ if not link: -+ link = conf.find_program(linker_name, path_list=path, mandatory=True) -+ ar = v.AR -+ if not ar: -+ ar = conf.find_program(lib_name, path_list=path, mandatory=True) -+ -+ # manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later -+ mt = v.MT -+ if has_msvc_manifest: -+ mt = conf.find_program('MT', path_list=path, mandatory=True) -+ -+ # no more possibility of failure means the data state will be consistent -+ # we may store the data safely now -+ -+ v.MSVC_MANIFEST = has_msvc_manifest -+ v.PATH = path -+ v.CPPPATH = includes -+ v.LIBPATH = libdirs -+ -+ # c/c++ compiler -+ v.CC = v.CXX = cxx -+ v.CC_NAME = v.CXX_NAME = 'msvc' -+ -+ v.LINK = v.LINK_CXX = link -+ if not v.LINK_CC: -+ v.LINK_CC = v.LINK_CXX -+ -+ v.AR = ar -+ v.MT = mt -+ v.MTFLAGS = v.ARFLAGS = ['/NOLOGO'] -+ -+ -+ conf.check_tool('winres') -+ -+ if not conf.env.WINRC: -+ warn('Resource compiler not found. Compiling resource file is disabled') -+ -+ # environment flags -+ try: v.prepend_value('CPPPATH', conf.environ['INCLUDE']) -+ except KeyError: pass -+ try: v.prepend_value('LIBPATH', conf.environ['LIB']) -+ except KeyError: pass -+ -+@conftest -+def msvc_common_flags(conf): -+ v = conf.env -+ -+ v['CPPFLAGS'] = ['/W3', '/nologo'] -+ -+ v['CCDEFINES_ST'] = '/D%s' -+ v['CXXDEFINES_ST'] = '/D%s' -+ -+ # TODO just use _WIN32, which defined by the compiler itself! -+ v['CCDEFINES'] = ['WIN32'] # avoid using this, any compiler predefines the _WIN32 marcro anyway -+ v['CXXDEFINES'] = ['WIN32'] # avoid using this, any compiler predefines the _WIN32 marcro anyway -+ -+ v['_CCINCFLAGS'] = [] -+ v['_CCDEFFLAGS'] = [] -+ v['_CXXINCFLAGS'] = [] -+ v['_CXXDEFFLAGS'] = [] -+ -+ v['CC_SRC_F'] = '' -+ v['CC_TGT_F'] = ['/c', '/Fo'] -+ v['CXX_SRC_F'] = '' -+ v['CXX_TGT_F'] = ['/c', '/Fo'] -+ -+ v['CPPPATH_ST'] = '/I%s' # template for adding include paths -+ -+ v['AR_TGT_F'] = v['CCLNK_TGT_F'] = v['CXXLNK_TGT_F'] = '/OUT:' -+ -+ # Subsystem specific flags -+ v['CPPFLAGS_CONSOLE'] = ['/SUBSYSTEM:CONSOLE'] -+ v['CPPFLAGS_NATIVE'] = ['/SUBSYSTEM:NATIVE'] -+ v['CPPFLAGS_POSIX'] = ['/SUBSYSTEM:POSIX'] -+ v['CPPFLAGS_WINDOWS'] = ['/SUBSYSTEM:WINDOWS'] -+ v['CPPFLAGS_WINDOWSCE'] = ['/SUBSYSTEM:WINDOWSCE'] -+ -+ # CRT specific flags -+ v['CPPFLAGS_CRT_MULTITHREADED'] = ['/MT'] -+ v['CPPFLAGS_CRT_MULTITHREADED_DLL'] = ['/MD'] -+ -+ # TODO these are defined by the compiler itself! -+ v['CPPDEFINES_CRT_MULTITHREADED'] = ['_MT'] # this is defined by the compiler itself! -+ v['CPPDEFINES_CRT_MULTITHREADED_DLL'] = ['_MT', '_DLL'] # these are defined by the compiler itself! -+ -+ v['CPPFLAGS_CRT_MULTITHREADED_DBG'] = ['/MTd'] -+ v['CPPFLAGS_CRT_MULTITHREADED_DLL_DBG'] = ['/MDd'] -+ -+ # TODO these are defined by the compiler itself! -+ v['CPPDEFINES_CRT_MULTITHREADED_DBG'] = ['_DEBUG', '_MT'] # these are defined by the compiler itself! -+ v['CPPDEFINES_CRT_MULTITHREADED_DLL_DBG'] = ['_DEBUG', '_MT', '_DLL'] # these are defined by the compiler itself! -+ -+ # compiler debug levels -+ v['CCFLAGS'] = ['/TC'] -+ v['CCFLAGS_OPTIMIZED'] = ['/O2', '/DNDEBUG'] -+ v['CCFLAGS_RELEASE'] = ['/O2', '/DNDEBUG'] -+ v['CCFLAGS_DEBUG'] = ['/Od', '/RTC1', '/ZI'] -+ v['CCFLAGS_ULTRADEBUG'] = ['/Od', '/RTC1', '/ZI'] -+ -+ v['CXXFLAGS'] = ['/TP', '/EHsc'] -+ v['CXXFLAGS_OPTIMIZED'] = ['/O2', '/DNDEBUG'] -+ v['CXXFLAGS_RELEASE'] = ['/O2', '/DNDEBUG'] -+ -+ v['CXXFLAGS_DEBUG'] = ['/Od', '/RTC1', '/ZI'] -+ v['CXXFLAGS_ULTRADEBUG'] = ['/Od', '/RTC1', '/ZI'] -+ -+ # linker -+ v['LIB'] = [] -+ -+ v['LIB_ST'] = '%s.lib' # template for adding libs -+ v['LIBPATH_ST'] = '/LIBPATH:%s' # template for adding libpaths -+ v['STATICLIB_ST'] = 'lib%s.lib' # Note: to be able to distinguish between a static lib and a dll import lib, it's a good pratice to name the static lib 'lib%s.lib' and the dll import lib '%s.lib' -+ v['STATICLIBPATH_ST'] = '/LIBPATH:%s' -+ -+ v['LINKFLAGS'] = ['/NOLOGO'] -+ if v['MSVC_MANIFEST']: -+ v.append_value('LINKFLAGS', '/MANIFEST') -+ v['LINKFLAGS_DEBUG'] = ['/DEBUG'] -+ v['LINKFLAGS_ULTRADEBUG'] = ['/DEBUG'] -+ -+ # shared library -+ v['shlib_CCFLAGS'] = [''] -+ v['shlib_CXXFLAGS'] = [''] -+ v['shlib_LINKFLAGS']= ['/DLL'] -+ v['shlib_PATTERN'] = '%s.dll' -+ v['implib_PATTERN'] = '%s.lib' -+ v['IMPLIB_ST'] = '/IMPLIB:%s' -+ -+ # static library -+ v['staticlib_LINKFLAGS'] = [''] -+ v['staticlib_PATTERN'] = 'lib%s.lib' # Note: to be able to distinguish between a static lib and a dll import lib, it's a good pratice to name the static lib 'lib%s.lib' and the dll import lib '%s.lib' -+ -+ # program -+ v['program_PATTERN'] = '%s.exe' -+ -+ -+####################################################################################################### -+##### conf above, build below -+ -+@after('apply_link') -+@feature('cc', 'cxx') -+def apply_flags_msvc(self): -+ if self.env.CC_NAME != 'msvc' or not self.link_task: -+ return -+ -+ subsystem = getattr(self, 'subsystem', '') -+ if subsystem: -+ subsystem = '/subsystem:%s' % subsystem -+ flags = 'cstaticlib' in self.features and 'ARFLAGS' or 'LINKFLAGS' -+ self.env.append_value(flags, subsystem) -+ -+ if getattr(self, 'link_task', None) and not 'cstaticlib' in self.features: -+ for f in self.env.LINKFLAGS: -+ d = f.lower() -+ if d[1:] == 'debug': -+ pdbnode = self.link_task.outputs[0].change_ext('.pdb') -+ pdbfile = pdbnode.bldpath(self.env) -+ self.link_task.outputs.append(pdbnode) -+ self.bld.install_files(self.install_path, [pdbnode], env=self.env) -+ break -+ -+@feature('cprogram', 'cshlib', 'cstaticlib') -+@after('apply_lib_vars') -+@before('apply_obj_vars') -+def apply_obj_vars_msvc(self): -+ if self.env['CC_NAME'] != 'msvc': -+ return -+ -+ try: -+ self.meths.remove('apply_obj_vars') -+ except ValueError: -+ pass -+ -+ libpaths = getattr(self, 'libpaths', []) -+ if not libpaths: self.libpaths = libpaths -+ -+ env = self.env -+ app = env.append_unique -+ -+ cpppath_st = env['CPPPATH_ST'] -+ lib_st = env['LIB_ST'] -+ staticlib_st = env['STATICLIB_ST'] -+ libpath_st = env['LIBPATH_ST'] -+ staticlibpath_st = env['STATICLIBPATH_ST'] -+ -+ for i in env['LIBPATH']: -+ app('LINKFLAGS', libpath_st % i) -+ if not libpaths.count(i): -+ libpaths.append(i) -+ -+ for i in env['LIBPATH']: -+ app('LINKFLAGS', staticlibpath_st % i) -+ if not libpaths.count(i): -+ libpaths.append(i) -+ -+ # i doubt that anyone will make a fully static binary anyway -+ if not env['FULLSTATIC']: -+ if env['STATICLIB'] or env['LIB']: -+ app('LINKFLAGS', env['SHLIB_MARKER']) # TODO does SHLIB_MARKER work? -+ -+ for i in env['STATICLIB']: -+ app('LINKFLAGS', staticlib_st % i) -+ -+ for i in env['LIB']: -+ app('LINKFLAGS', lib_st % i) -+ -+# split the manifest file processing from the link task, like for the rc processing -+ -+@feature('cprogram', 'cshlib') -+@after('apply_link') -+def apply_manifest(self): -+ """Special linker for MSVC with support for embedding manifests into DLL's -+ and executables compiled by Visual Studio 2005 or probably later. Without -+ the manifest file, the binaries are unusable. -+ See: http://msdn2.microsoft.com/en-us/library/ms235542(VS.80).aspx""" -+ -+ if self.env.CC_NAME == 'msvc' and self.env.MSVC_MANIFEST: -+ out_node = self.link_task.outputs[0] -+ man_node = out_node.parent.find_or_declare(out_node.name + '.manifest') -+ self.link_task.outputs.append(man_node) -+ self.link_task.do_manifest = True -+ -+def exec_mf(self): -+ env = self.env -+ mtool = env['MT'] -+ if not mtool: -+ return 0 -+ -+ self.do_manifest = False -+ -+ outfile = self.outputs[0].bldpath(env) -+ -+ manifest = None -+ for out_node in self.outputs: -+ if out_node.name.endswith('.manifest'): -+ manifest = out_node.bldpath(env) -+ break -+ if manifest is None: -+ # Should never get here. If we do, it means the manifest file was -+ # never added to the outputs list, thus we don't have a manifest file -+ # to embed, so we just return. -+ return 0 -+ -+ # embedding mode. Different for EXE's and DLL's. -+ # see: http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx -+ mode = '' -+ if 'cprogram' in self.generator.features: -+ mode = '1' -+ elif 'cshlib' in self.generator.features: -+ mode = '2' -+ -+ debug('msvc: embedding manifest') -+ #flags = ' '.join(env['MTFLAGS'] or []) -+ -+ lst = [] -+ lst.extend([env['MT']]) -+ lst.extend(Utils.to_list(env['MTFLAGS'])) -+ lst.extend(Utils.to_list("-manifest")) -+ lst.extend(Utils.to_list(manifest)) -+ lst.extend(Utils.to_list("-outputresource:%s;%s" % (outfile, mode))) -+ -+ #cmd='%s %s -manifest "%s" -outputresource:"%s";#%s' % (mtool, flags, -+ # manifest, outfile, mode) -+ lst = [lst] -+ return self.exec_command(*lst) -+ -+########## stupid evil command modification: concatenate the tokens /Fx, /doc, and /x: with the next token -+ -+def exec_command_msvc(self, *k, **kw): -+ "instead of quoting all the paths and keep using the shell, we can just join the options msvc is interested in" -+ if self.env['CC_NAME'] == 'msvc': -+ if isinstance(k[0], list): -+ lst = [] -+ carry = '' -+ for a in k[0]: -+ if len(a) == 3 and a.startswith('/F') or a == '/doc' or a[-1] == ':': -+ carry = a -+ else: -+ lst.append(carry + a) -+ carry = '' -+ k = [lst] -+ -+ env = dict(os.environ) -+ env.update(PATH = ';'.join(self.env['PATH'])) -+ kw['env'] = env -+ -+ ret = self.generator.bld.exec_command(*k, **kw) -+ if ret: return ret -+ if getattr(self, 'do_manifest', None): -+ ret = exec_mf(self) -+ return ret -+ -+for k in 'cc cxx winrc cc_link cxx_link static_link qxx'.split(): -+ cls = Task.TaskBase.classes.get(k, None) -+ if cls: -+ cls.exec_command = exec_command_msvc -+ -diff --git a/buildtools/wafadmin/Tools/nasm.py b/buildtools/wafadmin/Tools/nasm.py -new file mode 100644 -index 0000000..b99c3c7 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/nasm.py -@@ -0,0 +1,49 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2008 -+ -+""" -+Nasm processing -+""" -+ -+import os -+import TaskGen, Task, Utils -+from TaskGen import taskgen, before, extension -+ -+nasm_str = '${NASM} ${NASM_FLAGS} ${NASM_INCLUDES} ${SRC} -o ${TGT}' -+ -+EXT_NASM = ['.s', '.S', '.asm', '.ASM', '.spp', '.SPP'] -+ -+@before('apply_link') -+def apply_nasm_vars(self): -+ -+ # flags -+ if hasattr(self, 'nasm_flags'): -+ for flag in self.to_list(self.nasm_flags): -+ self.env.append_value('NASM_FLAGS', flag) -+ -+ # includes - well, if we suppose it works with c processing -+ if hasattr(self, 'includes'): -+ for inc in self.to_list(self.includes): -+ node = self.path.find_dir(inc) -+ if not node: -+ raise Utils.WafError('cannot find the dir' + inc) -+ self.env.append_value('NASM_INCLUDES', '-I%s' % node.srcpath(self.env)) -+ self.env.append_value('NASM_INCLUDES', '-I%s' % node.bldpath(self.env)) -+ -+@extension(EXT_NASM) -+def nasm_file(self, node): -+ try: obj_ext = self.obj_ext -+ except AttributeError: obj_ext = '_%d.o' % self.idx -+ -+ task = self.create_task('nasm', node, node.change_ext(obj_ext)) -+ self.compiled_tasks.append(task) -+ -+ self.meths.append('apply_nasm_vars') -+ -+# create our action here -+Task.simple_task_type('nasm', nasm_str, color='BLUE', ext_out='.o', shell=False) -+ -+def detect(conf): -+ nasm = conf.find_program(['nasm', 'yasm'], var='NASM', mandatory=True) -+ -diff --git a/buildtools/wafadmin/Tools/ocaml.py b/buildtools/wafadmin/Tools/ocaml.py -new file mode 100644 -index 0000000..20c9269 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/ocaml.py -@@ -0,0 +1,298 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006 (ita) -+ -+"ocaml support" -+ -+import os, re -+import TaskGen, Utils, Task, Build -+from Logs import error -+from TaskGen import taskgen, feature, before, after, extension -+ -+EXT_MLL = ['.mll'] -+EXT_MLY = ['.mly'] -+EXT_MLI = ['.mli'] -+EXT_MLC = ['.c'] -+EXT_ML = ['.ml'] -+ -+open_re = re.compile('^\s*open\s+([a-zA-Z]+)(;;){0,1}$', re.M) -+foo = re.compile(r"""(\(\*)|(\*\))|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^()*"'\\]*)""", re.M) -+def filter_comments(txt): -+ meh = [0] -+ def repl(m): -+ if m.group(1): meh[0] += 1 -+ elif m.group(2): meh[0] -= 1 -+ elif not meh[0]: return m.group(0) -+ return '' -+ return foo.sub(repl, txt) -+ -+def scan(self): -+ node = self.inputs[0] -+ code = filter_comments(node.read(self.env)) -+ -+ global open_re -+ names = [] -+ import_iterator = open_re.finditer(code) -+ if import_iterator: -+ for import_match in import_iterator: -+ names.append(import_match.group(1)) -+ found_lst = [] -+ raw_lst = [] -+ for name in names: -+ nd = None -+ for x in self.incpaths: -+ nd = x.find_resource(name.lower()+'.ml') -+ if not nd: nd = x.find_resource(name+'.ml') -+ if nd: -+ found_lst.append(nd) -+ break -+ else: -+ raw_lst.append(name) -+ -+ return (found_lst, raw_lst) -+ -+native_lst=['native', 'all', 'c_object'] -+bytecode_lst=['bytecode', 'all'] -+class ocaml_taskgen(TaskGen.task_gen): -+ def __init__(self, *k, **kw): -+ TaskGen.task_gen.__init__(self, *k, **kw) -+ -+@feature('ocaml') -+def init_ml(self): -+ Utils.def_attrs(self, -+ type = 'all', -+ incpaths_lst = [], -+ bld_incpaths_lst = [], -+ mlltasks = [], -+ mlytasks = [], -+ mlitasks = [], -+ native_tasks = [], -+ bytecode_tasks = [], -+ linktasks = [], -+ bytecode_env = None, -+ native_env = None, -+ compiled_tasks = [], -+ includes = '', -+ uselib = '', -+ are_deps_set = 0) -+ -+@feature('ocaml') -+@after('init_ml') -+def init_envs_ml(self): -+ -+ self.islibrary = getattr(self, 'islibrary', False) -+ -+ global native_lst, bytecode_lst -+ self.native_env = None -+ if self.type in native_lst: -+ self.native_env = self.env.copy() -+ if self.islibrary: self.native_env['OCALINKFLAGS'] = '-a' -+ -+ self.bytecode_env = None -+ if self.type in bytecode_lst: -+ self.bytecode_env = self.env.copy() -+ if self.islibrary: self.bytecode_env['OCALINKFLAGS'] = '-a' -+ -+ if self.type == 'c_object': -+ self.native_env.append_unique('OCALINKFLAGS_OPT', '-output-obj') -+ -+@feature('ocaml') -+@before('apply_vars_ml') -+@after('init_envs_ml') -+def apply_incpaths_ml(self): -+ inc_lst = self.includes.split() -+ lst = self.incpaths_lst -+ for dir in inc_lst: -+ node = self.path.find_dir(dir) -+ if not node: -+ error("node not found: " + str(dir)) -+ continue -+ self.bld.rescan(node) -+ if not node in lst: lst.append(node) -+ self.bld_incpaths_lst.append(node) -+ # now the nodes are added to self.incpaths_lst -+ -+@feature('ocaml') -+@before('apply_core') -+def apply_vars_ml(self): -+ for i in self.incpaths_lst: -+ if self.bytecode_env: -+ app = self.bytecode_env.append_value -+ app('OCAMLPATH', '-I') -+ app('OCAMLPATH', i.srcpath(self.env)) -+ app('OCAMLPATH', '-I') -+ app('OCAMLPATH', i.bldpath(self.env)) -+ -+ if self.native_env: -+ app = self.native_env.append_value -+ app('OCAMLPATH', '-I') -+ app('OCAMLPATH', i.bldpath(self.env)) -+ app('OCAMLPATH', '-I') -+ app('OCAMLPATH', i.srcpath(self.env)) -+ -+ varnames = ['INCLUDES', 'OCAMLFLAGS', 'OCALINKFLAGS', 'OCALINKFLAGS_OPT'] -+ for name in self.uselib.split(): -+ for vname in varnames: -+ cnt = self.env[vname+'_'+name] -+ if cnt: -+ if self.bytecode_env: self.bytecode_env.append_value(vname, cnt) -+ if self.native_env: self.native_env.append_value(vname, cnt) -+ -+@feature('ocaml') -+@after('apply_core') -+def apply_link_ml(self): -+ -+ if self.bytecode_env: -+ ext = self.islibrary and '.cma' or '.run' -+ -+ linktask = self.create_task('ocalink') -+ linktask.bytecode = 1 -+ linktask.set_outputs(self.path.find_or_declare(self.target + ext)) -+ linktask.obj = self -+ linktask.env = self.bytecode_env -+ self.linktasks.append(linktask) -+ -+ if self.native_env: -+ if self.type == 'c_object': ext = '.o' -+ elif self.islibrary: ext = '.cmxa' -+ else: ext = '' -+ -+ linktask = self.create_task('ocalinkx') -+ linktask.set_outputs(self.path.find_or_declare(self.target + ext)) -+ linktask.obj = self -+ linktask.env = self.native_env -+ self.linktasks.append(linktask) -+ -+ # we produce a .o file to be used by gcc -+ self.compiled_tasks.append(linktask) -+ -+@extension(EXT_MLL) -+def mll_hook(self, node): -+ mll_task = self.create_task('ocamllex', node, node.change_ext('.ml'), env=self.native_env) -+ self.mlltasks.append(mll_task) -+ -+ self.allnodes.append(mll_task.outputs[0]) -+ -+@extension(EXT_MLY) -+def mly_hook(self, node): -+ mly_task = self.create_task('ocamlyacc', node, [node.change_ext('.ml'), node.change_ext('.mli')], env=self.native_env) -+ self.mlytasks.append(mly_task) -+ self.allnodes.append(mly_task.outputs[0]) -+ -+ task = self.create_task('ocamlcmi', mly_task.outputs[1], mly_task.outputs[1].change_ext('.cmi'), env=self.native_env) -+ -+@extension(EXT_MLI) -+def mli_hook(self, node): -+ task = self.create_task('ocamlcmi', node, node.change_ext('.cmi'), env=self.native_env) -+ self.mlitasks.append(task) -+ -+@extension(EXT_MLC) -+def mlc_hook(self, node): -+ task = self.create_task('ocamlcc', node, node.change_ext('.o'), env=self.native_env) -+ self.compiled_tasks.append(task) -+ -+@extension(EXT_ML) -+def ml_hook(self, node): -+ if self.native_env: -+ task = self.create_task('ocamlx', node, node.change_ext('.cmx'), env=self.native_env) -+ task.obj = self -+ task.incpaths = self.bld_incpaths_lst -+ self.native_tasks.append(task) -+ -+ if self.bytecode_env: -+ task = self.create_task('ocaml', node, node.change_ext('.cmo'), env=self.bytecode_env) -+ task.obj = self -+ task.bytecode = 1 -+ task.incpaths = self.bld_incpaths_lst -+ self.bytecode_tasks.append(task) -+ -+def compile_may_start(self): -+ if not getattr(self, 'flag_deps', ''): -+ self.flag_deps = 1 -+ -+ # the evil part is that we can only compute the dependencies after the -+ # source files can be read (this means actually producing the source files) -+ if getattr(self, 'bytecode', ''): alltasks = self.obj.bytecode_tasks -+ else: alltasks = self.obj.native_tasks -+ -+ self.signature() # ensure that files are scanned - unfortunately -+ tree = self.generator.bld -+ env = self.env -+ for node in self.inputs: -+ lst = tree.node_deps[self.unique_id()] -+ for depnode in lst: -+ for t in alltasks: -+ if t == self: continue -+ if depnode in t.inputs: -+ self.set_run_after(t) -+ -+ # TODO necessary to get the signature right - for now -+ delattr(self, 'cache_sig') -+ self.signature() -+ -+ return Task.Task.runnable_status(self) -+ -+b = Task.simple_task_type -+cls = b('ocamlx', '${OCAMLOPT} ${OCAMLPATH} ${OCAMLFLAGS} ${INCLUDES} -c -o ${TGT} ${SRC}', color='GREEN', shell=False) -+cls.runnable_status = compile_may_start -+cls.scan = scan -+ -+b = Task.simple_task_type -+cls = b('ocaml', '${OCAMLC} ${OCAMLPATH} ${OCAMLFLAGS} ${INCLUDES} -c -o ${TGT} ${SRC}', color='GREEN', shell=False) -+cls.runnable_status = compile_may_start -+cls.scan = scan -+ -+ -+b('ocamlcmi', '${OCAMLC} ${OCAMLPATH} ${INCLUDES} -o ${TGT} -c ${SRC}', color='BLUE', before="ocaml ocamlcc ocamlx") -+b('ocamlcc', 'cd ${TGT[0].bld_dir(env)} && ${OCAMLOPT} ${OCAMLFLAGS} ${OCAMLPATH} ${INCLUDES} -c ${SRC[0].abspath(env)}', color='GREEN') -+ -+b('ocamllex', '${OCAMLLEX} ${SRC} -o ${TGT}', color='BLUE', before="ocamlcmi ocaml ocamlcc") -+b('ocamlyacc', '${OCAMLYACC} -b ${TGT[0].bld_base(env)} ${SRC}', color='BLUE', before="ocamlcmi ocaml ocamlcc") -+ -+ -+def link_may_start(self): -+ if not getattr(self, 'order', ''): -+ -+ # now reorder the inputs given the task dependencies -+ if getattr(self, 'bytecode', 0): alltasks = self.obj.bytecode_tasks -+ else: alltasks = self.obj.native_tasks -+ -+ # this part is difficult, we do not have a total order on the tasks -+ # if the dependencies are wrong, this may not stop -+ seen = [] -+ pendant = []+alltasks -+ while pendant: -+ task = pendant.pop(0) -+ if task in seen: continue -+ for x in task.run_after: -+ if not x in seen: -+ pendant.append(task) -+ break -+ else: -+ seen.append(task) -+ self.inputs = [x.outputs[0] for x in seen] -+ self.order = 1 -+ return Task.Task.runnable_status(self) -+ -+act = b('ocalink', '${OCAMLC} -o ${TGT} ${INCLUDES} ${OCALINKFLAGS} ${SRC}', color='YELLOW', after="ocaml ocamlcc") -+act.runnable_status = link_may_start -+act = b('ocalinkx', '${OCAMLOPT} -o ${TGT} ${INCLUDES} ${OCALINKFLAGS_OPT} ${SRC}', color='YELLOW', after="ocamlx ocamlcc") -+act.runnable_status = link_may_start -+ -+def detect(conf): -+ opt = conf.find_program('ocamlopt', var='OCAMLOPT') -+ occ = conf.find_program('ocamlc', var='OCAMLC') -+ if (not opt) or (not occ): -+ conf.fatal('The objective caml compiler was not found:\ninstall it or make it available in your PATH') -+ -+ v = conf.env -+ v['OCAMLC'] = occ -+ v['OCAMLOPT'] = opt -+ v['OCAMLLEX'] = conf.find_program('ocamllex', var='OCAMLLEX') -+ v['OCAMLYACC'] = conf.find_program('ocamlyacc', var='OCAMLYACC') -+ v['OCAMLFLAGS'] = '' -+ v['OCAMLLIB'] = Utils.cmd_output(conf.env['OCAMLC']+' -where').strip()+os.sep -+ v['LIBPATH_OCAML'] = Utils.cmd_output(conf.env['OCAMLC']+' -where').strip()+os.sep -+ v['CPPPATH_OCAML'] = Utils.cmd_output(conf.env['OCAMLC']+' -where').strip()+os.sep -+ v['LIB_OCAML'] = 'camlrun' -+ -diff --git a/buildtools/wafadmin/Tools/osx.py b/buildtools/wafadmin/Tools/osx.py -new file mode 100644 -index 0000000..561eca4 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/osx.py -@@ -0,0 +1,188 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy 2008 -+ -+"""MacOSX related tools -+ -+To compile an executable into a Mac application bundle (a .app), set its 'mac_app' attribute -+ obj.mac_app = True -+ -+To make a bundled shared library (a .bundle), set the 'mac_bundle' attribute: -+ obj.mac_bundle = True -+""" -+ -+import os, shutil, sys, platform -+import TaskGen, Task, Build, Options, Utils -+from TaskGen import taskgen, feature, after, before -+from Logs import error, debug -+ -+# plist template -+app_info = ''' -+ -+ -+ -+ -+ CFBundlePackageType -+ APPL -+ CFBundleGetInfoString -+ Created by Waf -+ CFBundleSignature -+ ???? -+ NOTE -+ THIS IS A GENERATED FILE, DO NOT MODIFY -+ CFBundleExecutable -+ %s -+ -+ -+''' -+ -+# see WAF issue 285 -+# and also http://trac.macports.org/ticket/17059 -+@feature('cc', 'cxx') -+@before('apply_lib_vars') -+def set_macosx_deployment_target(self): -+ if self.env['MACOSX_DEPLOYMENT_TARGET']: -+ os.environ['MACOSX_DEPLOYMENT_TARGET'] = self.env['MACOSX_DEPLOYMENT_TARGET'] -+ elif 'MACOSX_DEPLOYMENT_TARGET' not in os.environ: -+ if sys.platform == 'darwin': -+ os.environ['MACOSX_DEPLOYMENT_TARGET'] = '.'.join(platform.mac_ver()[0].split('.')[:2]) -+ -+@feature('cc', 'cxx') -+@after('apply_lib_vars') -+def apply_framework(self): -+ for x in self.to_list(self.env['FRAMEWORKPATH']): -+ frameworkpath_st = '-F%s' -+ self.env.append_unique('CXXFLAGS', frameworkpath_st % x) -+ self.env.append_unique('CCFLAGS', frameworkpath_st % x) -+ self.env.append_unique('LINKFLAGS', frameworkpath_st % x) -+ -+ for x in self.to_list(self.env['FRAMEWORK']): -+ self.env.append_value('LINKFLAGS', ['-framework', x]) -+ -+@taskgen -+def create_bundle_dirs(self, name, out): -+ bld = self.bld -+ dir = out.parent.get_dir(name) -+ -+ if not dir: -+ dir = out.__class__(name, out.parent, 1) -+ bld.rescan(dir) -+ contents = out.__class__('Contents', dir, 1) -+ bld.rescan(contents) -+ macos = out.__class__('MacOS', contents, 1) -+ bld.rescan(macos) -+ return dir -+ -+def bundle_name_for_output(out): -+ name = out.name -+ k = name.rfind('.') -+ if k >= 0: -+ name = name[:k] + '.app' -+ else: -+ name = name + '.app' -+ return name -+ -+@taskgen -+@after('apply_link') -+@feature('cprogram') -+def create_task_macapp(self): -+ """Use env['MACAPP'] to force *all* executables to be transformed into Mac applications -+ or use obj.mac_app = True to build specific targets as Mac apps""" -+ if self.env['MACAPP'] or getattr(self, 'mac_app', False): -+ apptask = self.create_task('macapp') -+ apptask.set_inputs(self.link_task.outputs) -+ -+ out = self.link_task.outputs[0] -+ -+ name = bundle_name_for_output(out) -+ dir = self.create_bundle_dirs(name, out) -+ -+ n1 = dir.find_or_declare(['Contents', 'MacOS', out.name]) -+ -+ apptask.set_outputs([n1]) -+ apptask.chmod = 0755 -+ apptask.install_path = os.path.join(self.install_path, name, 'Contents', 'MacOS') -+ self.apptask = apptask -+ -+@after('apply_link') -+@feature('cprogram') -+def create_task_macplist(self): -+ """Use env['MACAPP'] to force *all* executables to be transformed into Mac applications -+ or use obj.mac_app = True to build specific targets as Mac apps""" -+ if self.env['MACAPP'] or getattr(self, 'mac_app', False): -+ # check if the user specified a plist before using our template -+ if not getattr(self, 'mac_plist', False): -+ self.mac_plist = app_info -+ -+ plisttask = self.create_task('macplist') -+ plisttask.set_inputs(self.link_task.outputs) -+ -+ out = self.link_task.outputs[0] -+ self.mac_plist = self.mac_plist % (out.name) -+ -+ name = bundle_name_for_output(out) -+ dir = self.create_bundle_dirs(name, out) -+ -+ n1 = dir.find_or_declare(['Contents', 'Info.plist']) -+ -+ plisttask.set_outputs([n1]) -+ plisttask.mac_plist = self.mac_plist -+ plisttask.install_path = os.path.join(self.install_path, name, 'Contents') -+ self.plisttask = plisttask -+ -+@after('apply_link') -+@feature('cshlib') -+def apply_link_osx(self): -+ name = self.link_task.outputs[0].name -+ if not self.install_path: -+ return -+ if getattr(self, 'vnum', None): -+ name = name.replace('.dylib', '.%s.dylib' % self.vnum) -+ -+ path = os.path.join(Utils.subst_vars(self.install_path, self.env), name) -+ if '-dynamiclib' in self.env['LINKFLAGS']: -+ self.env.append_value('LINKFLAGS', '-install_name') -+ self.env.append_value('LINKFLAGS', path) -+ -+@before('apply_link', 'apply_lib_vars') -+@feature('cc', 'cxx') -+def apply_bundle(self): -+ """use env['MACBUNDLE'] to force all shlibs into mac bundles -+ or use obj.mac_bundle = True for specific targets only""" -+ if not ('cshlib' in self.features or 'shlib' in self.features): return -+ if self.env['MACBUNDLE'] or getattr(self, 'mac_bundle', False): -+ self.env['shlib_PATTERN'] = self.env['macbundle_PATTERN'] -+ uselib = self.uselib = self.to_list(self.uselib) -+ if not 'MACBUNDLE' in uselib: uselib.append('MACBUNDLE') -+ -+@after('apply_link') -+@feature('cshlib') -+def apply_bundle_remove_dynamiclib(self): -+ if self.env['MACBUNDLE'] or getattr(self, 'mac_bundle', False): -+ if not getattr(self, 'vnum', None): -+ try: -+ self.env['LINKFLAGS'].remove('-dynamiclib') -+ self.env['LINKFLAGS'].remove('-single_module') -+ except ValueError: -+ pass -+ -+# TODO REMOVE IN 1.6 (global variable) -+app_dirs = ['Contents', 'Contents/MacOS', 'Contents/Resources'] -+ -+def app_build(task): -+ env = task.env -+ shutil.copy2(task.inputs[0].srcpath(env), task.outputs[0].abspath(env)) -+ -+ return 0 -+ -+def plist_build(task): -+ env = task.env -+ f = open(task.outputs[0].abspath(env), "w") -+ f.write(task.mac_plist) -+ f.close() -+ -+ return 0 -+ -+Task.task_type_from_func('macapp', vars=[], func=app_build, after="cxx_link cc_link static_link") -+Task.task_type_from_func('macplist', vars=[], func=plist_build, after="cxx_link cc_link static_link") -+ -diff --git a/buildtools/wafadmin/Tools/perl.py b/buildtools/wafadmin/Tools/perl.py -new file mode 100644 -index 0000000..a6787a8 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/perl.py -@@ -0,0 +1,109 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# andersg at 0x63.nu 2007 -+ -+import os -+import Task, Options, Utils -+from Configure import conf -+from TaskGen import extension, taskgen, feature, before -+ -+xsubpp_str = '${PERL} ${XSUBPP} -noprototypes -typemap ${EXTUTILS_TYPEMAP} ${SRC} > ${TGT}' -+EXT_XS = ['.xs'] -+ -+@before('apply_incpaths', 'apply_type_vars', 'apply_lib_vars') -+@feature('perlext') -+def init_perlext(self): -+ self.uselib = self.to_list(getattr(self, 'uselib', '')) -+ if not 'PERL' in self.uselib: self.uselib.append('PERL') -+ if not 'PERLEXT' in self.uselib: self.uselib.append('PERLEXT') -+ self.env['shlib_PATTERN'] = self.env['perlext_PATTERN'] -+ -+@extension(EXT_XS) -+def xsubpp_file(self, node): -+ outnode = node.change_ext('.c') -+ self.create_task('xsubpp', node, outnode) -+ self.allnodes.append(outnode) -+ -+Task.simple_task_type('xsubpp', xsubpp_str, color='BLUE', before='cc cxx', shell=False) -+ -+@conf -+def check_perl_version(conf, minver=None): -+ """ -+ Checks if perl is installed. -+ -+ If installed the variable PERL will be set in environment. -+ -+ Perl binary can be overridden by --with-perl-binary config variable -+ -+ """ -+ -+ if getattr(Options.options, 'perlbinary', None): -+ conf.env.PERL = Options.options.perlbinary -+ else: -+ conf.find_program('perl', var='PERL', mandatory=True) -+ -+ try: -+ version = Utils.cmd_output([conf.env.PERL, '-e', 'printf "%vd",$^V']) -+ except: -+ conf.fatal('could not determine the perl version') -+ -+ conf.env.PERL_VERSION = version -+ cver = '' -+ if minver: -+ try: -+ ver = tuple(map(int, version.split('.'))) -+ except: -+ conf.fatal('unsupported perl version %r' % version) -+ if ver < minver: -+ conf.fatal('perl is too old') -+ -+ cver = '.'.join(map(str,minver)) -+ conf.check_message('perl', cver, True, version) -+ -+@conf -+def check_perl_module(conf, module): -+ """ -+ Check if specified perlmodule is installed. -+ -+ Minimum version can be specified by specifying it after modulename -+ like this: -+ -+ conf.check_perl_module("Some::Module 2.92") -+ """ -+ cmd = [conf.env['PERL'], '-e', 'use %s' % module] -+ r = Utils.pproc.call(cmd, stdout=Utils.pproc.PIPE, stderr=Utils.pproc.PIPE) == 0 -+ conf.check_message("perl module %s" % module, "", r) -+ return r -+ -+@conf -+def check_perl_ext_devel(conf): -+ """ -+ Check for configuration needed to build perl extensions. -+ -+ Sets different xxx_PERLEXT variables in the environment. -+ -+ Also sets the ARCHDIR_PERL variable useful as installation path, -+ which can be overridden by --with-perl-archdir -+ """ -+ if not conf.env.PERL: -+ conf.fatal('perl detection is required first') -+ -+ def read_out(cmd): -+ return Utils.to_list(Utils.cmd_output([conf.env.PERL, '-MConfig', '-e', cmd])) -+ -+ conf.env.LINKFLAGS_PERLEXT = read_out('print $Config{lddlflags}') -+ conf.env.CPPPATH_PERLEXT = read_out('print "$Config{archlib}/CORE"') -+ conf.env.CCFLAGS_PERLEXT = read_out('print "$Config{ccflags} $Config{cccdlflags}"') -+ conf.env.XSUBPP = read_out('print "$Config{privlib}/ExtUtils/xsubpp$Config{exe_ext}"') -+ conf.env.EXTUTILS_TYPEMAP = read_out('print "$Config{privlib}/ExtUtils/typemap"') -+ conf.env.perlext_PATTERN = '%s.' + read_out('print $Config{dlext}')[0] -+ -+ if getattr(Options.options, 'perlarchdir', None): -+ conf.env.ARCHDIR_PERL = Options.options.perlarchdir -+ else: -+ conf.env.ARCHDIR_PERL = read_out('print $Config{sitearch}')[0] -+ -+def set_options(opt): -+ opt.add_option("--with-perl-binary", type="string", dest="perlbinary", help = 'Specify alternate perl binary', default=None) -+ opt.add_option("--with-perl-archdir", type="string", dest="perlarchdir", help = 'Specify directory where to install arch specific files', default=None) -+ -diff --git a/buildtools/wafadmin/Tools/preproc.py b/buildtools/wafadmin/Tools/preproc.py -new file mode 100644 -index 0000000..5055456 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/preproc.py -@@ -0,0 +1,836 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006-2009 (ita) -+ -+""" -+C/C++ preprocessor for finding dependencies -+ -+Reasons for using the Waf preprocessor by default -+1. Some c/c++ extensions (Qt) require a custom preprocessor for obtaining the dependencies (.moc files) -+2. Not all compilers provide .d files for obtaining the dependencies (portability) -+3. A naive file scanner will not catch the constructs such as "#include foo()" -+4. A naive file scanner will catch unnecessary dependencies (change an unused header -> recompile everything) -+ -+Regarding the speed concerns: -+a. the preprocessing is performed only when files must be compiled -+b. the macros are evaluated only for #if/#elif/#include -+c. the time penalty is about 10% -+d. system headers are not scanned -+ -+Now if you do not want the Waf preprocessor, the tool "gccdeps" uses the .d files produced -+during the compilation to track the dependencies (useful when used with the boost libraries). -+It only works with gcc though, and it cannot be used with Qt builds. A dumb -+file scanner will be added in the future, so we will have most bahaviours. -+""" -+# TODO: more varargs, pragma once -+# TODO: dumb file scanner tracking all includes -+ -+import re, sys, os, string -+import Logs, Build, Utils -+from Logs import debug, error -+import traceback -+ -+class PreprocError(Utils.WafError): -+ pass -+ -+POPFILE = '-' -+ -+ -+recursion_limit = 5000 -+"do not loop too much on header inclusion" -+ -+go_absolute = 0 -+"set to 1 to track headers on files in /usr/include - else absolute paths are ignored" -+ -+standard_includes = ['/usr/include'] -+if sys.platform == "win32": -+ standard_includes = [] -+ -+use_trigraphs = 0 -+'apply the trigraph rules first' -+ -+strict_quotes = 0 -+"Keep <> for system includes (do not search for those includes)" -+ -+g_optrans = { -+'not':'!', -+'and':'&&', -+'bitand':'&', -+'and_eq':'&=', -+'or':'||', -+'bitor':'|', -+'or_eq':'|=', -+'xor':'^', -+'xor_eq':'^=', -+'compl':'~', -+} -+"these ops are for c++, to reset, set an empty dict" -+ -+# ignore #warning and #error -+re_lines = re.compile(\ -+ '^[ \t]*(#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*)\r*$', -+ re.IGNORECASE | re.MULTILINE) -+ -+re_mac = re.compile("^[a-zA-Z_]\w*") -+re_fun = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*[(]') -+re_pragma_once = re.compile('^\s*once\s*', re.IGNORECASE) -+re_nl = re.compile('\\\\\r*\n', re.MULTILINE) -+re_cpp = re.compile( -+ r"""(/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)|//[^\n]*|("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|.[^/"'\\]*)""", -+ re.MULTILINE) -+trig_def = [('??'+a, b) for a, b in zip("=-/!'()<>", r'#~\|^[]{}')] -+chr_esc = {'0':0, 'a':7, 'b':8, 't':9, 'n':10, 'f':11, 'v':12, 'r':13, '\\':92, "'":39} -+ -+NUM = 'i' -+OP = 'O' -+IDENT = 'T' -+STR = 's' -+CHAR = 'c' -+ -+tok_types = [NUM, STR, IDENT, OP] -+exp_types = [ -+ r"""0[xX](?P[a-fA-F0-9]+)(?P[uUlL]*)|L*?'(?P(\\.|[^\\'])+)'|(?P\d+)[Ee](?P[+-]*?\d+)(?P[fFlL]*)|(?P\d*\.\d+)([Ee](?P[+-]*?\d+))?(?P[fFlL]*)|(?P\d+\.\d*)([Ee](?P[+-]*?\d+))?(?P[fFlL]*)|(?P0*)(?P\d+)(?P[uUlL]*)""", -+ r'L?"([^"\\]|\\.)*"', -+ r'[a-zA-Z_]\w*', -+ r'%:%:|<<=|>>=|\.\.\.|<<|<%|<:|<=|>>|>=|\+\+|\+=|--|->|-=|\*=|/=|%:|%=|%>|==|&&|&=|\|\||\|=|\^=|:>|!=|##|[\(\)\{\}\[\]<>\?\|\^\*\+&=:!#;,%/\-\?\~\.]', -+] -+re_clexer = re.compile('|'.join(["(?P<%s>%s)" % (name, part) for name, part in zip(tok_types, exp_types)]), re.M) -+ -+accepted = 'a' -+ignored = 'i' -+undefined = 'u' -+skipped = 's' -+ -+def repl(m): -+ if m.group(1): -+ return ' ' -+ s = m.group(2) -+ if s is None: -+ return '' -+ return s -+ -+def filter_comments(filename): -+ # return a list of tuples : keyword, line -+ code = Utils.readf(filename) -+ if use_trigraphs: -+ for (a, b) in trig_def: code = code.split(a).join(b) -+ code = re_nl.sub('', code) -+ code = re_cpp.sub(repl, code) -+ return [(m.group(2), m.group(3)) for m in re.finditer(re_lines, code)] -+ -+prec = {} -+# op -> number, needed for such expressions: #if 1 && 2 != 0 -+ops = ['* / %', '+ -', '<< >>', '< <= >= >', '== !=', '& | ^', '&& ||', ','] -+for x in range(len(ops)): -+ syms = ops[x] -+ for u in syms.split(): -+ prec[u] = x -+ -+def reduce_nums(val_1, val_2, val_op): -+ """apply arithmetic rules and try to return an integer result""" -+ #print val_1, val_2, val_op -+ -+ # now perform the operation, make certain a and b are numeric -+ try: a = 0 + val_1 -+ except TypeError: a = int(val_1) -+ try: b = 0 + val_2 -+ except TypeError: b = int(val_2) -+ -+ d = val_op -+ if d == '%': c = a%b -+ elif d=='+': c = a+b -+ elif d=='-': c = a-b -+ elif d=='*': c = a*b -+ elif d=='/': c = a/b -+ elif d=='^': c = a^b -+ elif d=='|': c = a|b -+ elif d=='||': c = int(a or b) -+ elif d=='&': c = a&b -+ elif d=='&&': c = int(a and b) -+ elif d=='==': c = int(a == b) -+ elif d=='!=': c = int(a != b) -+ elif d=='<=': c = int(a <= b) -+ elif d=='<': c = int(a < b) -+ elif d=='>': c = int(a > b) -+ elif d=='>=': c = int(a >= b) -+ elif d=='^': c = int(a^b) -+ elif d=='<<': c = a<>': c = a>>b -+ else: c = 0 -+ return c -+ -+def get_num(lst): -+ if not lst: raise PreprocError("empty list for get_num") -+ (p, v) = lst[0] -+ if p == OP: -+ if v == '(': -+ count_par = 1 -+ i = 1 -+ while i < len(lst): -+ (p, v) = lst[i] -+ -+ if p == OP: -+ if v == ')': -+ count_par -= 1 -+ if count_par == 0: -+ break -+ elif v == '(': -+ count_par += 1 -+ i += 1 -+ else: -+ raise PreprocError("rparen expected %r" % lst) -+ -+ (num, _) = get_term(lst[1:i]) -+ return (num, lst[i+1:]) -+ -+ elif v == '+': -+ return get_num(lst[1:]) -+ elif v == '-': -+ num, lst = get_num(lst[1:]) -+ return (reduce_nums('-1', num, '*'), lst) -+ elif v == '!': -+ num, lst = get_num(lst[1:]) -+ return (int(not int(num)), lst) -+ elif v == '~': -+ return (~ int(num), lst) -+ else: -+ raise PreprocError("invalid op token %r for get_num" % lst) -+ elif p == NUM: -+ return v, lst[1:] -+ elif p == IDENT: -+ # all macros should have been replaced, remaining identifiers eval to 0 -+ return 0, lst[1:] -+ else: -+ raise PreprocError("invalid token %r for get_num" % lst) -+ -+def get_term(lst): -+ if not lst: raise PreprocError("empty list for get_term") -+ num, lst = get_num(lst) -+ if not lst: -+ return (num, []) -+ (p, v) = lst[0] -+ if p == OP: -+ if v == '&&' and not num: -+ return (num, []) -+ elif v == '||' and num: -+ return (num, []) -+ elif v == ',': -+ # skip -+ return get_term(lst[1:]) -+ elif v == '?': -+ count_par = 0 -+ i = 1 -+ while i < len(lst): -+ (p, v) = lst[i] -+ -+ if p == OP: -+ if v == ')': -+ count_par -= 1 -+ elif v == '(': -+ count_par += 1 -+ elif v == ':': -+ if count_par == 0: -+ break -+ i += 1 -+ else: -+ raise PreprocError("rparen expected %r" % lst) -+ -+ if int(num): -+ return get_term(lst[1:i]) -+ else: -+ return get_term(lst[i+1:]) -+ -+ else: -+ num2, lst = get_num(lst[1:]) -+ -+ if not lst: -+ # no more tokens to process -+ num2 = reduce_nums(num, num2, v) -+ return get_term([(NUM, num2)] + lst) -+ -+ # operator precedence -+ p2, v2 = lst[0] -+ if p2 != OP: -+ raise PreprocError("op expected %r" % lst) -+ -+ if prec[v2] >= prec[v]: -+ num2 = reduce_nums(num, num2, v) -+ return get_term([(NUM, num2)] + lst) -+ else: -+ num3, lst = get_num(lst[1:]) -+ num3 = reduce_nums(num2, num3, v2) -+ return get_term([(NUM, num), (p, v), (NUM, num3)] + lst) -+ -+ -+ raise PreprocError("cannot reduce %r" % lst) -+ -+def reduce_eval(lst): -+ """take a list of tokens and output true or false (#if/#elif conditions)""" -+ num, lst = get_term(lst) -+ return (NUM, num) -+ -+def stringize(lst): -+ """use for converting a list of tokens to a string""" -+ lst = [str(v2) for (p2, v2) in lst] -+ return "".join(lst) -+ -+def paste_tokens(t1, t2): -+ """ -+ here is what we can paste: -+ a ## b -> ab -+ > ## = -> >= -+ a ## 2 -> a2 -+ """ -+ p1 = None -+ if t1[0] == OP and t2[0] == OP: -+ p1 = OP -+ elif t1[0] == IDENT and (t2[0] == IDENT or t2[0] == NUM): -+ p1 = IDENT -+ elif t1[0] == NUM and t2[0] == NUM: -+ p1 = NUM -+ if not p1: -+ raise PreprocError('tokens do not make a valid paste %r and %r' % (t1, t2)) -+ return (p1, t1[1] + t2[1]) -+ -+def reduce_tokens(lst, defs, ban=[]): -+ """replace the tokens in lst, using the macros provided in defs, and a list of macros that cannot be re-applied""" -+ i = 0 -+ -+ while i < len(lst): -+ (p, v) = lst[i] -+ -+ if p == IDENT and v == "defined": -+ del lst[i] -+ if i < len(lst): -+ (p2, v2) = lst[i] -+ if p2 == IDENT: -+ if v2 in defs: -+ lst[i] = (NUM, 1) -+ else: -+ lst[i] = (NUM, 0) -+ elif p2 == OP and v2 == '(': -+ del lst[i] -+ (p2, v2) = lst[i] -+ del lst[i] # remove the ident, and change the ) for the value -+ if v2 in defs: -+ lst[i] = (NUM, 1) -+ else: -+ lst[i] = (NUM, 0) -+ else: -+ raise PreprocError("invalid define expression %r" % lst) -+ -+ elif p == IDENT and v in defs: -+ -+ if isinstance(defs[v], str): -+ a, b = extract_macro(defs[v]) -+ defs[v] = b -+ macro_def = defs[v] -+ to_add = macro_def[1] -+ -+ if isinstance(macro_def[0], list): -+ # macro without arguments -+ del lst[i] -+ for x in xrange(len(to_add)): -+ lst.insert(i, to_add[x]) -+ i += 1 -+ else: -+ # collect the arguments for the funcall -+ -+ args = [] -+ del lst[i] -+ -+ if i >= len(lst): -+ raise PreprocError("expected '(' after %r (got nothing)" % v) -+ -+ (p2, v2) = lst[i] -+ if p2 != OP or v2 != '(': -+ raise PreprocError("expected '(' after %r" % v) -+ -+ del lst[i] -+ -+ one_param = [] -+ count_paren = 0 -+ while i < len(lst): -+ p2, v2 = lst[i] -+ -+ del lst[i] -+ if p2 == OP and count_paren == 0: -+ if v2 == '(': -+ one_param.append((p2, v2)) -+ count_paren += 1 -+ elif v2 == ')': -+ if one_param: args.append(one_param) -+ break -+ elif v2 == ',': -+ if not one_param: raise PreprocError("empty param in funcall %s" % p) -+ args.append(one_param) -+ one_param = [] -+ else: -+ one_param.append((p2, v2)) -+ else: -+ one_param.append((p2, v2)) -+ if v2 == '(': count_paren += 1 -+ elif v2 == ')': count_paren -= 1 -+ else: -+ raise PreprocError('malformed macro') -+ -+ # substitute the arguments within the define expression -+ accu = [] -+ arg_table = macro_def[0] -+ j = 0 -+ while j < len(to_add): -+ (p2, v2) = to_add[j] -+ -+ if p2 == OP and v2 == '#': -+ # stringize is for arguments only -+ if j+1 < len(to_add) and to_add[j+1][0] == IDENT and to_add[j+1][1] in arg_table: -+ toks = args[arg_table[to_add[j+1][1]]] -+ accu.append((STR, stringize(toks))) -+ j += 1 -+ else: -+ accu.append((p2, v2)) -+ elif p2 == OP and v2 == '##': -+ # token pasting, how can man invent such a complicated system? -+ if accu and j+1 < len(to_add): -+ # we have at least two tokens -+ -+ t1 = accu[-1] -+ -+ if to_add[j+1][0] == IDENT and to_add[j+1][1] in arg_table: -+ toks = args[arg_table[to_add[j+1][1]]] -+ -+ if toks: -+ accu[-1] = paste_tokens(t1, toks[0]) #(IDENT, accu[-1][1] + toks[0][1]) -+ accu.extend(toks[1:]) -+ else: -+ # error, case "a##" -+ accu.append((p2, v2)) -+ accu.extend(toks) -+ elif to_add[j+1][0] == IDENT and to_add[j+1][1] == '__VA_ARGS__': -+ # TODO not sure -+ # first collect the tokens -+ va_toks = [] -+ st = len(macro_def[0]) -+ pt = len(args) -+ for x in args[pt-st+1:]: -+ va_toks.extend(x) -+ va_toks.append((OP, ',')) -+ if va_toks: va_toks.pop() # extra comma -+ if len(accu)>1: -+ (p3, v3) = accu[-1] -+ (p4, v4) = accu[-2] -+ if v3 == '##': -+ # remove the token paste -+ accu.pop() -+ if v4 == ',' and pt < st: -+ # remove the comma -+ accu.pop() -+ accu += va_toks -+ else: -+ accu[-1] = paste_tokens(t1, to_add[j+1]) -+ -+ j += 1 -+ else: -+ # invalid paste, case "##a" or "b##" -+ accu.append((p2, v2)) -+ -+ elif p2 == IDENT and v2 in arg_table: -+ toks = args[arg_table[v2]] -+ reduce_tokens(toks, defs, ban+[v]) -+ accu.extend(toks) -+ else: -+ accu.append((p2, v2)) -+ -+ j += 1 -+ -+ -+ reduce_tokens(accu, defs, ban+[v]) -+ -+ for x in xrange(len(accu)-1, -1, -1): -+ lst.insert(i, accu[x]) -+ -+ i += 1 -+ -+ -+def eval_macro(lst, adefs): -+ """reduce the tokens from the list lst, and try to return a 0/1 result""" -+ reduce_tokens(lst, adefs, []) -+ if not lst: raise PreprocError("missing tokens to evaluate") -+ (p, v) = reduce_eval(lst) -+ return int(v) != 0 -+ -+def extract_macro(txt): -+ """process a macro definition from "#define f(x, y) x * y" into a function or a simple macro without arguments""" -+ t = tokenize(txt) -+ if re_fun.search(txt): -+ p, name = t[0] -+ -+ p, v = t[1] -+ if p != OP: raise PreprocError("expected open parenthesis") -+ -+ i = 1 -+ pindex = 0 -+ params = {} -+ prev = '(' -+ -+ while 1: -+ i += 1 -+ p, v = t[i] -+ -+ if prev == '(': -+ if p == IDENT: -+ params[v] = pindex -+ pindex += 1 -+ prev = p -+ elif p == OP and v == ')': -+ break -+ else: -+ raise PreprocError("unexpected token (3)") -+ elif prev == IDENT: -+ if p == OP and v == ',': -+ prev = v -+ elif p == OP and v == ')': -+ break -+ else: -+ raise PreprocError("comma or ... expected") -+ elif prev == ',': -+ if p == IDENT: -+ params[v] = pindex -+ pindex += 1 -+ prev = p -+ elif p == OP and v == '...': -+ raise PreprocError("not implemented (1)") -+ else: -+ raise PreprocError("comma or ... expected (2)") -+ elif prev == '...': -+ raise PreprocError("not implemented (2)") -+ else: -+ raise PreprocError("unexpected else") -+ -+ #~ print (name, [params, t[i+1:]]) -+ return (name, [params, t[i+1:]]) -+ else: -+ (p, v) = t[0] -+ return (v, [[], t[1:]]) -+ -+re_include = re.compile('^\s*(<(?P.*)>|"(?P.*)")') -+def extract_include(txt, defs): -+ """process a line in the form "#include foo" to return a string representing the file""" -+ m = re_include.search(txt) -+ if m: -+ if m.group('a'): return '<', m.group('a') -+ if m.group('b'): return '"', m.group('b') -+ -+ # perform preprocessing and look at the result, it must match an include -+ toks = tokenize(txt) -+ reduce_tokens(toks, defs, ['waf_include']) -+ -+ if not toks: -+ raise PreprocError("could not parse include %s" % txt) -+ -+ if len(toks) == 1: -+ if toks[0][0] == STR: -+ return '"', toks[0][1] -+ else: -+ if toks[0][1] == '<' and toks[-1][1] == '>': -+ return stringize(toks).lstrip('<').rstrip('>') -+ -+ raise PreprocError("could not parse include %s." % txt) -+ -+def parse_char(txt): -+ if not txt: raise PreprocError("attempted to parse a null char") -+ if txt[0] != '\\': -+ return ord(txt) -+ c = txt[1] -+ if c == 'x': -+ if len(txt) == 4 and txt[3] in string.hexdigits: return int(txt[2:], 16) -+ return int(txt[2:], 16) -+ elif c.isdigit(): -+ if c == '0' and len(txt)==2: return 0 -+ for i in 3, 2, 1: -+ if len(txt) > i and txt[1:1+i].isdigit(): -+ return (1+i, int(txt[1:1+i], 8)) -+ else: -+ try: return chr_esc[c] -+ except KeyError: raise PreprocError("could not parse char literal '%s'" % txt) -+ -+@Utils.run_once -+def tokenize(s): -+ """convert a string into a list of tokens (shlex.split does not apply to c/c++/d)""" -+ ret = [] -+ for match in re_clexer.finditer(s): -+ m = match.group -+ for name in tok_types: -+ v = m(name) -+ if v: -+ if name == IDENT: -+ try: v = g_optrans[v]; name = OP -+ except KeyError: -+ # c++ specific -+ if v.lower() == "true": -+ v = 1 -+ name = NUM -+ elif v.lower() == "false": -+ v = 0 -+ name = NUM -+ elif name == NUM: -+ if m('oct'): v = int(v, 8) -+ elif m('hex'): v = int(m('hex'), 16) -+ elif m('n0'): v = m('n0') -+ else: -+ v = m('char') -+ if v: v = parse_char(v) -+ else: v = m('n2') or m('n4') -+ elif name == OP: -+ if v == '%:': v = '#' -+ elif v == '%:%:': v = '##' -+ elif name == STR: -+ # remove the quotes around the string -+ v = v[1:-1] -+ ret.append((name, v)) -+ break -+ return ret -+ -+@Utils.run_once -+def define_name(line): -+ return re_mac.match(line).group(0) -+ -+class c_parser(object): -+ def __init__(self, nodepaths=None, defines=None): -+ #self.lines = txt.split('\n') -+ self.lines = [] -+ -+ if defines is None: -+ self.defs = {} -+ else: -+ self.defs = dict(defines) # make a copy -+ self.state = [] -+ -+ self.env = None # needed for the variant when searching for files -+ -+ self.count_files = 0 -+ self.currentnode_stack = [] -+ -+ self.nodepaths = nodepaths or [] -+ -+ self.nodes = [] -+ self.names = [] -+ -+ # file added -+ self.curfile = '' -+ self.ban_includes = set([]) -+ -+ def cached_find_resource(self, node, filename): -+ try: -+ nd = node.bld.cache_nd -+ except: -+ nd = node.bld.cache_nd = {} -+ -+ tup = (node.id, filename) -+ try: -+ return nd[tup] -+ except KeyError: -+ ret = node.find_resource(filename) -+ nd[tup] = ret -+ return ret -+ -+ def tryfind(self, filename): -+ self.curfile = filename -+ -+ # for msvc it should be a for loop on the whole stack -+ found = self.cached_find_resource(self.currentnode_stack[-1], filename) -+ -+ for n in self.nodepaths: -+ if found: -+ break -+ found = self.cached_find_resource(n, filename) -+ -+ if found: -+ self.nodes.append(found) -+ if filename[-4:] != '.moc': -+ self.addlines(found) -+ else: -+ if not filename in self.names: -+ self.names.append(filename) -+ return found -+ -+ def addlines(self, node): -+ -+ self.currentnode_stack.append(node.parent) -+ filepath = node.abspath(self.env) -+ -+ self.count_files += 1 -+ if self.count_files > recursion_limit: raise PreprocError("recursion limit exceeded") -+ pc = self.parse_cache -+ debug('preproc: reading file %r', filepath) -+ try: -+ lns = pc[filepath] -+ except KeyError: -+ pass -+ else: -+ self.lines.extend(lns) -+ return -+ -+ try: -+ lines = filter_comments(filepath) -+ lines.append((POPFILE, '')) -+ lines.reverse() -+ pc[filepath] = lines # cache the lines filtered -+ self.lines.extend(lines) -+ except IOError: -+ raise PreprocError("could not read the file %s" % filepath) -+ except Exception: -+ if Logs.verbose > 0: -+ error("parsing %s failed" % filepath) -+ traceback.print_exc() -+ -+ def start(self, node, env): -+ debug('preproc: scanning %s (in %s)', node.name, node.parent.name) -+ -+ self.env = env -+ variant = node.variant(env) -+ bld = node.__class__.bld -+ try: -+ self.parse_cache = bld.parse_cache -+ except AttributeError: -+ bld.parse_cache = {} -+ self.parse_cache = bld.parse_cache -+ -+ self.addlines(node) -+ if env['DEFLINES']: -+ lst = [('define', x) for x in env['DEFLINES']] -+ lst.reverse() -+ self.lines.extend(lst) -+ -+ while self.lines: -+ (kind, line) = self.lines.pop() -+ if kind == POPFILE: -+ self.currentnode_stack.pop() -+ continue -+ try: -+ self.process_line(kind, line) -+ except Exception, e: -+ if Logs.verbose: -+ debug('preproc: line parsing failed (%s): %s %s', e, line, Utils.ex_stack()) -+ -+ def process_line(self, token, line): -+ """ -+ WARNING: a new state must be added for if* because the endif -+ """ -+ ve = Logs.verbose -+ if ve: debug('preproc: line is %s - %s state is %s', token, line, self.state) -+ state = self.state -+ -+ # make certain we define the state if we are about to enter in an if block -+ if token in ['ifdef', 'ifndef', 'if']: -+ state.append(undefined) -+ elif token == 'endif': -+ state.pop() -+ -+ # skip lines when in a dead 'if' branch, wait for the endif -+ if not token in ['else', 'elif', 'endif']: -+ if skipped in self.state or ignored in self.state: -+ return -+ -+ if token == 'if': -+ ret = eval_macro(tokenize(line), self.defs) -+ if ret: state[-1] = accepted -+ else: state[-1] = ignored -+ elif token == 'ifdef': -+ m = re_mac.match(line) -+ if m and m.group(0) in self.defs: state[-1] = accepted -+ else: state[-1] = ignored -+ elif token == 'ifndef': -+ m = re_mac.match(line) -+ if m and m.group(0) in self.defs: state[-1] = ignored -+ else: state[-1] = accepted -+ elif token == 'include' or token == 'import': -+ (kind, inc) = extract_include(line, self.defs) -+ if inc in self.ban_includes: return -+ if token == 'import': self.ban_includes.add(inc) -+ if ve: debug('preproc: include found %s (%s) ', inc, kind) -+ if kind == '"' or not strict_quotes: -+ self.tryfind(inc) -+ elif token == 'elif': -+ if state[-1] == accepted: -+ state[-1] = skipped -+ elif state[-1] == ignored: -+ if eval_macro(tokenize(line), self.defs): -+ state[-1] = accepted -+ elif token == 'else': -+ if state[-1] == accepted: state[-1] = skipped -+ elif state[-1] == ignored: state[-1] = accepted -+ elif token == 'define': -+ try: -+ self.defs[define_name(line)] = line -+ except: -+ raise PreprocError("invalid define line %s" % line) -+ elif token == 'undef': -+ m = re_mac.match(line) -+ if m and m.group(0) in self.defs: -+ self.defs.__delitem__(m.group(0)) -+ #print "undef %s" % name -+ elif token == 'pragma': -+ if re_pragma_once.match(line.lower()): -+ self.ban_includes.add(self.curfile) -+ -+def get_deps(node, env, nodepaths=[]): -+ """ -+ Get the dependencies using a c/c++ preprocessor, this is required for finding dependencies of the kind -+ #include some_macro() -+ """ -+ -+ gruik = c_parser(nodepaths) -+ gruik.start(node, env) -+ return (gruik.nodes, gruik.names) -+ -+#################### dumb dependency scanner -+ -+re_inc = re.compile(\ -+ '^[ \t]*(#|%:)[ \t]*(include)[ \t]*(.*)\r*$', -+ re.IGNORECASE | re.MULTILINE) -+ -+def lines_includes(filename): -+ code = Utils.readf(filename) -+ if use_trigraphs: -+ for (a, b) in trig_def: code = code.split(a).join(b) -+ code = re_nl.sub('', code) -+ code = re_cpp.sub(repl, code) -+ return [(m.group(2), m.group(3)) for m in re.finditer(re_inc, code)] -+ -+def get_deps_simple(node, env, nodepaths=[], defines={}): -+ """ -+ Get the dependencies by just looking recursively at the #include statements -+ """ -+ -+ nodes = [] -+ names = [] -+ -+ def find_deps(node): -+ lst = lines_includes(node.abspath(env)) -+ -+ for (_, line) in lst: -+ (t, filename) = extract_include(line, defines) -+ if filename in names: -+ continue -+ -+ if filename.endswith('.moc'): -+ names.append(filename) -+ -+ found = None -+ for n in nodepaths: -+ if found: -+ break -+ found = n.find_resource(filename) -+ -+ if not found: -+ if not filename in names: -+ names.append(filename) -+ elif not found in nodes: -+ nodes.append(found) -+ find_deps(node) -+ -+ find_deps(node) -+ return (nodes, names) -+ -+ -diff --git a/buildtools/wafadmin/Tools/python.py b/buildtools/wafadmin/Tools/python.py -new file mode 100644 -index 0000000..4f73081 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/python.py -@@ -0,0 +1,413 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2007 (ita) -+# Gustavo Carneiro (gjc), 2007 -+ -+"Python support" -+ -+import os, sys -+import TaskGen, Utils, Utils, Runner, Options, Build -+from Logs import debug, warn, info -+from TaskGen import extension, taskgen, before, after, feature -+from Configure import conf -+ -+EXT_PY = ['.py'] -+FRAG_2 = ''' -+#include "Python.h" -+#ifdef __cplusplus -+extern "C" { -+#endif -+ void Py_Initialize(void); -+ void Py_Finalize(void); -+#ifdef __cplusplus -+} -+#endif -+int main() -+{ -+ Py_Initialize(); -+ Py_Finalize(); -+ return 0; -+} -+''' -+ -+@feature('pyext') -+@before('apply_incpaths', 'apply_lib_vars', 'apply_type_vars', 'apply_bundle') -+@after('vars_target_cshlib') -+def init_pyext(self): -+ self.default_install_path = '${PYTHONARCHDIR}' -+ self.uselib = self.to_list(getattr(self, 'uselib', '')) -+ if not 'PYEXT' in self.uselib: -+ self.uselib.append('PYEXT') -+ self.env['MACBUNDLE'] = True -+ -+@before('apply_link', 'apply_lib_vars', 'apply_type_vars') -+@after('apply_bundle') -+@feature('pyext') -+def pyext_shlib_ext(self): -+ # override shlib_PATTERN set by the osx module -+ self.env['shlib_PATTERN'] = self.env['pyext_PATTERN'] -+ -+@before('apply_incpaths', 'apply_lib_vars', 'apply_type_vars') -+@feature('pyembed') -+def init_pyembed(self): -+ self.uselib = self.to_list(getattr(self, 'uselib', '')) -+ if not 'PYEMBED' in self.uselib: -+ self.uselib.append('PYEMBED') -+ -+@extension(EXT_PY) -+def process_py(self, node): -+ if not (self.bld.is_install and self.install_path): -+ return -+ def inst_py(ctx): -+ install_pyfile(self, node) -+ self.bld.add_post_fun(inst_py) -+ -+def install_pyfile(self, node): -+ path = self.bld.get_install_path(self.install_path + os.sep + node.name, self.env) -+ -+ self.bld.install_files(self.install_path, [node], self.env, self.chmod, postpone=False) -+ if self.bld.is_install < 0: -+ info("* removing byte compiled python files") -+ for x in 'co': -+ try: -+ os.remove(path + x) -+ except OSError: -+ pass -+ -+ if self.bld.is_install > 0: -+ if self.env['PYC'] or self.env['PYO']: -+ info("* byte compiling %r" % path) -+ -+ if self.env['PYC']: -+ program = (""" -+import sys, py_compile -+for pyfile in sys.argv[1:]: -+ py_compile.compile(pyfile, pyfile + 'c') -+""") -+ argv = [self.env['PYTHON'], '-c', program, path] -+ ret = Utils.pproc.Popen(argv).wait() -+ if ret: -+ raise Utils.WafError('bytecode compilation failed %r' % path) -+ -+ if self.env['PYO']: -+ program = (""" -+import sys, py_compile -+for pyfile in sys.argv[1:]: -+ py_compile.compile(pyfile, pyfile + 'o') -+""") -+ argv = [self.env['PYTHON'], self.env['PYFLAGS_OPT'], '-c', program, path] -+ ret = Utils.pproc.Popen(argv).wait() -+ if ret: -+ raise Utils.WafError('bytecode compilation failed %r' % path) -+ -+# COMPAT -+class py_taskgen(TaskGen.task_gen): -+ def __init__(self, *k, **kw): -+ TaskGen.task_gen.__init__(self, *k, **kw) -+ -+@before('apply_core') -+@after('vars_target_cprogram', 'vars_target_cshlib') -+@feature('py') -+def init_py(self): -+ self.default_install_path = '${PYTHONDIR}' -+ -+def _get_python_variables(python_exe, variables, imports=['import sys']): -+ """Run a python interpreter and print some variables""" -+ program = list(imports) -+ program.append('') -+ for v in variables: -+ program.append("print(repr(%s))" % v) -+ os_env = dict(os.environ) -+ try: -+ del os_env['MACOSX_DEPLOYMENT_TARGET'] # see comments in the OSX tool -+ except KeyError: -+ pass -+ proc = Utils.pproc.Popen([python_exe, "-c", '\n'.join(program)], stdout=Utils.pproc.PIPE, env=os_env) -+ output = proc.communicate()[0].split("\n") # do not touch, python3 -+ if proc.returncode: -+ if Options.options.verbose: -+ warn("Python program to extract python configuration variables failed:\n%s" -+ % '\n'.join(["line %03i: %s" % (lineno+1, line) for lineno, line in enumerate(program)])) -+ raise RuntimeError -+ return_values = [] -+ for s in output: -+ s = s.strip() -+ if not s: -+ continue -+ if s == 'None': -+ return_values.append(None) -+ elif s[0] == "'" and s[-1] == "'": -+ return_values.append(s[1:-1]) -+ elif s[0].isdigit(): -+ return_values.append(int(s)) -+ else: break -+ return return_values -+ -+@conf -+def check_python_headers(conf, mandatory=True): -+ """Check for headers and libraries necessary to extend or embed python. -+ -+ On success the environment variables xxx_PYEXT and xxx_PYEMBED are added for uselib -+ -+ PYEXT: for compiling python extensions -+ PYEMBED: for embedding a python interpreter""" -+ -+ if not conf.env['CC_NAME'] and not conf.env['CXX_NAME']: -+ conf.fatal('load a compiler first (gcc, g++, ..)') -+ -+ if not conf.env['PYTHON_VERSION']: -+ conf.check_python_version() -+ -+ env = conf.env -+ python = env['PYTHON'] -+ if not python: -+ conf.fatal('could not find the python executable') -+ -+ ## On Mac OSX we need to use mac bundles for python plugins -+ if Options.platform == 'darwin': -+ conf.check_tool('osx') -+ -+ try: -+ # Get some python configuration variables using distutils -+ v = 'prefix SO SYSLIBS LDFLAGS SHLIBS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED MACOSX_DEPLOYMENT_TARGET'.split() -+ (python_prefix, python_SO, python_SYSLIBS, python_LDFLAGS, python_SHLIBS, -+ python_LIBDIR, python_LIBPL, INCLUDEPY, Py_ENABLE_SHARED, -+ python_MACOSX_DEPLOYMENT_TARGET) = \ -+ _get_python_variables(python, ["get_config_var('%s')" % x for x in v], -+ ['from distutils.sysconfig import get_config_var']) -+ except RuntimeError: -+ conf.fatal("Python development headers not found (-v for details).") -+ -+ conf.log.write("""Configuration returned from %r: -+python_prefix = %r -+python_SO = %r -+python_SYSLIBS = %r -+python_LDFLAGS = %r -+python_SHLIBS = %r -+python_LIBDIR = %r -+python_LIBPL = %r -+INCLUDEPY = %r -+Py_ENABLE_SHARED = %r -+MACOSX_DEPLOYMENT_TARGET = %r -+""" % (python, python_prefix, python_SO, python_SYSLIBS, python_LDFLAGS, python_SHLIBS, -+ python_LIBDIR, python_LIBPL, INCLUDEPY, Py_ENABLE_SHARED, python_MACOSX_DEPLOYMENT_TARGET)) -+ -+ if python_MACOSX_DEPLOYMENT_TARGET: -+ conf.env['MACOSX_DEPLOYMENT_TARGET'] = python_MACOSX_DEPLOYMENT_TARGET -+ conf.environ['MACOSX_DEPLOYMENT_TARGET'] = python_MACOSX_DEPLOYMENT_TARGET -+ -+ env['pyext_PATTERN'] = '%s'+python_SO -+ -+ # Check for python libraries for embedding -+ if python_SYSLIBS is not None: -+ for lib in python_SYSLIBS.split(): -+ if lib.startswith('-l'): -+ lib = lib[2:] # strip '-l' -+ env.append_value('LIB_PYEMBED', lib) -+ -+ if python_SHLIBS is not None: -+ for lib in python_SHLIBS.split(): -+ if lib.startswith('-l'): -+ env.append_value('LIB_PYEMBED', lib[2:]) # strip '-l' -+ else: -+ env.append_value('LINKFLAGS_PYEMBED', lib) -+ -+ if Options.platform != 'darwin' and python_LDFLAGS: -+ env.append_value('LINKFLAGS_PYEMBED', python_LDFLAGS.split()) -+ -+ result = False -+ name = 'python' + env['PYTHON_VERSION'] -+ -+ if python_LIBDIR is not None: -+ path = [python_LIBDIR] -+ conf.log.write("\n\n# Trying LIBDIR: %r\n" % path) -+ result = conf.check(lib=name, uselib='PYEMBED', libpath=path) -+ -+ if not result and python_LIBPL is not None: -+ conf.log.write("\n\n# try again with -L$python_LIBPL (some systems don't install the python library in $prefix/lib)\n") -+ path = [python_LIBPL] -+ result = conf.check(lib=name, uselib='PYEMBED', libpath=path) -+ -+ if not result: -+ conf.log.write("\n\n# try again with -L$prefix/libs, and pythonXY name rather than pythonX.Y (win32)\n") -+ path = [os.path.join(python_prefix, "libs")] -+ name = 'python' + env['PYTHON_VERSION'].replace('.', '') -+ result = conf.check(lib=name, uselib='PYEMBED', libpath=path) -+ -+ if result: -+ env['LIBPATH_PYEMBED'] = path -+ env.append_value('LIB_PYEMBED', name) -+ else: -+ conf.log.write("\n\n### LIB NOT FOUND\n") -+ -+ # under certain conditions, python extensions must link to -+ # python libraries, not just python embedding programs. -+ if (sys.platform == 'win32' or sys.platform.startswith('os2') -+ or sys.platform == 'darwin' or Py_ENABLE_SHARED): -+ env['LIBPATH_PYEXT'] = env['LIBPATH_PYEMBED'] -+ env['LIB_PYEXT'] = env['LIB_PYEMBED'] -+ -+ # We check that pythonX.Y-config exists, and if it exists we -+ # use it to get only the includes, else fall back to distutils. -+ python_config = conf.find_program( -+ 'python%s-config' % ('.'.join(env['PYTHON_VERSION'].split('.')[:2])), -+ var='PYTHON_CONFIG') -+ if not python_config: -+ python_config = conf.find_program( -+ 'python-config-%s' % ('.'.join(env['PYTHON_VERSION'].split('.')[:2])), -+ var='PYTHON_CONFIG') -+ -+ includes = [] -+ if python_config: -+ for incstr in Utils.cmd_output("%s %s --includes" % (python, python_config)).strip().split(): -+ # strip the -I or /I -+ if (incstr.startswith('-I') -+ or incstr.startswith('/I')): -+ incstr = incstr[2:] -+ # append include path, unless already given -+ if incstr not in includes: -+ includes.append(incstr) -+ conf.log.write("Include path for Python extensions " -+ "(found via python-config --includes): %r\n" % (includes,)) -+ env['CPPPATH_PYEXT'] = includes -+ env['CPPPATH_PYEMBED'] = includes -+ else: -+ conf.log.write("Include path for Python extensions " -+ "(found via distutils module): %r\n" % (INCLUDEPY,)) -+ env['CPPPATH_PYEXT'] = [INCLUDEPY] -+ env['CPPPATH_PYEMBED'] = [INCLUDEPY] -+ -+ # Code using the Python API needs to be compiled with -fno-strict-aliasing -+ if env['CC_NAME'] == 'gcc': -+ env.append_value('CCFLAGS_PYEMBED', '-fno-strict-aliasing') -+ env.append_value('CCFLAGS_PYEXT', '-fno-strict-aliasing') -+ if env['CXX_NAME'] == 'gcc': -+ env.append_value('CXXFLAGS_PYEMBED', '-fno-strict-aliasing') -+ env.append_value('CXXFLAGS_PYEXT', '-fno-strict-aliasing') -+ -+ # See if it compiles -+ conf.check(define_name='HAVE_PYTHON_H', -+ uselib='PYEMBED', fragment=FRAG_2, -+ errmsg='Could not find the python development headers', mandatory=mandatory) -+ -+@conf -+def check_python_version(conf, minver=None): -+ """ -+ Check if the python interpreter is found matching a given minimum version. -+ minver should be a tuple, eg. to check for python >= 2.4.2 pass (2,4,2) as minver. -+ -+ If successful, PYTHON_VERSION is defined as 'MAJOR.MINOR' -+ (eg. '2.4') of the actual python version found, and PYTHONDIR is -+ defined, pointing to the site-packages directory appropriate for -+ this python version, where modules/packages/extensions should be -+ installed. -+ """ -+ assert minver is None or isinstance(minver, tuple) -+ python = conf.env['PYTHON'] -+ if not python: -+ conf.fatal('could not find the python executable') -+ -+ # Get python version string -+ cmd = [python, "-c", "import sys\nfor x in sys.version_info: print(str(x))"] -+ debug('python: Running python command %r' % cmd) -+ proc = Utils.pproc.Popen(cmd, stdout=Utils.pproc.PIPE) -+ lines = proc.communicate()[0].split() -+ assert len(lines) == 5, "found %i lines, expected 5: %r" % (len(lines), lines) -+ pyver_tuple = (int(lines[0]), int(lines[1]), int(lines[2]), lines[3], int(lines[4])) -+ -+ # compare python version with the minimum required -+ result = (minver is None) or (pyver_tuple >= minver) -+ -+ if result: -+ # define useful environment variables -+ pyver = '.'.join([str(x) for x in pyver_tuple[:2]]) -+ conf.env['PYTHON_VERSION'] = pyver -+ -+ if 'PYTHONDIR' in conf.environ: -+ pydir = conf.environ['PYTHONDIR'] -+ else: -+ if sys.platform == 'win32': -+ (python_LIBDEST, pydir) = \ -+ _get_python_variables(python, -+ ["get_config_var('LIBDEST')", -+ "get_python_lib(standard_lib=0, prefix=%r)" % conf.env['PREFIX']], -+ ['from distutils.sysconfig import get_config_var, get_python_lib']) -+ else: -+ python_LIBDEST = None -+ (pydir,) = \ -+ _get_python_variables(python, -+ ["get_python_lib(standard_lib=0, prefix=%r)" % conf.env['PREFIX']], -+ ['from distutils.sysconfig import get_config_var, get_python_lib']) -+ if python_LIBDEST is None: -+ if conf.env['LIBDIR']: -+ python_LIBDEST = os.path.join(conf.env['LIBDIR'], "python" + pyver) -+ else: -+ python_LIBDEST = os.path.join(conf.env['PREFIX'], "lib", "python" + pyver) -+ -+ if 'PYTHONARCHDIR' in conf.environ: -+ pyarchdir = conf.environ['PYTHONARCHDIR'] -+ else: -+ (pyarchdir,) = _get_python_variables(python, -+ ["get_python_lib(plat_specific=1, standard_lib=0, prefix=%r)" % conf.env['PREFIX']], -+ ['from distutils.sysconfig import get_config_var, get_python_lib']) -+ if not pyarchdir: -+ pyarchdir = pydir -+ -+ if hasattr(conf, 'define'): # conf.define is added by the C tool, so may not exist -+ conf.define('PYTHONDIR', pydir) -+ conf.define('PYTHONARCHDIR', pyarchdir) -+ -+ conf.env['PYTHONDIR'] = pydir -+ -+ # Feedback -+ pyver_full = '.'.join(map(str, pyver_tuple[:3])) -+ if minver is None: -+ conf.check_message_custom('Python version', '', pyver_full) -+ else: -+ minver_str = '.'.join(map(str, minver)) -+ conf.check_message('Python version', ">= %s" % minver_str, result, option=pyver_full) -+ -+ if not result: -+ conf.fatal('The python version is too old (%r)' % pyver_full) -+ -+@conf -+def check_python_module(conf, module_name): -+ """ -+ Check if the selected python interpreter can import the given python module. -+ """ -+ result = not Utils.pproc.Popen([conf.env['PYTHON'], "-c", "import %s" % module_name], -+ stderr=Utils.pproc.PIPE, stdout=Utils.pproc.PIPE).wait() -+ conf.check_message('Python module', module_name, result) -+ if not result: -+ conf.fatal('Could not find the python module %r' % module_name) -+ -+def detect(conf): -+ -+ if not conf.env.PYTHON: -+ conf.env.PYTHON = sys.executable -+ -+ python = conf.find_program('python', var='PYTHON') -+ if not python: -+ conf.fatal('Could not find the path of the python executable') -+ -+ v = conf.env -+ -+ v['PYCMD'] = '"import sys, py_compile;py_compile.compile(sys.argv[1], sys.argv[2])"' -+ v['PYFLAGS'] = '' -+ v['PYFLAGS_OPT'] = '-O' -+ -+ v['PYC'] = getattr(Options.options, 'pyc', 1) -+ v['PYO'] = getattr(Options.options, 'pyo', 1) -+ -+def set_options(opt): -+ opt.add_option('--nopyc', -+ action='store_false', -+ default=1, -+ help = 'Do not install bytecode compiled .pyc files (configuration) [Default:install]', -+ dest = 'pyc') -+ opt.add_option('--nopyo', -+ action='store_false', -+ default=1, -+ help='Do not install optimised compiled .pyo files (configuration) [Default:install]', -+ dest='pyo') -+ -diff --git a/buildtools/wafadmin/Tools/qt4.py b/buildtools/wafadmin/Tools/qt4.py -new file mode 100644 -index 0000000..84d121a ---- /dev/null -+++ b/buildtools/wafadmin/Tools/qt4.py -@@ -0,0 +1,505 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006 (ita) -+ -+""" -+Qt4 support -+ -+If QT4_ROOT is given (absolute path), the configuration will look in it first -+ -+This module also demonstrates how to add tasks dynamically (when the build has started) -+""" -+ -+try: -+ from xml.sax import make_parser -+ from xml.sax.handler import ContentHandler -+except ImportError: -+ has_xml = False -+ ContentHandler = object -+else: -+ has_xml = True -+ -+import os, sys -+import ccroot, cxx -+import TaskGen, Task, Utils, Runner, Options, Node, Configure -+from TaskGen import taskgen, feature, after, extension -+from Logs import error -+from Constants import * -+ -+MOC_H = ['.h', '.hpp', '.hxx', '.hh'] -+EXT_RCC = ['.qrc'] -+EXT_UI = ['.ui'] -+EXT_QT4 = ['.cpp', '.cc', '.cxx', '.C'] -+ -+class qxx_task(Task.Task): -+ "A cpp task that may create a moc task dynamically" -+ -+ before = ['cxx_link', 'static_link'] -+ -+ def __init__(self, *k, **kw): -+ Task.Task.__init__(self, *k, **kw) -+ self.moc_done = 0 -+ -+ def scan(self): -+ (nodes, names) = ccroot.scan(self) -+ # for some reasons (variants) the moc node may end in the list of node deps -+ for x in nodes: -+ if x.name.endswith('.moc'): -+ nodes.remove(x) -+ names.append(x.relpath_gen(self.inputs[0].parent)) -+ return (nodes, names) -+ -+ def runnable_status(self): -+ if self.moc_done: -+ # if there is a moc task, delay the computation of the file signature -+ for t in self.run_after: -+ if not t.hasrun: -+ return ASK_LATER -+ # the moc file enters in the dependency calculation -+ # so we need to recompute the signature when the moc file is present -+ self.signature() -+ return Task.Task.runnable_status(self) -+ else: -+ # yes, really, there are people who generate cxx files -+ for t in self.run_after: -+ if not t.hasrun: -+ return ASK_LATER -+ self.add_moc_tasks() -+ return ASK_LATER -+ -+ def add_moc_tasks(self): -+ -+ node = self.inputs[0] -+ tree = node.__class__.bld -+ -+ try: -+ # compute the signature once to know if there is a moc file to create -+ self.signature() -+ except KeyError: -+ # the moc file may be referenced somewhere else -+ pass -+ else: -+ # remove the signature, it must be recomputed with the moc task -+ delattr(self, 'cache_sig') -+ -+ moctasks=[] -+ mocfiles=[] -+ variant = node.variant(self.env) -+ try: -+ tmp_lst = tree.raw_deps[self.unique_id()] -+ tree.raw_deps[self.unique_id()] = [] -+ except KeyError: -+ tmp_lst = [] -+ for d in tmp_lst: -+ if not d.endswith('.moc'): continue -+ # paranoid check -+ if d in mocfiles: -+ error("paranoia owns") -+ continue -+ -+ # process that base.moc only once -+ mocfiles.append(d) -+ -+ # find the extension (performed only when the .cpp has changes) -+ base2 = d[:-4] -+ for path in [node.parent] + self.generator.env['INC_PATHS']: -+ tree.rescan(path) -+ vals = getattr(Options.options, 'qt_header_ext', '') or MOC_H -+ for ex in vals: -+ h_node = path.find_resource(base2 + ex) -+ if h_node: -+ break -+ else: -+ continue -+ break -+ else: -+ raise Utils.WafError("no header found for %s which is a moc file" % str(d)) -+ -+ m_node = h_node.change_ext('.moc') -+ tree.node_deps[(self.inputs[0].parent.id, self.env.variant(), m_node.name)] = h_node -+ -+ # create the task -+ task = Task.TaskBase.classes['moc'](self.env, normal=0) -+ task.set_inputs(h_node) -+ task.set_outputs(m_node) -+ -+ generator = tree.generator -+ generator.outstanding.insert(0, task) -+ generator.total += 1 -+ -+ moctasks.append(task) -+ -+ # remove raw deps except the moc files to save space (optimization) -+ tmp_lst = tree.raw_deps[self.unique_id()] = mocfiles -+ -+ # look at the file inputs, it is set right above -+ lst = tree.node_deps.get(self.unique_id(), ()) -+ for d in lst: -+ name = d.name -+ if name.endswith('.moc'): -+ task = Task.TaskBase.classes['moc'](self.env, normal=0) -+ task.set_inputs(tree.node_deps[(self.inputs[0].parent.id, self.env.variant(), name)]) # 1st element in a tuple -+ task.set_outputs(d) -+ -+ generator = tree.generator -+ generator.outstanding.insert(0, task) -+ generator.total += 1 -+ -+ moctasks.append(task) -+ -+ # simple scheduler dependency: run the moc task before others -+ self.run_after = moctasks -+ self.moc_done = 1 -+ -+ run = Task.TaskBase.classes['cxx'].__dict__['run'] -+ -+def translation_update(task): -+ outs = [a.abspath(task.env) for a in task.outputs] -+ outs = " ".join(outs) -+ lupdate = task.env['QT_LUPDATE'] -+ -+ for x in task.inputs: -+ file = x.abspath(task.env) -+ cmd = "%s %s -ts %s" % (lupdate, file, outs) -+ Utils.pprint('BLUE', cmd) -+ task.generator.bld.exec_command(cmd) -+ -+class XMLHandler(ContentHandler): -+ def __init__(self): -+ self.buf = [] -+ self.files = [] -+ def startElement(self, name, attrs): -+ if name == 'file': -+ self.buf = [] -+ def endElement(self, name): -+ if name == 'file': -+ self.files.append(''.join(self.buf)) -+ def characters(self, cars): -+ self.buf.append(cars) -+ -+def scan(self): -+ "add the dependency on the files referenced in the qrc" -+ node = self.inputs[0] -+ parser = make_parser() -+ curHandler = XMLHandler() -+ parser.setContentHandler(curHandler) -+ fi = open(self.inputs[0].abspath(self.env)) -+ parser.parse(fi) -+ fi.close() -+ -+ nodes = [] -+ names = [] -+ root = self.inputs[0].parent -+ for x in curHandler.files: -+ nd = root.find_resource(x) -+ if nd: nodes.append(nd) -+ else: names.append(x) -+ -+ return (nodes, names) -+ -+@extension(EXT_RCC) -+def create_rcc_task(self, node): -+ "hook for rcc files" -+ rcnode = node.change_ext('_rc.cpp') -+ rcctask = self.create_task('rcc', node, rcnode) -+ cpptask = self.create_task('cxx', rcnode, rcnode.change_ext('.o')) -+ self.compiled_tasks.append(cpptask) -+ return cpptask -+ -+@extension(EXT_UI) -+def create_uic_task(self, node): -+ "hook for uic tasks" -+ uictask = self.create_task('ui4', node) -+ uictask.outputs = [self.path.find_or_declare(self.env['ui_PATTERN'] % node.name[:-3])] -+ return uictask -+ -+class qt4_taskgen(cxx.cxx_taskgen): -+ def __init__(self, *k, **kw): -+ cxx.cxx_taskgen.__init__(self, *k, **kw) -+ self.features.append('qt4') -+ -+@extension('.ts') -+def add_lang(self, node): -+ """add all the .ts file into self.lang""" -+ self.lang = self.to_list(getattr(self, 'lang', [])) + [node] -+ -+@feature('qt4') -+@after('apply_link') -+def apply_qt4(self): -+ if getattr(self, 'lang', None): -+ update = getattr(self, 'update', None) -+ lst=[] -+ trans=[] -+ for l in self.to_list(self.lang): -+ -+ if not isinstance(l, Node.Node): -+ l = self.path.find_resource(l+'.ts') -+ -+ t = self.create_task('ts2qm', l, l.change_ext('.qm')) -+ lst.append(t.outputs[0]) -+ -+ if update: -+ trans.append(t.inputs[0]) -+ -+ trans_qt4 = getattr(Options.options, 'trans_qt4', False) -+ if update and trans_qt4: -+ # we need the cpp files given, except the rcc task we create after -+ # FIXME may be broken -+ u = Task.TaskCmd(translation_update, self.env, 2) -+ u.inputs = [a.inputs[0] for a in self.compiled_tasks] -+ u.outputs = trans -+ -+ if getattr(self, 'langname', None): -+ t = Task.TaskBase.classes['qm2rcc'](self.env) -+ t.set_inputs(lst) -+ t.set_outputs(self.path.find_or_declare(self.langname+'.qrc')) -+ t.path = self.path -+ k = create_rcc_task(self, t.outputs[0]) -+ self.link_task.inputs.append(k.outputs[0]) -+ -+ self.env.append_value('MOC_FLAGS', self.env._CXXDEFFLAGS) -+ self.env.append_value('MOC_FLAGS', self.env._CXXINCFLAGS) -+ -+@extension(EXT_QT4) -+def cxx_hook(self, node): -+ # create the compilation task: cpp or cc -+ try: obj_ext = self.obj_ext -+ except AttributeError: obj_ext = '_%d.o' % self.idx -+ -+ task = self.create_task('qxx', node, node.change_ext(obj_ext)) -+ self.compiled_tasks.append(task) -+ return task -+ -+def process_qm2rcc(task): -+ outfile = task.outputs[0].abspath(task.env) -+ f = open(outfile, 'w') -+ f.write('\n\n') -+ for k in task.inputs: -+ f.write(' ') -+ #f.write(k.name) -+ f.write(k.path_to_parent(task.path)) -+ f.write('\n') -+ f.write('\n') -+ f.close() -+ -+b = Task.simple_task_type -+b('moc', '${QT_MOC} ${MOC_FLAGS} ${SRC} ${MOC_ST} ${TGT}', color='BLUE', vars=['QT_MOC', 'MOC_FLAGS'], shell=False) -+cls = b('rcc', '${QT_RCC} -name ${SRC[0].name} ${SRC[0].abspath(env)} ${RCC_ST} -o ${TGT}', color='BLUE', before='cxx moc qxx_task', after="qm2rcc", shell=False) -+cls.scan = scan -+b('ui4', '${QT_UIC} ${SRC} -o ${TGT}', color='BLUE', before='cxx moc qxx_task', shell=False) -+b('ts2qm', '${QT_LRELEASE} ${QT_LRELEASE_FLAGS} ${SRC} -qm ${TGT}', color='BLUE', before='qm2rcc', shell=False) -+ -+Task.task_type_from_func('qm2rcc', vars=[], func=process_qm2rcc, color='BLUE', before='rcc', after='ts2qm') -+ -+def detect_qt4(conf): -+ env = conf.env -+ opt = Options.options -+ -+ qtdir = getattr(opt, 'qtdir', '') -+ qtbin = getattr(opt, 'qtbin', '') -+ qtlibs = getattr(opt, 'qtlibs', '') -+ useframework = getattr(opt, 'use_qt4_osxframework', True) -+ -+ paths = [] -+ -+ # the path to qmake has been given explicitely -+ if qtbin: -+ paths = [qtbin] -+ -+ # the qt directory has been given - we deduce the qt binary path -+ if not qtdir: -+ qtdir = conf.environ.get('QT4_ROOT', '') -+ qtbin = os.path.join(qtdir, 'bin') -+ paths = [qtbin] -+ -+ # no qtdir, look in the path and in /usr/local/Trolltech -+ if not qtdir: -+ paths = os.environ.get('PATH', '').split(os.pathsep) -+ paths.append('/usr/share/qt4/bin/') -+ try: -+ lst = os.listdir('/usr/local/Trolltech/') -+ except OSError: -+ pass -+ else: -+ if lst: -+ lst.sort() -+ lst.reverse() -+ -+ # keep the highest version -+ qtdir = '/usr/local/Trolltech/%s/' % lst[0] -+ qtbin = os.path.join(qtdir, 'bin') -+ paths.append(qtbin) -+ -+ # at the end, try to find qmake in the paths given -+ # keep the one with the highest version -+ cand = None -+ prev_ver = ['4', '0', '0'] -+ for qmk in ['qmake-qt4', 'qmake4', 'qmake']: -+ qmake = conf.find_program(qmk, path_list=paths) -+ if qmake: -+ try: -+ version = Utils.cmd_output([qmake, '-query', 'QT_VERSION']).strip() -+ except ValueError: -+ pass -+ else: -+ if version: -+ new_ver = version.split('.') -+ if new_ver > prev_ver: -+ cand = qmake -+ prev_ver = new_ver -+ if cand: -+ qmake = cand -+ else: -+ conf.fatal('could not find qmake for qt4') -+ -+ conf.env.QMAKE = qmake -+ qtincludes = Utils.cmd_output([qmake, '-query', 'QT_INSTALL_HEADERS']).strip() -+ qtdir = Utils.cmd_output([qmake, '-query', 'QT_INSTALL_PREFIX']).strip() + os.sep -+ qtbin = Utils.cmd_output([qmake, '-query', 'QT_INSTALL_BINS']).strip() + os.sep -+ -+ if not qtlibs: -+ try: -+ qtlibs = Utils.cmd_output([qmake, '-query', 'QT_INSTALL_LIBS']).strip() + os.sep -+ except ValueError: -+ qtlibs = os.path.join(qtdir, 'lib') -+ -+ def find_bin(lst, var): -+ for f in lst: -+ ret = conf.find_program(f, path_list=paths) -+ if ret: -+ env[var]=ret -+ break -+ -+ vars = "QtCore QtGui QtUiTools QtNetwork QtOpenGL QtSql QtSvg QtTest QtXml QtWebKit Qt3Support".split() -+ -+ find_bin(['uic-qt3', 'uic3'], 'QT_UIC3') -+ find_bin(['uic-qt4', 'uic'], 'QT_UIC') -+ if not env['QT_UIC']: -+ conf.fatal('cannot find the uic compiler for qt4') -+ -+ try: -+ version = Utils.cmd_output(env['QT_UIC'] + " -version 2>&1").strip() -+ except ValueError: -+ conf.fatal('your uic compiler is for qt3, add uic for qt4 to your path') -+ -+ version = version.replace('Qt User Interface Compiler ','') -+ version = version.replace('User Interface Compiler for Qt', '') -+ if version.find(" 3.") != -1: -+ conf.check_message('uic version', '(too old)', 0, option='(%s)'%version) -+ sys.exit(1) -+ conf.check_message('uic version', '', 1, option='(%s)'%version) -+ -+ find_bin(['moc-qt4', 'moc'], 'QT_MOC') -+ find_bin(['rcc'], 'QT_RCC') -+ find_bin(['lrelease-qt4', 'lrelease'], 'QT_LRELEASE') -+ find_bin(['lupdate-qt4', 'lupdate'], 'QT_LUPDATE') -+ -+ env['UIC3_ST']= '%s -o %s' -+ env['UIC_ST'] = '%s -o %s' -+ env['MOC_ST'] = '-o' -+ env['ui_PATTERN'] = 'ui_%s.h' -+ env['QT_LRELEASE_FLAGS'] = ['-silent'] -+ -+ vars_debug = [a+'_debug' for a in vars] -+ -+ try: -+ conf.find_program('pkg-config', var='pkgconfig', path_list=paths, mandatory=True) -+ -+ except Configure.ConfigurationError: -+ -+ for lib in vars_debug+vars: -+ uselib = lib.upper() -+ -+ d = (lib.find('_debug') > 0) and 'd' or '' -+ -+ # original author seems to prefer static to shared libraries -+ for (pat, kind) in ((conf.env.staticlib_PATTERN, 'STATIC'), (conf.env.shlib_PATTERN, '')): -+ -+ conf.check_message_1('Checking for %s %s' % (lib, kind)) -+ -+ for ext in ['', '4']: -+ path = os.path.join(qtlibs, pat % (lib + d + ext)) -+ if os.path.exists(path): -+ env.append_unique(kind + 'LIB_' + uselib, lib + d + ext) -+ conf.check_message_2('ok ' + path, 'GREEN') -+ break -+ path = os.path.join(qtbin, pat % (lib + d + ext)) -+ if os.path.exists(path): -+ env.append_unique(kind + 'LIB_' + uselib, lib + d + ext) -+ conf.check_message_2('ok ' + path, 'GREEN') -+ break -+ else: -+ conf.check_message_2('not found', 'YELLOW') -+ continue -+ break -+ -+ env.append_unique('LIBPATH_' + uselib, qtlibs) -+ env.append_unique('CPPPATH_' + uselib, qtincludes) -+ env.append_unique('CPPPATH_' + uselib, qtincludes + os.sep + lib) -+ else: -+ for i in vars_debug+vars: -+ try: -+ conf.check_cfg(package=i, args='--cflags --libs --silence-errors', path=conf.env.pkgconfig) -+ except ValueError: -+ pass -+ -+ # the libpaths are set nicely, unfortunately they make really long command-lines -+ # remove the qtcore ones from qtgui, etc -+ def process_lib(vars_, coreval): -+ for d in vars_: -+ var = d.upper() -+ if var == 'QTCORE': continue -+ -+ value = env['LIBPATH_'+var] -+ if value: -+ core = env[coreval] -+ accu = [] -+ for lib in value: -+ if lib in core: continue -+ accu.append(lib) -+ env['LIBPATH_'+var] = accu -+ -+ process_lib(vars, 'LIBPATH_QTCORE') -+ process_lib(vars_debug, 'LIBPATH_QTCORE_DEBUG') -+ -+ # rpath if wanted -+ want_rpath = getattr(Options.options, 'want_rpath', 1) -+ if want_rpath: -+ def process_rpath(vars_, coreval): -+ for d in vars_: -+ var = d.upper() -+ value = env['LIBPATH_'+var] -+ if value: -+ core = env[coreval] -+ accu = [] -+ for lib in value: -+ if var != 'QTCORE': -+ if lib in core: -+ continue -+ accu.append('-Wl,--rpath='+lib) -+ env['RPATH_'+var] = accu -+ process_rpath(vars, 'LIBPATH_QTCORE') -+ process_rpath(vars_debug, 'LIBPATH_QTCORE_DEBUG') -+ -+ env['QTLOCALE'] = str(env['PREFIX'])+'/share/locale' -+ -+def detect(conf): -+ detect_qt4(conf) -+ -+def set_options(opt): -+ opt.add_option('--want-rpath', type='int', default=1, dest='want_rpath', help='set rpath to 1 or 0 [Default 1]') -+ -+ opt.add_option('--header-ext', -+ type='string', -+ default='', -+ help='header extension for moc files', -+ dest='qt_header_ext') -+ -+ for i in 'qtdir qtbin qtlibs'.split(): -+ opt.add_option('--'+i, type='string', default='', dest=i) -+ -+ if sys.platform == "darwin": -+ opt.add_option('--no-qt4-framework', action="store_false", help='do not use the framework version of Qt4 in OS X', dest='use_qt4_osxframework',default=True) -+ -+ opt.add_option('--translate', action="store_true", help="collect translation strings", dest="trans_qt4", default=False) -+ -diff --git a/buildtools/wafadmin/Tools/ruby.py b/buildtools/wafadmin/Tools/ruby.py -new file mode 100644 -index 0000000..d3b7569 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/ruby.py -@@ -0,0 +1,120 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# daniel.svensson at purplescout.se 2008 -+ -+import os -+import Task, Options, Utils -+from TaskGen import before, feature, after -+from Configure import conf -+ -+@feature('rubyext') -+@before('apply_incpaths', 'apply_type_vars', 'apply_lib_vars', 'apply_bundle') -+@after('default_cc', 'vars_target_cshlib') -+def init_rubyext(self): -+ self.default_install_path = '${ARCHDIR_RUBY}' -+ self.uselib = self.to_list(getattr(self, 'uselib', '')) -+ if not 'RUBY' in self.uselib: -+ self.uselib.append('RUBY') -+ if not 'RUBYEXT' in self.uselib: -+ self.uselib.append('RUBYEXT') -+ -+@feature('rubyext') -+@before('apply_link') -+def apply_ruby_so_name(self): -+ self.env['shlib_PATTERN'] = self.env['rubyext_PATTERN'] -+ -+@conf -+def check_ruby_version(conf, minver=()): -+ """ -+ Checks if ruby is installed. -+ If installed the variable RUBY will be set in environment. -+ Ruby binary can be overridden by --with-ruby-binary config variable -+ """ -+ -+ if Options.options.rubybinary: -+ conf.env.RUBY = Options.options.rubybinary -+ else: -+ conf.find_program("ruby", var="RUBY", mandatory=True) -+ -+ ruby = conf.env.RUBY -+ -+ try: -+ version = Utils.cmd_output([ruby, '-e', 'puts defined?(VERSION) ? VERSION : RUBY_VERSION']).strip() -+ except: -+ conf.fatal('could not determine ruby version') -+ conf.env.RUBY_VERSION = version -+ -+ try: -+ ver = tuple(map(int, version.split("."))) -+ except: -+ conf.fatal('unsupported ruby version %r' % version) -+ -+ cver = '' -+ if minver: -+ if ver < minver: -+ conf.fatal('ruby is too old') -+ cver = ".".join([str(x) for x in minver]) -+ -+ conf.check_message('ruby', cver, True, version) -+ -+@conf -+def check_ruby_ext_devel(conf): -+ if not conf.env.RUBY: -+ conf.fatal('ruby detection is required first') -+ -+ if not conf.env.CC_NAME and not conf.env.CXX_NAME: -+ conf.fatal('load a c/c++ compiler first') -+ -+ version = tuple(map(int, conf.env.RUBY_VERSION.split("."))) -+ -+ def read_out(cmd): -+ return Utils.to_list(Utils.cmd_output([conf.env.RUBY, '-rrbconfig', '-e', cmd])) -+ -+ def read_config(key): -+ return read_out('puts Config::CONFIG[%r]' % key) -+ -+ ruby = conf.env['RUBY'] -+ archdir = read_config('archdir') -+ cpppath = archdir -+ if version >= (1, 9, 0): -+ ruby_hdrdir = read_config('rubyhdrdir') -+ cpppath += ruby_hdrdir -+ cpppath += [os.path.join(ruby_hdrdir[0], read_config('arch')[0])] -+ -+ conf.check(header_name='ruby.h', includes=cpppath, mandatory=True, errmsg='could not find ruby header file') -+ -+ conf.env.LIBPATH_RUBYEXT = read_config('libdir') -+ conf.env.LIBPATH_RUBYEXT += archdir -+ conf.env.CPPPATH_RUBYEXT = cpppath -+ conf.env.CCFLAGS_RUBYEXT = read_config("CCDLFLAGS") -+ conf.env.rubyext_PATTERN = '%s.' + read_config('DLEXT')[0] -+ -+ # ok this is really stupid, but the command and flags are combined. -+ # so we try to find the first argument... -+ flags = read_config('LDSHARED') -+ while flags and flags[0][0] != '-': -+ flags = flags[1:] -+ -+ # we also want to strip out the deprecated ppc flags -+ if len(flags) > 1 and flags[1] == "ppc": -+ flags = flags[2:] -+ -+ conf.env.LINKFLAGS_RUBYEXT = flags -+ conf.env.LINKFLAGS_RUBYEXT += read_config("LIBS") -+ conf.env.LINKFLAGS_RUBYEXT += read_config("LIBRUBYARG_SHARED") -+ -+ if Options.options.rubyarchdir: -+ conf.env.ARCHDIR_RUBY = Options.options.rubyarchdir -+ else: -+ conf.env.ARCHDIR_RUBY = read_config('sitearchdir')[0] -+ -+ if Options.options.rubylibdir: -+ conf.env.LIBDIR_RUBY = Options.options.rubylibdir -+ else: -+ conf.env.LIBDIR_RUBY = read_config('sitelibdir')[0] -+ -+def set_options(opt): -+ opt.add_option('--with-ruby-archdir', type='string', dest='rubyarchdir', help='Specify directory where to install arch specific files') -+ opt.add_option('--with-ruby-libdir', type='string', dest='rubylibdir', help='Specify alternate ruby library path') -+ opt.add_option('--with-ruby-binary', type='string', dest='rubybinary', help='Specify alternate ruby binary') -+ -diff --git a/buildtools/wafadmin/Tools/suncc.py b/buildtools/wafadmin/Tools/suncc.py -new file mode 100644 -index 0000000..b1a2aad ---- /dev/null -+++ b/buildtools/wafadmin/Tools/suncc.py -@@ -0,0 +1,76 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006 (ita) -+# Ralf Habacker, 2006 (rh) -+ -+import os, optparse -+import Utils, Options, Configure -+import ccroot, ar -+from Configure import conftest -+ -+@conftest -+def find_scc(conf): -+ v = conf.env -+ cc = None -+ if v['CC']: cc = v['CC'] -+ elif 'CC' in conf.environ: cc = conf.environ['CC'] -+ #if not cc: cc = conf.find_program('gcc', var='CC') -+ if not cc: cc = conf.find_program('cc', var='CC') -+ if not cc: conf.fatal('suncc was not found') -+ cc = conf.cmd_to_list(cc) -+ -+ try: -+ if not Utils.cmd_output(cc + ['-flags']): -+ conf.fatal('suncc %r was not found' % cc) -+ except ValueError: -+ conf.fatal('suncc -flags could not be executed') -+ -+ v['CC'] = cc -+ v['CC_NAME'] = 'sun' -+ -+@conftest -+def scc_common_flags(conf): -+ v = conf.env -+ -+ # CPPFLAGS CCDEFINES _CCINCFLAGS _CCDEFFLAGS -+ -+ v['CC_SRC_F'] = '' -+ v['CC_TGT_F'] = ['-c', '-o', ''] -+ v['CPPPATH_ST'] = '-I%s' # template for adding include paths -+ -+ # linker -+ if not v['LINK_CC']: v['LINK_CC'] = v['CC'] -+ v['CCLNK_SRC_F'] = '' -+ v['CCLNK_TGT_F'] = ['-o', ''] # solaris hack, separate the -o from the target -+ -+ v['LIB_ST'] = '-l%s' # template for adding libs -+ v['LIBPATH_ST'] = '-L%s' # template for adding libpaths -+ v['STATICLIB_ST'] = '-l%s' -+ v['STATICLIBPATH_ST'] = '-L%s' -+ v['CCDEFINES_ST'] = '-D%s' -+ -+ v['SONAME_ST'] = '-Wl,-h -Wl,%s' -+ v['SHLIB_MARKER'] = '-Bdynamic' -+ v['STATICLIB_MARKER'] = '-Bstatic' -+ -+ # program -+ v['program_PATTERN'] = '%s' -+ -+ # shared library -+ v['shlib_CCFLAGS'] = ['-Kpic', '-DPIC'] -+ v['shlib_LINKFLAGS'] = ['-G'] -+ v['shlib_PATTERN'] = 'lib%s.so' -+ -+ # static lib -+ v['staticlib_LINKFLAGS'] = ['-Bstatic'] -+ v['staticlib_PATTERN'] = 'lib%s.a' -+ -+detect = ''' -+find_scc -+find_cpp -+find_ar -+scc_common_flags -+cc_load_tools -+cc_add_flags -+link_add_flags -+''' -diff --git a/buildtools/wafadmin/Tools/suncxx.py b/buildtools/wafadmin/Tools/suncxx.py -new file mode 100644 -index 0000000..8754b6c ---- /dev/null -+++ b/buildtools/wafadmin/Tools/suncxx.py -@@ -0,0 +1,75 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006 (ita) -+# Ralf Habacker, 2006 (rh) -+ -+import os, optparse -+import Utils, Options, Configure -+import ccroot, ar -+from Configure import conftest -+ -+@conftest -+def find_sxx(conf): -+ v = conf.env -+ cc = None -+ if v['CXX']: cc = v['CXX'] -+ elif 'CXX' in conf.environ: cc = conf.environ['CXX'] -+ if not cc: cc = conf.find_program('c++', var='CXX') -+ if not cc: conf.fatal('sunc++ was not found') -+ cc = conf.cmd_to_list(cc) -+ -+ try: -+ if not Utils.cmd_output(cc + ['-flags']): -+ conf.fatal('sunc++ %r was not found' % cc) -+ except ValueError: -+ conf.fatal('sunc++ -flags could not be executed') -+ -+ v['CXX'] = cc -+ v['CXX_NAME'] = 'sun' -+ -+@conftest -+def sxx_common_flags(conf): -+ v = conf.env -+ -+ # CPPFLAGS CXXDEFINES _CXXINCFLAGS _CXXDEFFLAGS -+ -+ v['CXX_SRC_F'] = '' -+ v['CXX_TGT_F'] = ['-c', '-o', ''] -+ v['CPPPATH_ST'] = '-I%s' # template for adding include paths -+ -+ # linker -+ if not v['LINK_CXX']: v['LINK_CXX'] = v['CXX'] -+ v['CXXLNK_SRC_F'] = '' -+ v['CXXLNK_TGT_F'] = ['-o', ''] # solaris hack, separate the -o from the target -+ -+ v['LIB_ST'] = '-l%s' # template for adding libs -+ v['LIBPATH_ST'] = '-L%s' # template for adding libpaths -+ v['STATICLIB_ST'] = '-l%s' -+ v['STATICLIBPATH_ST'] = '-L%s' -+ v['CXXDEFINES_ST'] = '-D%s' -+ -+ v['SONAME_ST'] = '-Wl,-h -Wl,%s' -+ v['SHLIB_MARKER'] = '-Bdynamic' -+ v['STATICLIB_MARKER'] = '-Bstatic' -+ -+ # program -+ v['program_PATTERN'] = '%s' -+ -+ # shared library -+ v['shlib_CXXFLAGS'] = ['-Kpic', '-DPIC'] -+ v['shlib_LINKFLAGS'] = ['-G'] -+ v['shlib_PATTERN'] = 'lib%s.so' -+ -+ # static lib -+ v['staticlib_LINKFLAGS'] = ['-Bstatic'] -+ v['staticlib_PATTERN'] = 'lib%s.a' -+ -+detect = ''' -+find_sxx -+find_cpp -+find_ar -+sxx_common_flags -+cxx_load_tools -+cxx_add_flags -+link_add_flags -+''' -diff --git a/buildtools/wafadmin/Tools/tex.py b/buildtools/wafadmin/Tools/tex.py -new file mode 100644 -index 0000000..2dd748b ---- /dev/null -+++ b/buildtools/wafadmin/Tools/tex.py -@@ -0,0 +1,251 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006 (ita) -+ -+"TeX/LaTeX/PDFLaTeX support" -+ -+import os, re -+import Utils, TaskGen, Task, Runner, Build -+from TaskGen import feature, before -+from Logs import error, warn, debug -+ -+re_tex = re.compile(r'\\(?Pinclude|input|import|bringin|lstinputlisting){(?P[^{}]*)}', re.M) -+def scan(self): -+ node = self.inputs[0] -+ env = self.env -+ -+ nodes = [] -+ names = [] -+ if not node: return (nodes, names) -+ -+ code = Utils.readf(node.abspath(env)) -+ -+ curdirnode = self.curdirnode -+ abs = curdirnode.abspath() -+ for match in re_tex.finditer(code): -+ path = match.group('file') -+ if path: -+ for k in ['', '.tex', '.ltx']: -+ # add another loop for the tex include paths? -+ debug('tex: trying %s%s' % (path, k)) -+ try: -+ os.stat(abs+os.sep+path+k) -+ except OSError: -+ continue -+ found = path+k -+ node = curdirnode.find_resource(found) -+ if node: -+ nodes.append(node) -+ else: -+ debug('tex: could not find %s' % path) -+ names.append(path) -+ -+ debug("tex: found the following : %s and names %s" % (nodes, names)) -+ return (nodes, names) -+ -+latex_fun, _ = Task.compile_fun('latex', '${LATEX} ${LATEXFLAGS} ${SRCFILE}', shell=False) -+pdflatex_fun, _ = Task.compile_fun('pdflatex', '${PDFLATEX} ${PDFLATEXFLAGS} ${SRCFILE}', shell=False) -+bibtex_fun, _ = Task.compile_fun('bibtex', '${BIBTEX} ${BIBTEXFLAGS} ${SRCFILE}', shell=False) -+makeindex_fun, _ = Task.compile_fun('bibtex', '${MAKEINDEX} ${MAKEINDEXFLAGS} ${SRCFILE}', shell=False) -+ -+g_bibtex_re = re.compile('bibdata', re.M) -+def tex_build(task, command='LATEX'): -+ env = task.env -+ bld = task.generator.bld -+ -+ if not env['PROMPT_LATEX']: -+ env.append_value('LATEXFLAGS', '-interaction=batchmode') -+ env.append_value('PDFLATEXFLAGS', '-interaction=batchmode') -+ -+ fun = latex_fun -+ if command == 'PDFLATEX': -+ fun = pdflatex_fun -+ -+ node = task.inputs[0] -+ reldir = node.bld_dir(env) -+ -+ #lst = [] -+ #for c in Utils.split_path(reldir): -+ # if c: lst.append('..') -+ #srcfile = os.path.join(*(lst + [node.srcpath(env)])) -+ #sr2 = os.path.join(*(lst + [node.parent.srcpath(env)])) -+ srcfile = node.abspath(env) -+ sr2 = node.parent.abspath() + os.pathsep + node.parent.abspath(env) + os.pathsep -+ -+ aux_node = node.change_ext('.aux') -+ idx_node = node.change_ext('.idx') -+ -+ nm = aux_node.name -+ docuname = nm[ : len(nm) - 4 ] # 4 is the size of ".aux" -+ -+ # important, set the cwd for everybody -+ task.cwd = task.inputs[0].parent.abspath(task.env) -+ -+ -+ warn('first pass on %s' % command) -+ -+ task.env.env = {'TEXINPUTS': sr2} -+ task.env.SRCFILE = srcfile -+ ret = fun(task) -+ if ret: -+ return ret -+ -+ # look in the .aux file if there is a bibfile to process -+ try: -+ ct = Utils.readf(aux_node.abspath(env)) -+ except (OSError, IOError): -+ error('error bibtex scan') -+ else: -+ fo = g_bibtex_re.findall(ct) -+ -+ # there is a .aux file to process -+ if fo: -+ warn('calling bibtex') -+ -+ task.env.env = {'BIBINPUTS': sr2, 'BSTINPUTS': sr2} -+ task.env.SRCFILE = docuname -+ ret = bibtex_fun(task) -+ if ret: -+ error('error when calling bibtex %s' % docuname) -+ return ret -+ -+ # look on the filesystem if there is a .idx file to process -+ try: -+ idx_path = idx_node.abspath(env) -+ os.stat(idx_path) -+ except OSError: -+ error('error file.idx scan') -+ else: -+ warn('calling makeindex') -+ -+ task.env.SRCFILE = idx_node.name -+ task.env.env = {} -+ ret = makeindex_fun(task) -+ if ret: -+ error('error when calling makeindex %s' % idx_path) -+ return ret -+ -+ -+ hash = '' -+ i = 0 -+ while i < 10: -+ # prevent against infinite loops - one never knows -+ i += 1 -+ -+ # watch the contents of file.aux -+ prev_hash = hash -+ try: -+ hash = Utils.h_file(aux_node.abspath(env)) -+ except KeyError: -+ error('could not read aux.h -> %s' % aux_node.abspath(env)) -+ pass -+ -+ # debug -+ #print "hash is, ", hash, " ", old_hash -+ -+ # stop if file.aux does not change anymore -+ if hash and hash == prev_hash: -+ break -+ -+ # run the command -+ warn('calling %s' % command) -+ -+ task.env.env = {'TEXINPUTS': sr2 + os.pathsep} -+ task.env.SRCFILE = srcfile -+ ret = fun(task) -+ if ret: -+ error('error when calling %s %s' % (command, latex_compile_cmd)) -+ return ret -+ -+ return None # ok -+ -+latex_vardeps = ['LATEX', 'LATEXFLAGS'] -+def latex_build(task): -+ return tex_build(task, 'LATEX') -+ -+pdflatex_vardeps = ['PDFLATEX', 'PDFLATEXFLAGS'] -+def pdflatex_build(task): -+ return tex_build(task, 'PDFLATEX') -+ -+class tex_taskgen(TaskGen.task_gen): -+ def __init__(self, *k, **kw): -+ TaskGen.task_gen.__init__(self, *k, **kw) -+ -+@feature('tex') -+@before('apply_core') -+def apply_tex(self): -+ if not getattr(self, 'type', None) in ['latex', 'pdflatex']: -+ self.type = 'pdflatex' -+ -+ tree = self.bld -+ outs = Utils.to_list(getattr(self, 'outs', [])) -+ -+ # prompt for incomplete files (else the batchmode is used) -+ self.env['PROMPT_LATEX'] = getattr(self, 'prompt', 1) -+ -+ deps_lst = [] -+ -+ if getattr(self, 'deps', None): -+ deps = self.to_list(self.deps) -+ for filename in deps: -+ n = self.path.find_resource(filename) -+ if not n in deps_lst: deps_lst.append(n) -+ -+ self.source = self.to_list(self.source) -+ for filename in self.source: -+ base, ext = os.path.splitext(filename) -+ -+ node = self.path.find_resource(filename) -+ if not node: raise Utils.WafError('cannot find %s' % filename) -+ -+ if self.type == 'latex': -+ task = self.create_task('latex', node, node.change_ext('.dvi')) -+ elif self.type == 'pdflatex': -+ task = self.create_task('pdflatex', node, node.change_ext('.pdf')) -+ -+ task.env = self.env -+ task.curdirnode = self.path -+ -+ # add the manual dependencies -+ if deps_lst: -+ variant = node.variant(self.env) -+ try: -+ lst = tree.node_deps[task.unique_id()] -+ for n in deps_lst: -+ if not n in lst: -+ lst.append(n) -+ except KeyError: -+ tree.node_deps[task.unique_id()] = deps_lst -+ -+ if self.type == 'latex': -+ if 'ps' in outs: -+ tsk = self.create_task('dvips', task.outputs, node.change_ext('.ps')) -+ tsk.env.env = {'TEXINPUTS' : node.parent.abspath() + os.pathsep + self.path.abspath() + os.pathsep + self.path.abspath(self.env)} -+ if 'pdf' in outs: -+ tsk = self.create_task('dvipdf', task.outputs, node.change_ext('.pdf')) -+ tsk.env.env = {'TEXINPUTS' : node.parent.abspath() + os.pathsep + self.path.abspath() + os.pathsep + self.path.abspath(self.env)} -+ elif self.type == 'pdflatex': -+ if 'ps' in outs: -+ self.create_task('pdf2ps', task.outputs, node.change_ext('.ps')) -+ self.source = [] -+ -+def detect(conf): -+ v = conf.env -+ for p in 'tex latex pdflatex bibtex dvips dvipdf ps2pdf makeindex pdf2ps'.split(): -+ conf.find_program(p, var=p.upper()) -+ v[p.upper()+'FLAGS'] = '' -+ v['DVIPSFLAGS'] = '-Ppdf' -+ -+b = Task.simple_task_type -+b('tex', '${TEX} ${TEXFLAGS} ${SRC}', color='BLUE', shell=False) # not used anywhere -+b('bibtex', '${BIBTEX} ${BIBTEXFLAGS} ${SRC}', color='BLUE', shell=False) # not used anywhere -+b('dvips', '${DVIPS} ${DVIPSFLAGS} ${SRC} -o ${TGT}', color='BLUE', after="latex pdflatex tex bibtex", shell=False) -+b('dvipdf', '${DVIPDF} ${DVIPDFFLAGS} ${SRC} ${TGT}', color='BLUE', after="latex pdflatex tex bibtex", shell=False) -+b('pdf2ps', '${PDF2PS} ${PDF2PSFLAGS} ${SRC} ${TGT}', color='BLUE', after="dvipdf pdflatex", shell=False) -+ -+b = Task.task_type_from_func -+cls = b('latex', latex_build, vars=latex_vardeps) -+cls.scan = scan -+cls = b('pdflatex', pdflatex_build, vars=pdflatex_vardeps) -+cls.scan = scan -+ -diff --git a/buildtools/wafadmin/Tools/unittestw.py b/buildtools/wafadmin/Tools/unittestw.py -new file mode 100644 -index 0000000..0e30a51 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/unittestw.py -@@ -0,0 +1,310 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Carlos Rafael Giani, 2006 -+ -+""" -+Unit tests run in the shutdown() method, and for c/c++ programs -+ -+One should NOT have to give parameters to programs to execute -+ -+In the shutdown method, add the following code: -+ -+ >>> def shutdown(): -+ ... ut = UnitTest.unit_test() -+ ... ut.run() -+ ... ut.print_results() -+ -+ -+Each object to use as a unit test must be a program and must have X{obj.unit_test=1} -+""" -+import os, sys -+import Build, TaskGen, Utils, Options, Logs, Task -+from TaskGen import before, after, feature -+from Constants import * -+ -+class unit_test(object): -+ "Unit test representation" -+ def __init__(self): -+ self.returncode_ok = 0 # Unit test returncode considered OK. All returncodes differing from this one -+ # will cause the unit test to be marked as "FAILED". -+ -+ # The following variables are filled with data by run(). -+ -+ # print_results() uses these for printing the unit test summary, -+ # but if there is need for direct access to the results, -+ # they can be retrieved here, after calling run(). -+ -+ self.num_tests_ok = 0 # Number of successful unit tests -+ self.num_tests_failed = 0 # Number of failed unit tests -+ self.num_tests_err = 0 # Tests that have not even run -+ self.total_num_tests = 0 # Total amount of unit tests -+ self.max_label_length = 0 # Maximum label length (pretty-print the output) -+ -+ self.unit_tests = Utils.ordered_dict() # Unit test dictionary. Key: the label (unit test filename relative -+ # to the build dir), value: unit test filename with absolute path -+ self.unit_test_results = {} # Dictionary containing the unit test results. -+ # Key: the label, value: result (true = success false = failure) -+ self.unit_test_erroneous = {} # Dictionary indicating erroneous unit tests. -+ # Key: the label, value: true = unit test has an error false = unit test is ok -+ self.change_to_testfile_dir = False #True if the test file needs to be executed from the same dir -+ self.want_to_see_test_output = False #True to see the stdout from the testfile (for example check suites) -+ self.want_to_see_test_error = False #True to see the stderr from the testfile (for example check suites) -+ self.run_if_waf_does = 'check' #build was the old default -+ -+ def run(self): -+ "Run the unit tests and gather results (note: no output here)" -+ -+ self.num_tests_ok = 0 -+ self.num_tests_failed = 0 -+ self.num_tests_err = 0 -+ self.total_num_tests = 0 -+ self.max_label_length = 0 -+ -+ self.unit_tests = Utils.ordered_dict() -+ self.unit_test_results = {} -+ self.unit_test_erroneous = {} -+ -+ ld_library_path = [] -+ -+ # If waf is not building, don't run anything -+ if not Options.commands[self.run_if_waf_does]: return -+ -+ # Get the paths for the shared libraries, and obtain the unit tests to execute -+ for obj in Build.bld.all_task_gen: -+ try: -+ link_task = obj.link_task -+ except AttributeError: -+ pass -+ else: -+ lib_path = link_task.outputs[0].parent.abspath(obj.env) -+ if lib_path not in ld_library_path: -+ ld_library_path.append(lib_path) -+ -+ unit_test = getattr(obj, 'unit_test', '') -+ if unit_test and 'cprogram' in obj.features: -+ try: -+ output = obj.path -+ filename = os.path.join(output.abspath(obj.env), obj.target) -+ srcdir = output.abspath() -+ label = os.path.join(output.bldpath(obj.env), obj.target) -+ self.max_label_length = max(self.max_label_length, len(label)) -+ self.unit_tests[label] = (filename, srcdir) -+ except KeyError: -+ pass -+ self.total_num_tests = len(self.unit_tests) -+ # Now run the unit tests -+ Utils.pprint('GREEN', 'Running the unit tests') -+ count = 0 -+ result = 1 -+ -+ for label in self.unit_tests.allkeys: -+ file_and_src = self.unit_tests[label] -+ filename = file_and_src[0] -+ srcdir = file_and_src[1] -+ count += 1 -+ line = Build.bld.progress_line(count, self.total_num_tests, Logs.colors.GREEN, Logs.colors.NORMAL) -+ if Options.options.progress_bar and line: -+ sys.stderr.write(line) -+ sys.stderr.flush() -+ try: -+ kwargs = {} -+ kwargs['env'] = os.environ.copy() -+ if self.change_to_testfile_dir: -+ kwargs['cwd'] = srcdir -+ if not self.want_to_see_test_output: -+ kwargs['stdout'] = Utils.pproc.PIPE # PIPE for ignoring output -+ if not self.want_to_see_test_error: -+ kwargs['stderr'] = Utils.pproc.PIPE # PIPE for ignoring output -+ if ld_library_path: -+ v = kwargs['env'] -+ def add_path(dct, path, var): -+ dct[var] = os.pathsep.join(Utils.to_list(path) + [os.environ.get(var, '')]) -+ if sys.platform == 'win32': -+ add_path(v, ld_library_path, 'PATH') -+ elif sys.platform == 'darwin': -+ add_path(v, ld_library_path, 'DYLD_LIBRARY_PATH') -+ add_path(v, ld_library_path, 'LD_LIBRARY_PATH') -+ else: -+ add_path(v, ld_library_path, 'LD_LIBRARY_PATH') -+ -+ pp = Utils.pproc.Popen(filename, **kwargs) -+ (out, err) = pp.communicate() # uh, and the output is ignored?? - fortunately this is going to disappear -+ -+ result = int(pp.returncode == self.returncode_ok) -+ -+ if result: -+ self.num_tests_ok += 1 -+ else: -+ self.num_tests_failed += 1 -+ -+ self.unit_test_results[label] = result -+ self.unit_test_erroneous[label] = 0 -+ except OSError: -+ self.unit_test_erroneous[label] = 1 -+ self.num_tests_err += 1 -+ except KeyboardInterrupt: -+ pass -+ if Options.options.progress_bar: sys.stdout.write(Logs.colors.cursor_on) -+ -+ def print_results(self): -+ "Pretty-prints a summary of all unit tests, along with some statistics" -+ -+ # If waf is not building, don't output anything -+ if not Options.commands[self.run_if_waf_does]: return -+ -+ p = Utils.pprint -+ # Early quit if no tests were performed -+ if self.total_num_tests == 0: -+ p('YELLOW', 'No unit tests present') -+ return -+ -+ for label in self.unit_tests.allkeys: -+ filename = self.unit_tests[label] -+ err = 0 -+ result = 0 -+ -+ try: err = self.unit_test_erroneous[label] -+ except KeyError: pass -+ -+ try: result = self.unit_test_results[label] -+ except KeyError: pass -+ -+ n = self.max_label_length - len(label) -+ if err: n += 4 -+ elif result: n += 7 -+ else: n += 3 -+ -+ line = '%s %s' % (label, '.' * n) -+ -+ if err: p('RED', '%sERROR' % line) -+ elif result: p('GREEN', '%sOK' % line) -+ else: p('YELLOW', '%sFAILED' % line) -+ -+ percentage_ok = float(self.num_tests_ok) / float(self.total_num_tests) * 100.0 -+ percentage_failed = float(self.num_tests_failed) / float(self.total_num_tests) * 100.0 -+ percentage_erroneous = float(self.num_tests_err) / float(self.total_num_tests) * 100.0 -+ -+ p('NORMAL', ''' -+Successful tests: %i (%.1f%%) -+Failed tests: %i (%.1f%%) -+Erroneous tests: %i (%.1f%%) -+ -+Total number of tests: %i -+''' % (self.num_tests_ok, percentage_ok, self.num_tests_failed, percentage_failed, -+ self.num_tests_err, percentage_erroneous, self.total_num_tests)) -+ p('GREEN', 'Unit tests finished') -+ -+ -+############################################################################################ -+ -+""" -+New unit test system -+ -+The targets with feature 'test' are executed after they are built -+bld(features='cprogram cc test', ...) -+ -+To display the results: -+import UnitTest -+bld.add_post_fun(UnitTest.summary) -+""" -+ -+import threading -+testlock = threading.Lock() -+ -+def set_options(opt): -+ opt.add_option('--alltests', action='store_true', default=True, help='Exec all unit tests', dest='all_tests') -+ -+@feature('test') -+@after('apply_link', 'vars_target_cprogram') -+def make_test(self): -+ if not 'cprogram' in self.features: -+ Logs.error('test cannot be executed %s' % self) -+ return -+ -+ self.default_install_path = None -+ self.create_task('utest', self.link_task.outputs) -+ -+def exec_test(self): -+ -+ status = 0 -+ -+ variant = self.env.variant() -+ -+ filename = self.inputs[0].abspath(self.env) -+ self.ut_exec = getattr(self, 'ut_exec', [filename]) -+ if getattr(self.generator, 'ut_fun', None): -+ self.generator.ut_fun(self) -+ -+ try: -+ fu = getattr(self.generator.bld, 'all_test_paths') -+ except AttributeError: -+ fu = os.environ.copy() -+ self.generator.bld.all_test_paths = fu -+ -+ lst = [] -+ for obj in self.generator.bld.all_task_gen: -+ link_task = getattr(obj, 'link_task', None) -+ if link_task and link_task.env.variant() == variant: -+ lst.append(link_task.outputs[0].parent.abspath(obj.env)) -+ -+ def add_path(dct, path, var): -+ dct[var] = os.pathsep.join(Utils.to_list(path) + [os.environ.get(var, '')]) -+ -+ if sys.platform == 'win32': -+ add_path(fu, lst, 'PATH') -+ elif sys.platform == 'darwin': -+ add_path(fu, lst, 'DYLD_LIBRARY_PATH') -+ add_path(fu, lst, 'LD_LIBRARY_PATH') -+ else: -+ add_path(fu, lst, 'LD_LIBRARY_PATH') -+ -+ -+ cwd = getattr(self.generator, 'ut_cwd', '') or self.inputs[0].parent.abspath(self.env) -+ proc = Utils.pproc.Popen(self.ut_exec, cwd=cwd, env=fu, stderr=Utils.pproc.PIPE, stdout=Utils.pproc.PIPE) -+ (stdout, stderr) = proc.communicate() -+ -+ tup = (filename, proc.returncode, stdout, stderr) -+ self.generator.utest_result = tup -+ -+ testlock.acquire() -+ try: -+ bld = self.generator.bld -+ Logs.debug("ut: %r", tup) -+ try: -+ bld.utest_results.append(tup) -+ except AttributeError: -+ bld.utest_results = [tup] -+ finally: -+ testlock.release() -+ -+cls = Task.task_type_from_func('utest', func=exec_test, color='PINK', ext_in='.bin') -+ -+old = cls.runnable_status -+def test_status(self): -+ ret = old(self) -+ if ret == SKIP_ME and getattr(Options.options, 'all_tests', False): -+ return RUN_ME -+ return ret -+ -+cls.runnable_status = test_status -+cls.quiet = 1 -+ -+def summary(bld): -+ lst = getattr(bld, 'utest_results', []) -+ if lst: -+ Utils.pprint('CYAN', 'execution summary') -+ -+ total = len(lst) -+ tfail = len([x for x in lst if x[1]]) -+ -+ Utils.pprint('CYAN', ' tests that pass %d/%d' % (total-tfail, total)) -+ for (f, code, out, err) in lst: -+ if not code: -+ Utils.pprint('CYAN', ' %s' % f) -+ -+ Utils.pprint('CYAN', ' tests that fail %d/%d' % (tfail, total)) -+ for (f, code, out, err) in lst: -+ if code: -+ Utils.pprint('CYAN', ' %s' % f) -+ -+ -diff --git a/buildtools/wafadmin/Tools/vala.py b/buildtools/wafadmin/Tools/vala.py -new file mode 100644 -index 0000000..753ee8d ---- /dev/null -+++ b/buildtools/wafadmin/Tools/vala.py -@@ -0,0 +1,308 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Ali Sabil, 2007 -+ -+import os.path, shutil -+import Task, Runner, Utils, Logs, Build, Node, Options -+from TaskGen import extension, after, before -+ -+EXT_VALA = ['.vala', '.gs'] -+ -+class valac_task(Task.Task): -+ -+ vars = ("VALAC", "VALAC_VERSION", "VALAFLAGS") -+ before = ("cc", "cxx") -+ -+ def run(self): -+ env = self.env -+ inputs = [a.srcpath(env) for a in self.inputs] -+ valac = env['VALAC'] -+ vala_flags = env.get_flat('VALAFLAGS') -+ top_src = self.generator.bld.srcnode.abspath() -+ top_bld = self.generator.bld.srcnode.abspath(env) -+ -+ if env['VALAC_VERSION'] > (0, 1, 6): -+ cmd = [valac, '-C', '--quiet', vala_flags] -+ else: -+ cmd = [valac, '-C', vala_flags] -+ -+ if self.threading: -+ cmd.append('--thread') -+ -+ if self.profile: -+ cmd.append('--profile=%s' % self.profile) -+ -+ if self.target_glib: -+ cmd.append('--target-glib=%s' % self.target_glib) -+ -+ features = self.generator.features -+ -+ if 'cshlib' in features or 'cstaticlib' in features: -+ output_dir = self.outputs[0].bld_dir(env) -+ cmd.append('--library ' + self.target) -+ if env['VALAC_VERSION'] >= (0, 7, 0): -+ for x in self.outputs: -+ if x.name.endswith('.h'): -+ cmd.append('--header ' + x.bldpath(self.env)) -+ cmd.append('--basedir ' + top_src) -+ cmd.append('-d ' + top_bld) -+ if env['VALAC_VERSION'] > (0, 7, 2) and hasattr(self, 'gir'): -+ cmd.append('--gir=%s.gir' % self.gir) -+ -+ else: -+ output_dir = self.outputs[0].bld_dir(env) -+ cmd.append('-d %s' % output_dir) -+ -+ for vapi_dir in self.vapi_dirs: -+ cmd.append('--vapidir=%s' % vapi_dir) -+ -+ for package in self.packages: -+ cmd.append('--pkg %s' % package) -+ -+ for package in self.packages_private: -+ cmd.append('--pkg %s' % package) -+ -+ cmd.append(" ".join(inputs)) -+ result = self.generator.bld.exec_command(" ".join(cmd)) -+ -+ if not 'cprogram' in features: -+ # generate the .deps file -+ if self.packages: -+ filename = os.path.join(self.generator.path.abspath(env), "%s.deps" % self.target) -+ deps = open(filename, 'w') -+ for package in self.packages: -+ deps.write(package + '\n') -+ deps.close() -+ -+ # handle vala 0.1.6 who doesn't honor --directory for the generated .vapi -+ self._fix_output("../%s.vapi" % self.target) -+ # handle vala >= 0.1.7 who has a weid definition for --directory -+ self._fix_output("%s.vapi" % self.target) -+ # handle vala >= 0.2.0 who doesn't honor --directory for the generated .gidl -+ self._fix_output("%s.gidl" % self.target) -+ # handle vala >= 0.3.6 who doesn't honor --directory for the generated .gir -+ self._fix_output("%s.gir" % self.target) -+ if hasattr(self, 'gir'): -+ self._fix_output("%s.gir" % self.gir) -+ -+ first = None -+ for node in self.outputs: -+ if not first: -+ first = node -+ else: -+ if first.parent.id != node.parent.id: -+ # issue #483 -+ if env['VALAC_VERSION'] < (0, 7, 0): -+ shutil.move(first.parent.abspath(self.env) + os.sep + node.name, node.abspath(self.env)) -+ return result -+ -+ def install(self): -+ bld = self.generator.bld -+ features = self.generator.features -+ -+ if self.attr("install_path") and ("cshlib" in features or "cstaticlib" in features): -+ headers_list = [o for o in self.outputs if o.suffix() == ".h"] -+ vapi_list = [o for o in self.outputs if (o.suffix() in (".vapi", ".deps"))] -+ gir_list = [o for o in self.outputs if o.suffix() == ".gir"] -+ -+ for header in headers_list: -+ top_src = self.generator.bld.srcnode -+ package = self.env['PACKAGE'] -+ try: -+ api_version = Utils.g_module.API_VERSION -+ except AttributeError: -+ version = Utils.g_module.VERSION.split(".") -+ if version[0] == "0": -+ api_version = "0." + version[1] -+ else: -+ api_version = version[0] + ".0" -+ install_path = '${INCLUDEDIR}/%s-%s/%s' % (package, api_version, header.relpath_gen(top_src)) -+ bld.install_as(install_path, header, self.env) -+ bld.install_files('${DATAROOTDIR}/vala/vapi', vapi_list, self.env) -+ bld.install_files('${DATAROOTDIR}/gir-1.0', gir_list, self.env) -+ -+ def _fix_output(self, output): -+ top_bld = self.generator.bld.srcnode.abspath(self.env) -+ try: -+ src = os.path.join(top_bld, output) -+ dst = self.generator.path.abspath (self.env) -+ shutil.move(src, dst) -+ except: -+ pass -+ -+@extension(EXT_VALA) -+def vala_file(self, node): -+ valatask = getattr(self, "valatask", None) -+ # there is only one vala task and it compiles all vala files .. :-/ -+ if not valatask: -+ valatask = self.create_task('valac') -+ self.valatask = valatask -+ self.includes = Utils.to_list(getattr(self, 'includes', [])) -+ self.uselib = self.to_list(self.uselib) -+ valatask.packages = [] -+ valatask.packages_private = Utils.to_list(getattr(self, 'packages_private', [])) -+ valatask.vapi_dirs = [] -+ valatask.target = self.target -+ valatask.threading = False -+ valatask.install_path = self.install_path -+ valatask.profile = getattr (self, 'profile', 'gobject') -+ valatask.target_glib = None #Deprecated -+ -+ packages = Utils.to_list(getattr(self, 'packages', [])) -+ vapi_dirs = Utils.to_list(getattr(self, 'vapi_dirs', [])) -+ includes = [] -+ -+ if hasattr(self, 'uselib_local'): -+ local_packages = Utils.to_list(self.uselib_local) -+ seen = [] -+ while len(local_packages) > 0: -+ package = local_packages.pop() -+ if package in seen: -+ continue -+ seen.append(package) -+ -+ # check if the package exists -+ package_obj = self.name_to_obj(package) -+ if not package_obj: -+ raise Utils.WafError("object '%s' was not found in uselib_local (required by '%s')" % (package, self.name)) -+ -+ package_name = package_obj.target -+ package_node = package_obj.path -+ package_dir = package_node.relpath_gen(self.path) -+ -+ for task in package_obj.tasks: -+ for output in task.outputs: -+ if output.name == package_name + ".vapi": -+ valatask.set_run_after(task) -+ if package_name not in packages: -+ packages.append(package_name) -+ if package_dir not in vapi_dirs: -+ vapi_dirs.append(package_dir) -+ if package_dir not in includes: -+ includes.append(package_dir) -+ -+ if hasattr(package_obj, 'uselib_local'): -+ lst = self.to_list(package_obj.uselib_local) -+ lst.reverse() -+ local_packages = [pkg for pkg in lst if pkg not in seen] + local_packages -+ -+ valatask.packages = packages -+ for vapi_dir in vapi_dirs: -+ try: -+ valatask.vapi_dirs.append(self.path.find_dir(vapi_dir).abspath()) -+ valatask.vapi_dirs.append(self.path.find_dir(vapi_dir).abspath(self.env)) -+ except AttributeError: -+ Logs.warn("Unable to locate Vala API directory: '%s'" % vapi_dir) -+ -+ self.includes.append(node.bld.srcnode.abspath()) -+ self.includes.append(node.bld.srcnode.abspath(self.env)) -+ for include in includes: -+ try: -+ self.includes.append(self.path.find_dir(include).abspath()) -+ self.includes.append(self.path.find_dir(include).abspath(self.env)) -+ except AttributeError: -+ Logs.warn("Unable to locate include directory: '%s'" % include) -+ -+ if valatask.profile == 'gobject': -+ if hasattr(self, 'target_glib'): -+ Logs.warn ('target_glib on vala tasks is deprecated --vala-target-glib=MAJOR.MINOR from the vala tool options') -+ -+ if getattr(Options.options, 'vala_target_glib', None): -+ valatask.target_glib = Options.options.vala_target_glib -+ -+ if not 'GOBJECT' in self.uselib: -+ self.uselib.append('GOBJECT') -+ -+ if hasattr(self, 'threading'): -+ if valatask.profile == 'gobject': -+ valatask.threading = self.threading -+ if not 'GTHREAD' in self.uselib: -+ self.uselib.append('GTHREAD') -+ else: -+ #Vala doesn't have threading support for dova nor posix -+ Logs.warn("Profile %s does not have threading support" % valatask.profile) -+ -+ if hasattr(self, 'gir'): -+ valatask.gir = self.gir -+ -+ env = valatask.env -+ -+ output_nodes = [] -+ -+ c_node = node.change_ext('.c') -+ output_nodes.append(c_node) -+ self.allnodes.append(c_node) -+ -+ if env['VALAC_VERSION'] < (0, 7, 0): -+ output_nodes.append(node.change_ext('.h')) -+ else: -+ if not 'cprogram' in self.features: -+ output_nodes.append(self.path.find_or_declare('%s.h' % self.target)) -+ -+ if not 'cprogram' in self.features: -+ output_nodes.append(self.path.find_or_declare('%s.vapi' % self.target)) -+ if env['VALAC_VERSION'] > (0, 7, 2): -+ if hasattr(self, 'gir'): -+ output_nodes.append(self.path.find_or_declare('%s.gir' % self.gir)) -+ elif env['VALAC_VERSION'] > (0, 3, 5): -+ output_nodes.append(self.path.find_or_declare('%s.gir' % self.target)) -+ elif env['VALAC_VERSION'] > (0, 1, 7): -+ output_nodes.append(self.path.find_or_declare('%s.gidl' % self.target)) -+ if valatask.packages: -+ output_nodes.append(self.path.find_or_declare('%s.deps' % self.target)) -+ -+ valatask.inputs.append(node) -+ valatask.outputs.extend(output_nodes) -+ -+def detect(conf): -+ min_version = (0, 1, 6) -+ min_version_str = "%d.%d.%d" % min_version -+ -+ valac = conf.find_program('valac', var='VALAC', mandatory=True) -+ -+ if not conf.env["HAVE_GOBJECT"]: -+ pkg_args = {'package': 'gobject-2.0', -+ 'uselib_store': 'GOBJECT', -+ 'args': '--cflags --libs'} -+ if getattr(Options.options, 'vala_target_glib', None): -+ pkg_args['atleast_version'] = Options.options.vala_target_glib -+ -+ conf.check_cfg(**pkg_args) -+ -+ if not conf.env["HAVE_GTHREAD"]: -+ pkg_args = {'package': 'gthread-2.0', -+ 'uselib_store': 'GTHREAD', -+ 'args': '--cflags --libs'} -+ if getattr(Options.options, 'vala_target_glib', None): -+ pkg_args['atleast_version'] = Options.options.vala_target_glib -+ -+ conf.check_cfg(**pkg_args) -+ -+ try: -+ output = Utils.cmd_output(valac + " --version", silent=True) -+ version = output.split(' ', 1)[-1].strip().split(".")[0:3] -+ version = [int(x) for x in version] -+ valac_version = tuple(version) -+ except Exception: -+ valac_version = (0, 0, 0) -+ -+ conf.check_message('program version', -+ 'valac >= ' + min_version_str, -+ valac_version >= min_version, -+ "%d.%d.%d" % valac_version) -+ -+ conf.check_tool('gnu_dirs') -+ -+ if valac_version < min_version: -+ conf.fatal("valac version too old to be used with this tool") -+ return -+ -+ conf.env['VALAC_VERSION'] = valac_version -+ conf.env['VALAFLAGS'] = '' -+ -+def set_options (opt): -+ valaopts = opt.add_option_group('Vala Compiler Options') -+ valaopts.add_option ('--vala-target-glib', default=None, -+ dest='vala_target_glib', metavar='MAJOR.MINOR', -+ help='Target version of glib for Vala GObject code generation') -+ -diff --git a/buildtools/wafadmin/Tools/winres.py b/buildtools/wafadmin/Tools/winres.py -new file mode 100644 -index 0000000..2500d43 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/winres.py -@@ -0,0 +1,45 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Brant Young, 2007 -+ -+"This hook is called when the class cpp/cc task generator encounters a '.rc' file: X{.rc -> [.res|.rc.o]}" -+ -+import os, sys, re -+import TaskGen, Task -+from Utils import quote_whitespace -+from TaskGen import extension -+ -+EXT_WINRC = ['.rc'] -+ -+winrc_str = '${WINRC} ${_CPPDEFFLAGS} ${_CCDEFFLAGS} ${WINRCFLAGS} ${_CPPINCFLAGS} ${_CCINCFLAGS} ${WINRC_TGT_F} ${TGT} ${WINRC_SRC_F} ${SRC}' -+ -+@extension(EXT_WINRC) -+def rc_file(self, node): -+ obj_ext = '.rc.o' -+ if self.env['WINRC_TGT_F'] == '/fo': obj_ext = '.res' -+ -+ rctask = self.create_task('winrc', node, node.change_ext(obj_ext)) -+ self.compiled_tasks.append(rctask) -+ -+# create our action, for use with rc file -+Task.simple_task_type('winrc', winrc_str, color='BLUE', before='cc cxx', shell=False) -+ -+def detect(conf): -+ v = conf.env -+ -+ winrc = v['WINRC'] -+ v['WINRC_TGT_F'] = '-o' -+ v['WINRC_SRC_F'] = '-i' -+ # find rc.exe -+ if not winrc: -+ if v['CC_NAME'] in ['gcc', 'cc', 'g++', 'c++']: -+ winrc = conf.find_program('windres', var='WINRC', path_list = v['PATH']) -+ elif v['CC_NAME'] == 'msvc': -+ winrc = conf.find_program('RC', var='WINRC', path_list = v['PATH']) -+ v['WINRC_TGT_F'] = '/fo' -+ v['WINRC_SRC_F'] = '' -+ if not winrc: -+ conf.fatal('winrc was not found!') -+ -+ v['WINRCFLAGS'] = '' -+ -diff --git a/buildtools/wafadmin/Tools/xlc.py b/buildtools/wafadmin/Tools/xlc.py -new file mode 100644 -index 0000000..e33b7a1 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/xlc.py -@@ -0,0 +1,78 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006-2008 (ita) -+# Ralf Habacker, 2006 (rh) -+# Yinon Ehrlich, 2009 -+# Michael Kuhn, 2009 -+ -+import os, sys -+import Configure, Options, Utils -+import ccroot, ar -+from Configure import conftest -+ -+@conftest -+def find_xlc(conf): -+ cc = conf.find_program(['xlc_r', 'xlc'], var='CC', mandatory=True) -+ cc = conf.cmd_to_list(cc) -+ conf.env.CC_NAME = 'xlc' -+ conf.env.CC = cc -+ -+@conftest -+def find_cpp(conf): -+ v = conf.env -+ cpp = None -+ if v['CPP']: cpp = v['CPP'] -+ elif 'CPP' in conf.environ: cpp = conf.environ['CPP'] -+ #if not cpp: cpp = v['CC'] -+ v['CPP'] = cpp -+ -+@conftest -+def xlc_common_flags(conf): -+ v = conf.env -+ -+ # CPPFLAGS CCDEFINES _CCINCFLAGS _CCDEFFLAGS -+ v['CCFLAGS_DEBUG'] = ['-g'] -+ v['CCFLAGS_RELEASE'] = ['-O2'] -+ -+ v['CC_SRC_F'] = '' -+ v['CC_TGT_F'] = ['-c', '-o', ''] # shell hack for -MD -+ v['CPPPATH_ST'] = '-I%s' # template for adding include paths -+ -+ # linker -+ if not v['LINK_CC']: v['LINK_CC'] = v['CC'] -+ v['CCLNK_SRC_F'] = '' -+ v['CCLNK_TGT_F'] = ['-o', ''] # shell hack for -MD -+ -+ v['LIB_ST'] = '-l%s' # template for adding libs -+ v['LIBPATH_ST'] = '-L%s' # template for adding libpaths -+ v['STATICLIB_ST'] = '-l%s' -+ v['STATICLIBPATH_ST'] = '-L%s' -+ v['RPATH_ST'] = '-Wl,-rpath,%s' -+ v['CCDEFINES_ST'] = '-D%s' -+ -+ v['SONAME_ST'] = '' -+ v['SHLIB_MARKER'] = '' -+ v['STATICLIB_MARKER'] = '' -+ v['FULLSTATIC_MARKER'] = '-static' -+ -+ # program -+ v['program_LINKFLAGS'] = ['-Wl,-brtl'] -+ v['program_PATTERN'] = '%s' -+ -+ # shared library -+ v['shlib_CCFLAGS'] = ['-fPIC', '-DPIC'] # avoid using -DPIC, -fPIC aleady defines the __PIC__ macro -+ v['shlib_LINKFLAGS'] = ['-G', '-Wl,-brtl,-bexpfull'] -+ v['shlib_PATTERN'] = 'lib%s.so' -+ -+ # static lib -+ v['staticlib_LINKFLAGS'] = '' -+ v['staticlib_PATTERN'] = 'lib%s.a' -+ -+def detect(conf): -+ conf.find_xlc() -+ conf.find_cpp() -+ conf.find_ar() -+ conf.xlc_common_flags() -+ conf.cc_load_tools() -+ conf.cc_add_flags() -+ conf.link_add_flags() -diff --git a/buildtools/wafadmin/Tools/xlcxx.py b/buildtools/wafadmin/Tools/xlcxx.py -new file mode 100644 -index 0000000..6e84662 ---- /dev/null -+++ b/buildtools/wafadmin/Tools/xlcxx.py -@@ -0,0 +1,78 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2006 (ita) -+# Ralf Habacker, 2006 (rh) -+# Yinon Ehrlich, 2009 -+# Michael Kuhn, 2009 -+ -+import os, sys -+import Configure, Options, Utils -+import ccroot, ar -+from Configure import conftest -+ -+@conftest -+def find_xlcxx(conf): -+ cxx = conf.find_program(['xlc++_r', 'xlc++'], var='CXX', mandatory=True) -+ cxx = conf.cmd_to_list(cxx) -+ conf.env.CXX_NAME = 'xlc++' -+ conf.env.CXX = cxx -+ -+@conftest -+def find_cpp(conf): -+ v = conf.env -+ cpp = None -+ if v['CPP']: cpp = v['CPP'] -+ elif 'CPP' in conf.environ: cpp = conf.environ['CPP'] -+ #if not cpp: cpp = v['CXX'] -+ v['CPP'] = cpp -+ -+@conftest -+def xlcxx_common_flags(conf): -+ v = conf.env -+ -+ # CPPFLAGS CXXDEFINES _CXXINCFLAGS _CXXDEFFLAGS -+ v['CXXFLAGS_DEBUG'] = ['-g'] -+ v['CXXFLAGS_RELEASE'] = ['-O2'] -+ -+ v['CXX_SRC_F'] = '' -+ v['CXX_TGT_F'] = ['-c', '-o', ''] # shell hack for -MD -+ v['CPPPATH_ST'] = '-I%s' # template for adding include paths -+ -+ # linker -+ if not v['LINK_CXX']: v['LINK_CXX'] = v['CXX'] -+ v['CXXLNK_SRC_F'] = '' -+ v['CXXLNK_TGT_F'] = ['-o', ''] # shell hack for -MD -+ -+ v['LIB_ST'] = '-l%s' # template for adding libs -+ v['LIBPATH_ST'] = '-L%s' # template for adding libpaths -+ v['STATICLIB_ST'] = '-l%s' -+ v['STATICLIBPATH_ST'] = '-L%s' -+ v['RPATH_ST'] = '-Wl,-rpath,%s' -+ v['CXXDEFINES_ST'] = '-D%s' -+ -+ v['SONAME_ST'] = '' -+ v['SHLIB_MARKER'] = '' -+ v['STATICLIB_MARKER'] = '' -+ v['FULLSTATIC_MARKER'] = '-static' -+ -+ # program -+ v['program_LINKFLAGS'] = ['-Wl,-brtl'] -+ v['program_PATTERN'] = '%s' -+ -+ # shared library -+ v['shlib_CXXFLAGS'] = ['-fPIC', '-DPIC'] # avoid using -DPIC, -fPIC aleady defines the __PIC__ macro -+ v['shlib_LINKFLAGS'] = ['-G', '-Wl,-brtl,-bexpfull'] -+ v['shlib_PATTERN'] = 'lib%s.so' -+ -+ # static lib -+ v['staticlib_LINKFLAGS'] = '' -+ v['staticlib_PATTERN'] = 'lib%s.a' -+ -+def detect(conf): -+ conf.find_xlcxx() -+ conf.find_cpp() -+ conf.find_ar() -+ conf.xlcxx_common_flags() -+ conf.cxx_load_tools() -+ conf.cxx_add_flags() -+ conf.link_add_flags() -diff --git a/buildtools/wafadmin/Utils.py b/buildtools/wafadmin/Utils.py -new file mode 100644 -index 0000000..41dad57 ---- /dev/null -+++ b/buildtools/wafadmin/Utils.py -@@ -0,0 +1,726 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2005 (ita) -+ -+""" -+Utilities, the stable ones are the following: -+ -+* h_file: compute a unique value for a file (hash), it uses -+ the module fnv if it is installed (see waf/utils/fnv & http://code.google.com/p/waf/wiki/FAQ) -+ else, md5 (see the python docs) -+ -+ For large projects (projects with more than 15000 files) or slow hard disks and filesystems (HFS) -+ it is possible to use a hashing based on the path and the size (may give broken cache results) -+ The method h_file MUST raise an OSError if the file is a folder -+ -+ import stat -+ def h_file(filename): -+ st = os.stat(filename) -+ if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('not a file') -+ m = Utils.md5() -+ m.update(str(st.st_mtime)) -+ m.update(str(st.st_size)) -+ m.update(filename) -+ return m.digest() -+ -+ To replace the function in your project, use something like this: -+ import Utils -+ Utils.h_file = h_file -+ -+* h_list -+* h_fun -+* get_term_cols -+* ordered_dict -+ -+""" -+ -+import os, sys, imp, string, errno, traceback, inspect, re, shutil, datetime, gc -+ -+# In python 3.0 we can get rid of all this -+try: from UserDict import UserDict -+except ImportError: from collections import UserDict -+if sys.hexversion >= 0x2060000 or os.name == 'java': -+ import subprocess as pproc -+else: -+ import pproc -+import Logs -+from Constants import * -+ -+try: -+ from collections import deque -+except ImportError: -+ class deque(list): -+ def popleft(self): -+ return self.pop(0) -+ -+is_win32 = sys.platform == 'win32' -+ -+try: -+ # defaultdict in python 2.5 -+ from collections import defaultdict as DefaultDict -+except ImportError: -+ class DefaultDict(dict): -+ def __init__(self, default_factory): -+ super(DefaultDict, self).__init__() -+ self.default_factory = default_factory -+ def __getitem__(self, key): -+ try: -+ return super(DefaultDict, self).__getitem__(key) -+ except KeyError: -+ value = self.default_factory() -+ self[key] = value -+ return value -+ -+class WafError(Exception): -+ def __init__(self, *args): -+ self.args = args -+ try: -+ self.stack = traceback.extract_stack() -+ except: -+ pass -+ Exception.__init__(self, *args) -+ def __str__(self): -+ return str(len(self.args) == 1 and self.args[0] or self.args) -+ -+class WscriptError(WafError): -+ def __init__(self, message, wscript_file=None): -+ if wscript_file: -+ self.wscript_file = wscript_file -+ self.wscript_line = None -+ else: -+ try: -+ (self.wscript_file, self.wscript_line) = self.locate_error() -+ except: -+ (self.wscript_file, self.wscript_line) = (None, None) -+ -+ msg_file_line = '' -+ if self.wscript_file: -+ msg_file_line = "%s:" % self.wscript_file -+ if self.wscript_line: -+ msg_file_line += "%s:" % self.wscript_line -+ err_message = "%s error: %s" % (msg_file_line, message) -+ WafError.__init__(self, err_message) -+ -+ def locate_error(self): -+ stack = traceback.extract_stack() -+ stack.reverse() -+ for frame in stack: -+ file_name = os.path.basename(frame[0]) -+ is_wscript = (file_name == WSCRIPT_FILE or file_name == WSCRIPT_BUILD_FILE) -+ if is_wscript: -+ return (frame[0], frame[1]) -+ return (None, None) -+ -+indicator = is_win32 and '\x1b[A\x1b[K%s%s%s\r' or '\x1b[K%s%s%s\r' -+ -+try: -+ from fnv import new as md5 -+ import Constants -+ Constants.SIG_NIL = 'signofnv' -+ -+ def h_file(filename): -+ m = md5() -+ try: -+ m.hfile(filename) -+ x = m.digest() -+ if x is None: raise OSError("not a file") -+ return x -+ except SystemError: -+ raise OSError("not a file" + filename) -+ -+except ImportError: -+ try: -+ try: -+ from hashlib import md5 -+ except ImportError: -+ from md5 import md5 -+ -+ def h_file(filename): -+ f = open(filename, 'rb') -+ m = md5() -+ while (filename): -+ filename = f.read(100000) -+ m.update(filename) -+ f.close() -+ return m.digest() -+ except ImportError: -+ # portability fixes may be added elsewhere (although, md5 should be everywhere by now) -+ md5 = None -+ -+class ordered_dict(UserDict): -+ def __init__(self, dict = None): -+ self.allkeys = [] -+ UserDict.__init__(self, dict) -+ -+ def __delitem__(self, key): -+ self.allkeys.remove(key) -+ UserDict.__delitem__(self, key) -+ -+ def __setitem__(self, key, item): -+ if key not in self.allkeys: self.allkeys.append(key) -+ UserDict.__setitem__(self, key, item) -+ -+def exec_command(s, **kw): -+ if 'log' in kw: -+ kw['stdout'] = kw['stderr'] = kw['log'] -+ del(kw['log']) -+ kw['shell'] = isinstance(s, str) -+ -+ try: -+ proc = pproc.Popen(s, **kw) -+ return proc.wait() -+ except OSError: -+ return -1 -+ -+if is_win32: -+ def exec_command(s, **kw): -+ if 'log' in kw: -+ kw['stdout'] = kw['stderr'] = kw['log'] -+ del(kw['log']) -+ kw['shell'] = isinstance(s, str) -+ -+ if len(s) > 2000: -+ startupinfo = pproc.STARTUPINFO() -+ startupinfo.dwFlags |= pproc.STARTF_USESHOWWINDOW -+ kw['startupinfo'] = startupinfo -+ -+ try: -+ if 'stdout' not in kw: -+ kw['stdout'] = pproc.PIPE -+ kw['stderr'] = pproc.PIPE -+ kw['universal_newlines'] = True -+ proc = pproc.Popen(s,**kw) -+ (stdout, stderr) = proc.communicate() -+ Logs.info(stdout) -+ if stderr: -+ Logs.error(stderr) -+ return proc.returncode -+ else: -+ proc = pproc.Popen(s,**kw) -+ return proc.wait() -+ except OSError: -+ return -1 -+ -+listdir = os.listdir -+if is_win32: -+ def listdir_win32(s): -+ if re.match('^[A-Za-z]:$', s): -+ # os.path.isdir fails if s contains only the drive name... (x:) -+ s += os.sep -+ if not os.path.isdir(s): -+ e = OSError() -+ e.errno = errno.ENOENT -+ raise e -+ return os.listdir(s) -+ listdir = listdir_win32 -+ -+def waf_version(mini = 0x010000, maxi = 0x100000): -+ "Halts if the waf version is wrong" -+ ver = HEXVERSION -+ try: min_val = mini + 0 -+ except TypeError: min_val = int(mini.replace('.', '0'), 16) -+ -+ if min_val > ver: -+ Logs.error("waf version should be at least %s (%s found)" % (mini, ver)) -+ sys.exit(1) -+ -+ try: max_val = maxi + 0 -+ except TypeError: max_val = int(maxi.replace('.', '0'), 16) -+ -+ if max_val < ver: -+ Logs.error("waf version should be at most %s (%s found)" % (maxi, ver)) -+ sys.exit(1) -+ -+def python_24_guard(): -+ if sys.hexversion < 0x20400f0 or sys.hexversion >= 0x3000000: -+ raise ImportError("Waf requires Python >= 2.3 but the raw source requires Python 2.4, 2.5 or 2.6") -+ -+def ex_stack(): -+ exc_type, exc_value, tb = sys.exc_info() -+ if Logs.verbose > 1: -+ exc_lines = traceback.format_exception(exc_type, exc_value, tb) -+ return ''.join(exc_lines) -+ return str(exc_value) -+ -+def to_list(sth): -+ if isinstance(sth, str): -+ return sth.split() -+ else: -+ return sth -+ -+g_loaded_modules = {} -+"index modules by absolute path" -+ -+g_module=None -+"the main module is special" -+ -+def load_module(file_path, name=WSCRIPT_FILE): -+ "this function requires an absolute path" -+ try: -+ return g_loaded_modules[file_path] -+ except KeyError: -+ pass -+ -+ module = imp.new_module(name) -+ -+ try: -+ code = readf(file_path, m='rU') -+ except (IOError, OSError): -+ raise WscriptError('Could not read the file %r' % file_path) -+ -+ module.waf_hash_val = code -+ -+ dt = os.path.dirname(file_path) -+ sys.path.insert(0, dt) -+ try: -+ exec(compile(code, file_path, 'exec'), module.__dict__) -+ except Exception: -+ exc_type, exc_value, tb = sys.exc_info() -+ raise WscriptError("".join(traceback.format_exception(exc_type, exc_value, tb)), file_path) -+ sys.path.remove(dt) -+ -+ g_loaded_modules[file_path] = module -+ -+ return module -+ -+def set_main_module(file_path): -+ "Load custom options, if defined" -+ global g_module -+ g_module = load_module(file_path, 'wscript_main') -+ g_module.root_path = file_path -+ -+ try: -+ g_module.APPNAME -+ except: -+ g_module.APPNAME = 'noname' -+ try: -+ g_module.VERSION -+ except: -+ g_module.VERSION = '1.0' -+ -+ # note: to register the module globally, use the following: -+ # sys.modules['wscript_main'] = g_module -+ -+def to_hashtable(s): -+ "used for importing env files" -+ tbl = {} -+ lst = s.split('\n') -+ for line in lst: -+ if not line: continue -+ mems = line.split('=') -+ tbl[mems[0]] = mems[1] -+ return tbl -+ -+def get_term_cols(): -+ "console width" -+ return 80 -+try: -+ import struct, fcntl, termios -+except ImportError: -+ pass -+else: -+ if Logs.got_tty: -+ def myfun(): -+ dummy_lines, cols = struct.unpack("HHHH", \ -+ fcntl.ioctl(sys.stderr.fileno(),termios.TIOCGWINSZ , \ -+ struct.pack("HHHH", 0, 0, 0, 0)))[:2] -+ return cols -+ # we actually try the function once to see if it is suitable -+ try: -+ myfun() -+ except: -+ pass -+ else: -+ get_term_cols = myfun -+ -+rot_idx = 0 -+rot_chr = ['\\', '|', '/', '-'] -+"the rotation character in the progress bar" -+ -+ -+def split_path(path): -+ return path.split('/') -+ -+def split_path_cygwin(path): -+ if path.startswith('//'): -+ ret = path.split('/')[2:] -+ ret[0] = '/' + ret[0] -+ return ret -+ return path.split('/') -+ -+re_sp = re.compile('[/\\\\]') -+def split_path_win32(path): -+ if path.startswith('\\\\'): -+ ret = re.split(re_sp, path)[2:] -+ ret[0] = '\\' + ret[0] -+ return ret -+ return re.split(re_sp, path) -+ -+if sys.platform == 'cygwin': -+ split_path = split_path_cygwin -+elif is_win32: -+ split_path = split_path_win32 -+ -+def copy_attrs(orig, dest, names, only_if_set=False): -+ for a in to_list(names): -+ u = getattr(orig, a, ()) -+ if u or not only_if_set: -+ setattr(dest, a, u) -+ -+def def_attrs(cls, **kw): -+ ''' -+ set attributes for class. -+ @param cls [any class]: the class to update the given attributes in. -+ @param kw [dictionary]: dictionary of attributes names and values. -+ -+ if the given class hasn't one (or more) of these attributes, add the attribute with its value to the class. -+ ''' -+ for k, v in kw.iteritems(): -+ if not hasattr(cls, k): -+ setattr(cls, k, v) -+ -+def quote_define_name(path): -+ fu = re.compile("[^a-zA-Z0-9]").sub("_", path) -+ fu = fu.upper() -+ return fu -+ -+def quote_whitespace(path): -+ return (path.strip().find(' ') > 0 and '"%s"' % path or path).replace('""', '"') -+ -+def trimquotes(s): -+ if not s: return '' -+ s = s.rstrip() -+ if s[0] == "'" and s[-1] == "'": return s[1:-1] -+ return s -+ -+def h_list(lst): -+ m = md5() -+ m.update(str(lst)) -+ return m.digest() -+ -+def h_fun(fun): -+ try: -+ return fun.code -+ except AttributeError: -+ try: -+ h = inspect.getsource(fun) -+ except IOError: -+ h = "nocode" -+ try: -+ fun.code = h -+ except AttributeError: -+ pass -+ return h -+ -+def pprint(col, str, label='', sep='\n'): -+ "print messages in color" -+ sys.stderr.write("%s%s%s %s%s" % (Logs.colors(col), str, Logs.colors.NORMAL, label, sep)) -+ -+def check_dir(dir): -+ """If a folder doesn't exists, create it.""" -+ try: -+ os.stat(dir) -+ except OSError: -+ try: -+ os.makedirs(dir) -+ except OSError, e: -+ raise WafError("Cannot create folder '%s' (original error: %s)" % (dir, e)) -+ -+def cmd_output(cmd, **kw): -+ -+ silent = False -+ if 'silent' in kw: -+ silent = kw['silent'] -+ del(kw['silent']) -+ -+ if 'e' in kw: -+ tmp = kw['e'] -+ del(kw['e']) -+ kw['env'] = tmp -+ -+ kw['shell'] = isinstance(cmd, str) -+ kw['stdout'] = pproc.PIPE -+ if silent: -+ kw['stderr'] = pproc.PIPE -+ -+ try: -+ p = pproc.Popen(cmd, **kw) -+ output = p.communicate()[0] -+ except OSError, e: -+ raise ValueError(str(e)) -+ -+ if p.returncode: -+ if not silent: -+ msg = "command execution failed: %s -> %r" % (cmd, str(output)) -+ raise ValueError(msg) -+ output = '' -+ return output -+ -+reg_subst = re.compile(r"(\\\\)|(\$\$)|\$\{([^}]+)\}") -+def subst_vars(expr, params): -+ "substitute ${PREFIX}/bin in /usr/local/bin" -+ def repl_var(m): -+ if m.group(1): -+ return '\\' -+ if m.group(2): -+ return '$' -+ try: -+ # environments may contain lists -+ return params.get_flat(m.group(3)) -+ except AttributeError: -+ return params[m.group(3)] -+ return reg_subst.sub(repl_var, expr) -+ -+def unversioned_sys_platform_to_binary_format(unversioned_sys_platform): -+ "infers the binary format from the unversioned_sys_platform name." -+ -+ if unversioned_sys_platform in ('linux', 'freebsd', 'netbsd', 'openbsd', 'sunos', 'gnu'): -+ return 'elf' -+ elif unversioned_sys_platform == 'darwin': -+ return 'mac-o' -+ elif unversioned_sys_platform in ('win32', 'cygwin', 'uwin', 'msys'): -+ return 'pe' -+ # TODO we assume all other operating systems are elf, which is not true. -+ # we may set this to 'unknown' and have ccroot and other tools handle the case "gracefully" (whatever that means). -+ return 'elf' -+ -+def unversioned_sys_platform(): -+ """returns an unversioned name from sys.platform. -+ sys.plaform is not very well defined and depends directly on the python source tree. -+ The version appended to the names is unreliable as it's taken from the build environment at the time python was built, -+ i.e., it's possible to get freebsd7 on a freebsd8 system. -+ So we remove the version from the name, except for special cases where the os has a stupid name like os2 or win32. -+ Some possible values of sys.platform are, amongst others: -+ aix3 aix4 atheos beos5 darwin freebsd2 freebsd3 freebsd4 freebsd5 freebsd6 freebsd7 -+ generic gnu0 irix5 irix6 linux2 mac netbsd1 next3 os2emx riscos sunos5 unixware7 -+ Investigating the python source tree may reveal more values. -+ """ -+ s = sys.platform -+ if s == 'java': -+ # The real OS is hidden under the JVM. -+ from java.lang import System -+ s = System.getProperty('os.name') -+ # see http://lopica.sourceforge.net/os.html for a list of possible values -+ if s == 'Mac OS X': -+ return 'darwin' -+ elif s.startswith('Windows '): -+ return 'win32' -+ elif s == 'OS/2': -+ return 'os2' -+ elif s == 'HP-UX': -+ return 'hpux' -+ elif s in ('SunOS', 'Solaris'): -+ return 'sunos' -+ else: s = s.lower() -+ if s == 'win32' or s.endswith('os2') and s != 'sunos2': return s -+ return re.split('\d+$', s)[0] -+ -+#@deprecated('use unversioned_sys_platform instead') -+def detect_platform(): -+ """this function has been in the Utils module for some time. -+ It's hard to guess what people have used it for. -+ It seems its goal is to return an unversionned sys.platform, but it's not handling all platforms. -+ For example, the version is not removed on freebsd and netbsd, amongst others. -+ """ -+ s = sys.platform -+ -+ # known POSIX -+ for x in 'cygwin linux irix sunos hpux aix darwin gnu'.split(): -+ # sys.platform may be linux2 -+ if s.find(x) >= 0: -+ return x -+ -+ # unknown POSIX -+ if os.name in 'posix java os2'.split(): -+ return os.name -+ -+ return s -+ -+def load_tool(tool, tooldir=None): -+ ''' -+ load_tool: import a Python module, optionally using several directories. -+ @param tool [string]: name of tool to import. -+ @param tooldir [list]: directories to look for the tool. -+ @return: the loaded module. -+ -+ Warning: this function is not thread-safe: plays with sys.path, -+ so must run in sequence. -+ ''' -+ if tooldir: -+ assert isinstance(tooldir, list) -+ sys.path = tooldir + sys.path -+ else: -+ tooldir = [] -+ try: -+ return __import__(tool) -+ finally: -+ for dt in tooldir: -+ sys.path.remove(dt) -+ -+def readf(fname, m='r'): -+ "get the contents of a file, it is not used anywhere for the moment" -+ f = open(fname, m) -+ try: -+ txt = f.read() -+ finally: -+ f.close() -+ return txt -+ -+def nada(*k, **kw): -+ """A function that does nothing""" -+ pass -+ -+def diff_path(top, subdir): -+ """difference between two absolute paths""" -+ top = os.path.normpath(top).replace('\\', '/').split('/') -+ subdir = os.path.normpath(subdir).replace('\\', '/').split('/') -+ if len(top) == len(subdir): return '' -+ diff = subdir[len(top) - len(subdir):] -+ return os.path.join(*diff) -+ -+class Context(object): -+ """A base class for commands to be executed from Waf scripts""" -+ -+ def set_curdir(self, dir): -+ self.curdir_ = dir -+ -+ def get_curdir(self): -+ try: -+ return self.curdir_ -+ except AttributeError: -+ self.curdir_ = os.getcwd() -+ return self.get_curdir() -+ -+ curdir = property(get_curdir, set_curdir) -+ -+ def recurse(self, dirs, name=''): -+ """The function for calling scripts from folders, it tries to call wscript + function_name -+ and if that file does not exist, it will call the method 'function_name' from a file named wscript -+ the dirs can be a list of folders or a string containing space-separated folder paths -+ """ -+ if not name: -+ name = inspect.stack()[1][3] -+ -+ if isinstance(dirs, str): -+ dirs = to_list(dirs) -+ -+ for x in dirs: -+ if os.path.isabs(x): -+ nexdir = x -+ else: -+ nexdir = os.path.join(self.curdir, x) -+ -+ base = os.path.join(nexdir, WSCRIPT_FILE) -+ file_path = base + '_' + name -+ -+ try: -+ txt = readf(file_path, m='rU') -+ except (OSError, IOError): -+ try: -+ module = load_module(base) -+ except OSError: -+ raise WscriptError('No such script %s' % base) -+ -+ try: -+ f = module.__dict__[name] -+ except KeyError: -+ raise WscriptError('No function %s defined in %s' % (name, base)) -+ -+ if getattr(self.__class__, 'pre_recurse', None): -+ self.pre_recurse(f, base, nexdir) -+ old = self.curdir -+ self.curdir = nexdir -+ try: -+ f(self) -+ finally: -+ self.curdir = old -+ if getattr(self.__class__, 'post_recurse', None): -+ self.post_recurse(module, base, nexdir) -+ else: -+ dc = {'ctx': self} -+ if getattr(self.__class__, 'pre_recurse', None): -+ dc = self.pre_recurse(txt, file_path, nexdir) -+ old = self.curdir -+ self.curdir = nexdir -+ try: -+ try: -+ exec(compile(txt, file_path, 'exec'), dc) -+ except Exception: -+ exc_type, exc_value, tb = sys.exc_info() -+ raise WscriptError("".join(traceback.format_exception(exc_type, exc_value, tb)), base) -+ finally: -+ self.curdir = old -+ if getattr(self.__class__, 'post_recurse', None): -+ self.post_recurse(txt, file_path, nexdir) -+ -+if is_win32: -+ old = shutil.copy2 -+ def copy2(src, dst): -+ old(src, dst) -+ shutil.copystat(src, src) -+ setattr(shutil, 'copy2', copy2) -+ -+def zip_folder(dir, zip_file_name, prefix): -+ """ -+ prefix represents the app to add in the archive -+ """ -+ import zipfile -+ zip = zipfile.ZipFile(zip_file_name, 'w', compression=zipfile.ZIP_DEFLATED) -+ base = os.path.abspath(dir) -+ -+ if prefix: -+ if prefix[-1] != os.sep: -+ prefix += os.sep -+ -+ n = len(base) -+ for root, dirs, files in os.walk(base): -+ for f in files: -+ archive_name = prefix + root[n:] + os.sep + f -+ zip.write(root + os.sep + f, archive_name, zipfile.ZIP_DEFLATED) -+ zip.close() -+ -+def get_elapsed_time(start): -+ "Format a time delta (datetime.timedelta) using the format DdHhMmS.MSs" -+ delta = datetime.datetime.now() - start -+ # cast to int necessary for python 3.0 -+ days = int(delta.days) -+ hours = int(delta.seconds / 3600) -+ minutes = int((delta.seconds - hours * 3600) / 60) -+ seconds = delta.seconds - hours * 3600 - minutes * 60 \ -+ + float(delta.microseconds) / 1000 / 1000 -+ result = '' -+ if days: -+ result += '%dd' % days -+ if days or hours: -+ result += '%dh' % hours -+ if days or hours or minutes: -+ result += '%dm' % minutes -+ return '%s%.3fs' % (result, seconds) -+ -+if os.name == 'java': -+ # For Jython (they should really fix the inconsistency) -+ try: -+ gc.disable() -+ gc.enable() -+ except NotImplementedError: -+ gc.disable = gc.enable -+ -+def run_once(fun): -+ """ -+ decorator, make a function cache its results, use like this: -+ -+ @run_once -+ def foo(k): -+ return 345*2343 -+ """ -+ cache = {} -+ def wrap(k): -+ try: -+ return cache[k] -+ except KeyError: -+ ret = fun(k) -+ cache[k] = ret -+ return ret -+ wrap.__cache__ = cache -+ return wrap -+ -diff --git a/buildtools/wafadmin/__init__.py b/buildtools/wafadmin/__init__.py -new file mode 100644 -index 0000000..01273cf ---- /dev/null -+++ b/buildtools/wafadmin/__init__.py -@@ -0,0 +1,3 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2005 (ita) -diff --git a/buildtools/wafadmin/ansiterm.py b/buildtools/wafadmin/ansiterm.py -new file mode 100644 -index 0000000..720b79c ---- /dev/null -+++ b/buildtools/wafadmin/ansiterm.py -@@ -0,0 +1,236 @@ -+import sys, os -+try: -+ if (not sys.stderr.isatty()) or (not sys.stdout.isatty()): -+ raise ValueError('not a tty') -+ -+ from ctypes import * -+ -+ class COORD(Structure): -+ _fields_ = [("X", c_short), ("Y", c_short)] -+ -+ class SMALL_RECT(Structure): -+ _fields_ = [("Left", c_short), ("Top", c_short), ("Right", c_short), ("Bottom", c_short)] -+ -+ class CONSOLE_SCREEN_BUFFER_INFO(Structure): -+ _fields_ = [("Size", COORD), ("CursorPosition", COORD), ("Attributes", c_short), ("Window", SMALL_RECT), ("MaximumWindowSize", COORD)] -+ -+ class CONSOLE_CURSOR_INFO(Structure): -+ _fields_ = [('dwSize',c_ulong), ('bVisible', c_int)] -+ -+ sbinfo = CONSOLE_SCREEN_BUFFER_INFO() -+ csinfo = CONSOLE_CURSOR_INFO() -+ hconsole = windll.kernel32.GetStdHandle(-11) -+ windll.kernel32.GetConsoleScreenBufferInfo(hconsole, byref(sbinfo)) -+ if sbinfo.Size.X < 10 or sbinfo.Size.Y < 10: raise Exception('small console') -+ windll.kernel32.GetConsoleCursorInfo(hconsole, byref(csinfo)) -+except Exception: -+ pass -+else: -+ import re, threading -+ -+ to_int = lambda number, default: number and int(number) or default -+ wlock = threading.Lock() -+ -+ STD_OUTPUT_HANDLE = -11 -+ STD_ERROR_HANDLE = -12 -+ -+ class AnsiTerm(object): -+ def __init__(self): -+ self.hconsole = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE) -+ self.cursor_history = [] -+ self.orig_sbinfo = CONSOLE_SCREEN_BUFFER_INFO() -+ self.orig_csinfo = CONSOLE_CURSOR_INFO() -+ windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(self.orig_sbinfo)) -+ windll.kernel32.GetConsoleCursorInfo(hconsole, byref(self.orig_csinfo)) -+ -+ -+ def screen_buffer_info(self): -+ sbinfo = CONSOLE_SCREEN_BUFFER_INFO() -+ windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(sbinfo)) -+ return sbinfo -+ -+ def clear_line(self, param): -+ mode = param and int(param) or 0 -+ sbinfo = self.screen_buffer_info() -+ if mode == 1: # Clear from begining of line to cursor position -+ line_start = COORD(0, sbinfo.CursorPosition.Y) -+ line_length = sbinfo.Size.X -+ elif mode == 2: # Clear entire line -+ line_start = COORD(sbinfo.CursorPosition.X, sbinfo.CursorPosition.Y) -+ line_length = sbinfo.Size.X - sbinfo.CursorPosition.X -+ else: # Clear from cursor position to end of line -+ line_start = sbinfo.CursorPosition -+ line_length = sbinfo.Size.X - sbinfo.CursorPosition.X -+ chars_written = c_int() -+ windll.kernel32.FillConsoleOutputCharacterA(self.hconsole, c_char(' '), line_length, line_start, byref(chars_written)) -+ windll.kernel32.FillConsoleOutputAttribute(self.hconsole, sbinfo.Attributes, line_length, line_start, byref(chars_written)) -+ -+ def clear_screen(self, param): -+ mode = to_int(param, 0) -+ sbinfo = self.screen_buffer_info() -+ if mode == 1: # Clear from begining of screen to cursor position -+ clear_start = COORD(0, 0) -+ clear_length = sbinfo.CursorPosition.X * sbinfo.CursorPosition.Y -+ elif mode == 2: # Clear entire screen and return cursor to home -+ clear_start = COORD(0, 0) -+ clear_length = sbinfo.Size.X * sbinfo.Size.Y -+ windll.kernel32.SetConsoleCursorPosition(self.hconsole, clear_start) -+ else: # Clear from cursor position to end of screen -+ clear_start = sbinfo.CursorPosition -+ clear_length = ((sbinfo.Size.X - sbinfo.CursorPosition.X) + sbinfo.Size.X * (sbinfo.Size.Y - sbinfo.CursorPosition.Y)) -+ chars_written = c_int() -+ windll.kernel32.FillConsoleOutputCharacterA(self.hconsole, c_char(' '), clear_length, clear_start, byref(chars_written)) -+ windll.kernel32.FillConsoleOutputAttribute(self.hconsole, sbinfo.Attributes, clear_length, clear_start, byref(chars_written)) -+ -+ def push_cursor(self, param): -+ sbinfo = self.screen_buffer_info() -+ self.cursor_history.push(sbinfo.CursorPosition) -+ -+ def pop_cursor(self, param): -+ if self.cursor_history: -+ old_pos = self.cursor_history.pop() -+ windll.kernel32.SetConsoleCursorPosition(self.hconsole, old_pos) -+ -+ def set_cursor(self, param): -+ x, sep, y = param.partition(';') -+ x = to_int(x, 1) - 1 -+ y = to_int(y, 1) - 1 -+ sbinfo = self.screen_buffer_info() -+ new_pos = COORD( -+ min(max(0, x), sbinfo.Size.X), -+ min(max(0, y), sbinfo.Size.Y) -+ ) -+ windll.kernel32.SetConsoleCursorPosition(self.hconsole, new_pos) -+ -+ def set_column(self, param): -+ x = to_int(param, 1) - 1 -+ sbinfo = self.screen_buffer_info() -+ new_pos = COORD( -+ min(max(0, x), sbinfo.Size.X), -+ sbinfo.CursorPosition.Y -+ ) -+ windll.kernel32.SetConsoleCursorPosition(self.hconsole, new_pos) -+ -+ def move_cursor(self, x_offset=0, y_offset=0): -+ sbinfo = self.screen_buffer_info() -+ new_pos = COORD( -+ min(max(0, sbinfo.CursorPosition.X + x_offset), sbinfo.Size.X), -+ min(max(0, sbinfo.CursorPosition.Y + y_offset), sbinfo.Size.Y) -+ ) -+ windll.kernel32.SetConsoleCursorPosition(self.hconsole, new_pos) -+ -+ def move_up(self, param): -+ self.move_cursor(y_offset = -to_int(param, 1)) -+ -+ def move_down(self, param): -+ self.move_cursor(y_offset = to_int(param, 1)) -+ -+ def move_left(self, param): -+ self.move_cursor(x_offset = -to_int(param, 1)) -+ -+ def move_right(self, param): -+ self.move_cursor(x_offset = to_int(param, 1)) -+ -+ def next_line(self, param): -+ sbinfo = self.screen_buffer_info() -+ self.move_cursor( -+ x_offset = -sbinfo.CursorPosition.X, -+ y_offset = to_int(param, 1) -+ ) -+ -+ def prev_line(self, param): -+ sbinfo = self.screen_buffer_info() -+ self.move_cursor( -+ x_offset = -sbinfo.CursorPosition.X, -+ y_offset = -to_int(param, 1) -+ ) -+ -+ escape_to_color = { (0, 30): 0x0, #black -+ (0, 31): 0x4, #red -+ (0, 32): 0x2, #green -+ (0, 33): 0x4+0x2, #dark yellow -+ (0, 34): 0x1, #blue -+ (0, 35): 0x1+0x4, #purple -+ (0, 36): 0x2+0x4, #cyan -+ (0, 37): 0x1+0x2+0x4, #grey -+ (1, 30): 0x1+0x2+0x4, #dark gray -+ (1, 31): 0x4+0x8, #red -+ (1, 32): 0x2+0x8, #light green -+ (1, 33): 0x4+0x2+0x8, #yellow -+ (1, 34): 0x1+0x8, #light blue -+ (1, 35): 0x1+0x4+0x8, #light purple -+ (1, 36): 0x1+0x2+0x8, #light cyan -+ (1, 37): 0x1+0x2+0x4+0x8, #white -+ } -+ -+ def set_color(self, param): -+ cols = param.split(';') -+ attr = self.orig_sbinfo.Attributes -+ for c in cols: -+ c = to_int(c, 0) -+ if c in range(30,38): -+ attr = (attr & 0xf0) | (self.escape_to_color.get((0,c), 0x7)) -+ elif c in range(40,48): -+ attr = (attr & 0x0f) | (self.escape_to_color.get((0,c), 0x7) << 8) -+ elif c in range(90,98): -+ attr = (attr & 0xf0) | (self.escape_to_color.get((1,c-60), 0x7)) -+ elif c in range(100,108): -+ attr = (attr & 0x0f) | (self.escape_to_color.get((1,c-60), 0x7) << 8) -+ elif c == 1: -+ attr |= 0x08 -+ windll.kernel32.SetConsoleTextAttribute(self.hconsole, attr) -+ -+ def show_cursor(self,param): -+ csinfo.bVisible = 1 -+ windll.kernel32.SetConsoleCursorInfo(self.hconsole, byref(csinfo)) -+ -+ def hide_cursor(self,param): -+ csinfo.bVisible = 0 -+ windll.kernel32.SetConsoleCursorInfo(self.hconsole, byref(csinfo)) -+ -+ ansi_command_table = { -+ 'A': move_up, -+ 'B': move_down, -+ 'C': move_right, -+ 'D': move_left, -+ 'E': next_line, -+ 'F': prev_line, -+ 'G': set_column, -+ 'H': set_cursor, -+ 'f': set_cursor, -+ 'J': clear_screen, -+ 'K': clear_line, -+ 'h': show_cursor, -+ 'l': hide_cursor, -+ 'm': set_color, -+ 's': push_cursor, -+ 'u': pop_cursor, -+ } -+ # Match either the escape sequence or text not containing escape sequence -+ ansi_tokans = re.compile('(?:\x1b\[([0-9?;]*)([a-zA-Z])|([^\x1b]+))') -+ def write(self, text): -+ try: -+ wlock.acquire() -+ for param, cmd, txt in self.ansi_tokans.findall(text): -+ if cmd: -+ cmd_func = self.ansi_command_table.get(cmd) -+ if cmd_func: -+ cmd_func(self, param) -+ else: -+ chars_written = c_int() -+ if isinstance(txt, unicode): -+ windll.kernel32.WriteConsoleW(self.hconsole, txt, len(txt), byref(chars_written), None) -+ else: -+ windll.kernel32.WriteConsoleA(self.hconsole, txt, len(txt), byref(chars_written), None) -+ finally: -+ wlock.release() -+ -+ def flush(self): -+ pass -+ -+ def isatty(self): -+ return True -+ -+ sys.stderr = sys.stdout = AnsiTerm() -+ os.environ['TERM'] = 'vt100' -+ -diff --git a/buildtools/wafadmin/pproc.py b/buildtools/wafadmin/pproc.py -new file mode 100644 -index 0000000..cb15178 ---- /dev/null -+++ b/buildtools/wafadmin/pproc.py -@@ -0,0 +1,620 @@ -+# borrowed from python 2.5.2c1 -+# Copyright (c) 2003-2005 by Peter Astrand -+# Licensed to PSF under a Contributor Agreement. -+ -+import sys -+mswindows = (sys.platform == "win32") -+ -+import os -+import types -+import traceback -+import gc -+ -+class CalledProcessError(Exception): -+ def __init__(self, returncode, cmd): -+ self.returncode = returncode -+ self.cmd = cmd -+ def __str__(self): -+ return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode) -+ -+if mswindows: -+ import threading -+ import msvcrt -+ if 0: -+ import pywintypes -+ from win32api import GetStdHandle, STD_INPUT_HANDLE, \ -+ STD_OUTPUT_HANDLE, STD_ERROR_HANDLE -+ from win32api import GetCurrentProcess, DuplicateHandle, \ -+ GetModuleFileName, GetVersion -+ from win32con import DUPLICATE_SAME_ACCESS, SW_HIDE -+ from win32pipe import CreatePipe -+ from win32process import CreateProcess, STARTUPINFO, \ -+ GetExitCodeProcess, STARTF_USESTDHANDLES, \ -+ STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE -+ from win32event import WaitForSingleObject, INFINITE, WAIT_OBJECT_0 -+ else: -+ from _subprocess import * -+ class STARTUPINFO: -+ dwFlags = 0 -+ hStdInput = None -+ hStdOutput = None -+ hStdError = None -+ wShowWindow = 0 -+ class pywintypes: -+ error = IOError -+else: -+ import select -+ import errno -+ import fcntl -+ import pickle -+ -+__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "CalledProcessError"] -+ -+try: -+ MAXFD = os.sysconf("SC_OPEN_MAX") -+except: -+ MAXFD = 256 -+ -+try: -+ False -+except NameError: -+ False = 0 -+ True = 1 -+ -+_active = [] -+ -+def _cleanup(): -+ for inst in _active[:]: -+ if inst.poll(_deadstate=sys.maxint) >= 0: -+ try: -+ _active.remove(inst) -+ except ValueError: -+ pass -+ -+PIPE = -1 -+STDOUT = -2 -+ -+ -+def call(*popenargs, **kwargs): -+ return Popen(*popenargs, **kwargs).wait() -+ -+def check_call(*popenargs, **kwargs): -+ retcode = call(*popenargs, **kwargs) -+ cmd = kwargs.get("args") -+ if cmd is None: -+ cmd = popenargs[0] -+ if retcode: -+ raise CalledProcessError(retcode, cmd) -+ return retcode -+ -+ -+def list2cmdline(seq): -+ result = [] -+ needquote = False -+ for arg in seq: -+ bs_buf = [] -+ -+ if result: -+ result.append(' ') -+ -+ needquote = (" " in arg) or ("\t" in arg) or arg == "" -+ if needquote: -+ result.append('"') -+ -+ for c in arg: -+ if c == '\\': -+ bs_buf.append(c) -+ elif c == '"': -+ result.append('\\' * len(bs_buf)*2) -+ bs_buf = [] -+ result.append('\\"') -+ else: -+ if bs_buf: -+ result.extend(bs_buf) -+ bs_buf = [] -+ result.append(c) -+ -+ if bs_buf: -+ result.extend(bs_buf) -+ -+ if needquote: -+ result.extend(bs_buf) -+ result.append('"') -+ -+ return ''.join(result) -+ -+class Popen(object): -+ def __init__(self, args, bufsize=0, executable=None, -+ stdin=None, stdout=None, stderr=None, -+ preexec_fn=None, close_fds=False, shell=False, -+ cwd=None, env=None, universal_newlines=False, -+ startupinfo=None, creationflags=0): -+ _cleanup() -+ -+ self._child_created = False -+ if not isinstance(bufsize, (int, long)): -+ raise TypeError("bufsize must be an integer") -+ -+ if mswindows: -+ if preexec_fn is not None: -+ raise ValueError("preexec_fn is not supported on Windows platforms") -+ if close_fds: -+ raise ValueError("close_fds is not supported on Windows platforms") -+ else: -+ if startupinfo is not None: -+ raise ValueError("startupinfo is only supported on Windows platforms") -+ if creationflags != 0: -+ raise ValueError("creationflags is only supported on Windows platforms") -+ -+ self.stdin = None -+ self.stdout = None -+ self.stderr = None -+ self.pid = None -+ self.returncode = None -+ self.universal_newlines = universal_newlines -+ -+ (p2cread, p2cwrite, -+ c2pread, c2pwrite, -+ errread, errwrite) = self._get_handles(stdin, stdout, stderr) -+ -+ self._execute_child(args, executable, preexec_fn, close_fds, -+ cwd, env, universal_newlines, -+ startupinfo, creationflags, shell, -+ p2cread, p2cwrite, -+ c2pread, c2pwrite, -+ errread, errwrite) -+ -+ if mswindows: -+ if stdin is None and p2cwrite is not None: -+ os.close(p2cwrite) -+ p2cwrite = None -+ if stdout is None and c2pread is not None: -+ os.close(c2pread) -+ c2pread = None -+ if stderr is None and errread is not None: -+ os.close(errread) -+ errread = None -+ -+ if p2cwrite: -+ self.stdin = os.fdopen(p2cwrite, 'wb', bufsize) -+ if c2pread: -+ if universal_newlines: -+ self.stdout = os.fdopen(c2pread, 'rU', bufsize) -+ else: -+ self.stdout = os.fdopen(c2pread, 'rb', bufsize) -+ if errread: -+ if universal_newlines: -+ self.stderr = os.fdopen(errread, 'rU', bufsize) -+ else: -+ self.stderr = os.fdopen(errread, 'rb', bufsize) -+ -+ -+ def _translate_newlines(self, data): -+ data = data.replace("\r\n", "\n") -+ data = data.replace("\r", "\n") -+ return data -+ -+ -+ def __del__(self, sys=sys): -+ if not self._child_created: -+ return -+ self.poll(_deadstate=sys.maxint) -+ if self.returncode is None and _active is not None: -+ _active.append(self) -+ -+ -+ def communicate(self, input=None): -+ if [self.stdin, self.stdout, self.stderr].count(None) >= 2: -+ stdout = None -+ stderr = None -+ if self.stdin: -+ if input: -+ self.stdin.write(input) -+ self.stdin.close() -+ elif self.stdout: -+ stdout = self.stdout.read() -+ elif self.stderr: -+ stderr = self.stderr.read() -+ self.wait() -+ return (stdout, stderr) -+ -+ return self._communicate(input) -+ -+ -+ if mswindows: -+ def _get_handles(self, stdin, stdout, stderr): -+ if stdin is None and stdout is None and stderr is None: -+ return (None, None, None, None, None, None) -+ -+ p2cread, p2cwrite = None, None -+ c2pread, c2pwrite = None, None -+ errread, errwrite = None, None -+ -+ if stdin is None: -+ p2cread = GetStdHandle(STD_INPUT_HANDLE) -+ if p2cread is not None: -+ pass -+ elif stdin is None or stdin == PIPE: -+ p2cread, p2cwrite = CreatePipe(None, 0) -+ p2cwrite = p2cwrite.Detach() -+ p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0) -+ elif isinstance(stdin, int): -+ p2cread = msvcrt.get_osfhandle(stdin) -+ else: -+ p2cread = msvcrt.get_osfhandle(stdin.fileno()) -+ p2cread = self._make_inheritable(p2cread) -+ -+ if stdout is None: -+ c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE) -+ if c2pwrite is not None: -+ pass -+ elif stdout is None or stdout == PIPE: -+ c2pread, c2pwrite = CreatePipe(None, 0) -+ c2pread = c2pread.Detach() -+ c2pread = msvcrt.open_osfhandle(c2pread, 0) -+ elif isinstance(stdout, int): -+ c2pwrite = msvcrt.get_osfhandle(stdout) -+ else: -+ c2pwrite = msvcrt.get_osfhandle(stdout.fileno()) -+ c2pwrite = self._make_inheritable(c2pwrite) -+ -+ if stderr is None: -+ errwrite = GetStdHandle(STD_ERROR_HANDLE) -+ if errwrite is not None: -+ pass -+ elif stderr is None or stderr == PIPE: -+ errread, errwrite = CreatePipe(None, 0) -+ errread = errread.Detach() -+ errread = msvcrt.open_osfhandle(errread, 0) -+ elif stderr == STDOUT: -+ errwrite = c2pwrite -+ elif isinstance(stderr, int): -+ errwrite = msvcrt.get_osfhandle(stderr) -+ else: -+ errwrite = msvcrt.get_osfhandle(stderr.fileno()) -+ errwrite = self._make_inheritable(errwrite) -+ -+ return (p2cread, p2cwrite, -+ c2pread, c2pwrite, -+ errread, errwrite) -+ def _make_inheritable(self, handle): -+ return DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), 0, 1, DUPLICATE_SAME_ACCESS) -+ -+ def _find_w9xpopen(self): -+ w9xpopen = os.path.join(os.path.dirname(GetModuleFileName(0)), "w9xpopen.exe") -+ if not os.path.exists(w9xpopen): -+ w9xpopen = os.path.join(os.path.dirname(sys.exec_prefix), "w9xpopen.exe") -+ if not os.path.exists(w9xpopen): -+ raise RuntimeError("Cannot locate w9xpopen.exe, which is needed for Popen to work with your shell or platform.") -+ return w9xpopen -+ -+ def _execute_child(self, args, executable, preexec_fn, close_fds, -+ cwd, env, universal_newlines, -+ startupinfo, creationflags, shell, -+ p2cread, p2cwrite, -+ c2pread, c2pwrite, -+ errread, errwrite): -+ -+ if not isinstance(args, types.StringTypes): -+ args = list2cmdline(args) -+ -+ if startupinfo is None: -+ startupinfo = STARTUPINFO() -+ if None not in (p2cread, c2pwrite, errwrite): -+ startupinfo.dwFlags |= STARTF_USESTDHANDLES -+ startupinfo.hStdInput = p2cread -+ startupinfo.hStdOutput = c2pwrite -+ startupinfo.hStdError = errwrite -+ -+ if shell: -+ startupinfo.dwFlags |= STARTF_USESHOWWINDOW -+ startupinfo.wShowWindow = SW_HIDE -+ comspec = os.environ.get("COMSPEC", "cmd.exe") -+ args = comspec + " /c " + args -+ if (GetVersion() >= 0x80000000L or -+ os.path.basename(comspec).lower() == "command.com"): -+ w9xpopen = self._find_w9xpopen() -+ args = '"%s" %s' % (w9xpopen, args) -+ creationflags |= CREATE_NEW_CONSOLE -+ -+ try: -+ hp, ht, pid, tid = CreateProcess(executable, args, None, None, 1, creationflags, env, cwd, startupinfo) -+ except pywintypes.error, e: -+ raise WindowsError(*e.args) -+ -+ self._child_created = True -+ self._handle = hp -+ self.pid = pid -+ ht.Close() -+ -+ if p2cread is not None: -+ p2cread.Close() -+ if c2pwrite is not None: -+ c2pwrite.Close() -+ if errwrite is not None: -+ errwrite.Close() -+ -+ -+ def poll(self, _deadstate=None): -+ if self.returncode is None: -+ if WaitForSingleObject(self._handle, 0) == WAIT_OBJECT_0: -+ self.returncode = GetExitCodeProcess(self._handle) -+ return self.returncode -+ -+ -+ def wait(self): -+ if self.returncode is None: -+ obj = WaitForSingleObject(self._handle, INFINITE) -+ self.returncode = GetExitCodeProcess(self._handle) -+ return self.returncode -+ -+ def _readerthread(self, fh, buffer): -+ buffer.append(fh.read()) -+ -+ def _communicate(self, input): -+ stdout = None -+ stderr = None -+ -+ if self.stdout: -+ stdout = [] -+ stdout_thread = threading.Thread(target=self._readerthread, args=(self.stdout, stdout)) -+ stdout_thread.setDaemon(True) -+ stdout_thread.start() -+ if self.stderr: -+ stderr = [] -+ stderr_thread = threading.Thread(target=self._readerthread, args=(self.stderr, stderr)) -+ stderr_thread.setDaemon(True) -+ stderr_thread.start() -+ -+ if self.stdin: -+ if input is not None: -+ self.stdin.write(input) -+ self.stdin.close() -+ -+ if self.stdout: -+ stdout_thread.join() -+ if self.stderr: -+ stderr_thread.join() -+ -+ if stdout is not None: -+ stdout = stdout[0] -+ if stderr is not None: -+ stderr = stderr[0] -+ -+ if self.universal_newlines and hasattr(file, 'newlines'): -+ if stdout: -+ stdout = self._translate_newlines(stdout) -+ if stderr: -+ stderr = self._translate_newlines(stderr) -+ -+ self.wait() -+ return (stdout, stderr) -+ -+ else: -+ def _get_handles(self, stdin, stdout, stderr): -+ p2cread, p2cwrite = None, None -+ c2pread, c2pwrite = None, None -+ errread, errwrite = None, None -+ -+ if stdin is None: -+ pass -+ elif stdin == PIPE: -+ p2cread, p2cwrite = os.pipe() -+ elif isinstance(stdin, int): -+ p2cread = stdin -+ else: -+ p2cread = stdin.fileno() -+ -+ if stdout is None: -+ pass -+ elif stdout == PIPE: -+ c2pread, c2pwrite = os.pipe() -+ elif isinstance(stdout, int): -+ c2pwrite = stdout -+ else: -+ c2pwrite = stdout.fileno() -+ -+ if stderr is None: -+ pass -+ elif stderr == PIPE: -+ errread, errwrite = os.pipe() -+ elif stderr == STDOUT: -+ errwrite = c2pwrite -+ elif isinstance(stderr, int): -+ errwrite = stderr -+ else: -+ errwrite = stderr.fileno() -+ -+ return (p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) -+ -+ def _set_cloexec_flag(self, fd): -+ try: -+ cloexec_flag = fcntl.FD_CLOEXEC -+ except AttributeError: -+ cloexec_flag = 1 -+ -+ old = fcntl.fcntl(fd, fcntl.F_GETFD) -+ fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag) -+ -+ def _close_fds(self, but): -+ for i in xrange(3, MAXFD): -+ if i == but: -+ continue -+ try: -+ os.close(i) -+ except: -+ pass -+ -+ def _execute_child(self, args, executable, preexec_fn, close_fds, -+ cwd, env, universal_newlines, startupinfo, creationflags, shell, -+ p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite): -+ -+ if isinstance(args, types.StringTypes): -+ args = [args] -+ else: -+ args = list(args) -+ -+ if shell: -+ args = ["/bin/sh", "-c"] + args -+ -+ if executable is None: -+ executable = args[0] -+ -+ errpipe_read, errpipe_write = os.pipe() -+ self._set_cloexec_flag(errpipe_write) -+ -+ gc_was_enabled = gc.isenabled() -+ gc.disable() -+ try: -+ self.pid = os.fork() -+ except: -+ if gc_was_enabled: -+ gc.enable() -+ raise -+ self._child_created = True -+ if self.pid == 0: -+ try: -+ if p2cwrite: -+ os.close(p2cwrite) -+ if c2pread: -+ os.close(c2pread) -+ if errread: -+ os.close(errread) -+ os.close(errpipe_read) -+ -+ if p2cread: -+ os.dup2(p2cread, 0) -+ if c2pwrite: -+ os.dup2(c2pwrite, 1) -+ if errwrite: -+ os.dup2(errwrite, 2) -+ -+ if p2cread and p2cread not in (0,): -+ os.close(p2cread) -+ if c2pwrite and c2pwrite not in (p2cread, 1): -+ os.close(c2pwrite) -+ if errwrite and errwrite not in (p2cread, c2pwrite, 2): -+ os.close(errwrite) -+ -+ if close_fds: -+ self._close_fds(but=errpipe_write) -+ -+ if cwd is not None: -+ os.chdir(cwd) -+ -+ if preexec_fn: -+ apply(preexec_fn) -+ -+ if env is None: -+ os.execvp(executable, args) -+ else: -+ os.execvpe(executable, args, env) -+ -+ except: -+ exc_type, exc_value, tb = sys.exc_info() -+ exc_lines = traceback.format_exception(exc_type, exc_value, tb) -+ exc_value.child_traceback = ''.join(exc_lines) -+ os.write(errpipe_write, pickle.dumps(exc_value)) -+ -+ os._exit(255) -+ -+ if gc_was_enabled: -+ gc.enable() -+ os.close(errpipe_write) -+ if p2cread and p2cwrite: -+ os.close(p2cread) -+ if c2pwrite and c2pread: -+ os.close(c2pwrite) -+ if errwrite and errread: -+ os.close(errwrite) -+ -+ data = os.read(errpipe_read, 1048576) -+ os.close(errpipe_read) -+ if data != "": -+ os.waitpid(self.pid, 0) -+ child_exception = pickle.loads(data) -+ raise child_exception -+ -+ def _handle_exitstatus(self, sts): -+ if os.WIFSIGNALED(sts): -+ self.returncode = -os.WTERMSIG(sts) -+ elif os.WIFEXITED(sts): -+ self.returncode = os.WEXITSTATUS(sts) -+ else: -+ raise RuntimeError("Unknown child exit status!") -+ -+ def poll(self, _deadstate=None): -+ if self.returncode is None: -+ try: -+ pid, sts = os.waitpid(self.pid, os.WNOHANG) -+ if pid == self.pid: -+ self._handle_exitstatus(sts) -+ except os.error: -+ if _deadstate is not None: -+ self.returncode = _deadstate -+ return self.returncode -+ -+ def wait(self): -+ if self.returncode is None: -+ pid, sts = os.waitpid(self.pid, 0) -+ self._handle_exitstatus(sts) -+ return self.returncode -+ -+ def _communicate(self, input): -+ read_set = [] -+ write_set = [] -+ stdout = None -+ stderr = None -+ -+ if self.stdin: -+ self.stdin.flush() -+ if input: -+ write_set.append(self.stdin) -+ else: -+ self.stdin.close() -+ if self.stdout: -+ read_set.append(self.stdout) -+ stdout = [] -+ if self.stderr: -+ read_set.append(self.stderr) -+ stderr = [] -+ -+ input_offset = 0 -+ while read_set or write_set: -+ rlist, wlist, xlist = select.select(read_set, write_set, []) -+ -+ if self.stdin in wlist: -+ bytes_written = os.write(self.stdin.fileno(), buffer(input, input_offset, 512)) -+ input_offset += bytes_written -+ if input_offset >= len(input): -+ self.stdin.close() -+ write_set.remove(self.stdin) -+ -+ if self.stdout in rlist: -+ data = os.read(self.stdout.fileno(), 1024) -+ if data == "": -+ self.stdout.close() -+ read_set.remove(self.stdout) -+ stdout.append(data) -+ -+ if self.stderr in rlist: -+ data = os.read(self.stderr.fileno(), 1024) -+ if data == "": -+ self.stderr.close() -+ read_set.remove(self.stderr) -+ stderr.append(data) -+ -+ if stdout is not None: -+ stdout = ''.join(stdout) -+ if stderr is not None: -+ stderr = ''.join(stderr) -+ -+ if self.universal_newlines and hasattr(file, 'newlines'): -+ if stdout: -+ stdout = self._translate_newlines(stdout) -+ if stderr: -+ stderr = self._translate_newlines(stderr) -+ -+ self.wait() -+ return (stdout, stderr) -+ -diff --git a/buildtools/wafadmin/py3kfixes.py b/buildtools/wafadmin/py3kfixes.py -new file mode 100644 -index 0000000..2f3c9c2 ---- /dev/null -+++ b/buildtools/wafadmin/py3kfixes.py -@@ -0,0 +1,130 @@ -+#!/usr/bin/env python -+# encoding: utf-8 -+# Thomas Nagy, 2009 (ita) -+ -+""" -+Fixes for py3k go here -+""" -+ -+import os -+ -+all_modifs = {} -+ -+def modif(dir, name, fun): -+ if name == '*': -+ lst = [] -+ for y in '. Tools 3rdparty'.split(): -+ for x in os.listdir(os.path.join(dir, y)): -+ if x.endswith('.py'): -+ lst.append(y + os.sep + x) -+ #lst = [y + os.sep + x for x in os.listdir(os.path.join(dir, y)) for y in '. Tools 3rdparty'.split() if x.endswith('.py')] -+ for x in lst: -+ modif(dir, x, fun) -+ return -+ -+ filename = os.path.join(dir, name) -+ f = open(filename, 'r') -+ txt = f.read() -+ f.close() -+ -+ txt = fun(txt) -+ -+ f = open(filename, 'w') -+ f.write(txt) -+ f.close() -+ -+def subst(filename): -+ def do_subst(fun): -+ global all_modifs -+ try: -+ all_modifs[filename] += fun -+ except KeyError: -+ all_modifs[filename] = [fun] -+ return fun -+ return do_subst -+ -+@subst('Constants.py') -+def r1(code): -+ code = code.replace("'iluvcuteoverload'", "b'iluvcuteoverload'") -+ code = code.replace("ABI=7", "ABI=37") -+ return code -+ -+@subst('Tools/ccroot.py') -+def r2(code): -+ code = code.replace("p.stdin.write('\\n')", "p.stdin.write(b'\\n')") -+ code = code.replace('p.communicate()[0]', 'p.communicate()[0].decode("utf-8")') -+ return code -+ -+@subst('Utils.py') -+def r3(code): -+ code = code.replace("m.update(str(lst))", "m.update(str(lst).encode())") -+ code = code.replace('p.communicate()[0]', 'p.communicate()[0].decode("utf-8")') -+ return code -+ -+@subst('ansiterm.py') -+def r33(code): -+ code = code.replace('unicode', 'str') -+ return code -+ -+@subst('Task.py') -+def r4(code): -+ code = code.replace("up(self.__class__.__name__)", "up(self.__class__.__name__.encode())") -+ code = code.replace("up(self.env.variant())", "up(self.env.variant().encode())") -+ code = code.replace("up(x.parent.abspath())", "up(x.parent.abspath().encode())") -+ code = code.replace("up(x.name)", "up(x.name.encode())") -+ code = code.replace('class TaskBase(object):\n\t__metaclass__=store_task_type', 'import binascii\n\nclass TaskBase(object, metaclass=store_task_type):') -+ code = code.replace('keys=self.cstr_groups.keys()', 'keys=list(self.cstr_groups.keys())') -+ code = code.replace("sig.encode('hex')", 'binascii.hexlify(sig)') -+ code = code.replace("os.path.join(Options.cache_global,ssig)", "os.path.join(Options.cache_global,ssig.decode())") -+ return code -+ -+@subst('Build.py') -+def r5(code): -+ code = code.replace("cPickle.dump(data,file,-1)", "cPickle.dump(data,file)") -+ code = code.replace('for node in src_dir_node.childs.values():', 'for node in list(src_dir_node.childs.values()):') -+ return code -+ -+@subst('*') -+def r6(code): -+ code = code.replace('xrange', 'range') -+ code = code.replace('iteritems', 'items') -+ code = code.replace('maxint', 'maxsize') -+ code = code.replace('iterkeys', 'keys') -+ code = code.replace('Error,e:', 'Error as e:') -+ code = code.replace('Exception,e:', 'Exception as e:') -+ return code -+ -+@subst('TaskGen.py') -+def r7(code): -+ code = code.replace('class task_gen(object):\n\t__metaclass__=register_obj', 'class task_gen(object, metaclass=register_obj):') -+ return code -+ -+@subst('Tools/python.py') -+def r8(code): -+ code = code.replace('proc.communicate()[0]', 'proc.communicate()[0].decode("utf-8")') -+ return code -+ -+@subst('Tools/glib2.py') -+def r9(code): -+ code = code.replace('f.write(c)', 'f.write(c.encode("utf-8"))') -+ return code -+ -+@subst('Tools/config_c.py') -+def r10(code): -+ code = code.replace("key=kw['success']", "key=kw['success']\n\t\t\t\ttry:\n\t\t\t\t\tkey=key.decode('utf-8')\n\t\t\t\texcept:\n\t\t\t\t\tpass") -+ code = code.replace('out=str(out)','out=out.decode("utf-8")') -+ code = code.replace('err=str(err)','err=err.decode("utf-8")') -+ return code -+ -+@subst('Tools/d.py') -+def r11(code): -+ code = code.replace('ret.strip()', 'ret.strip().decode("utf-8")') -+ return code -+ -+def fixdir(dir): -+ global all_modifs -+ for k in all_modifs: -+ for v in all_modifs[k]: -+ modif(os.path.join(dir, 'wafadmin'), k, v) -+ #print('substitutions finished') -+ diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/00-fix-typos-in-man-pages.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/00-fix-typos-in-man-pages.patch new file mode 100644 index 00000000..c94bc318 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/00-fix-typos-in-man-pages.patch @@ -0,0 +1,108 @@ +From 1573638212a9733a44939a4d38a226f38dca36f1 Mon Sep 17 00:00:00 2001 +From: Michele Baldessari +Date: Tue, 9 Jul 2013 23:23:33 +0200 +Subject: [PATCH] Fix typos in man-pages + +Fix some typos in the man-pages. + +Signed-off-by: Michele Baldessari +Reviewed-by: Simo Sorce + +Autobuild-User(master): Simo Sorce +Autobuild-Date(master): Wed Jul 10 16:45:07 CEST 2013 on sn-devel-104 +--- + docs-xml/manpages/dbwrap_tool.1.xml | 2 +- + docs-xml/manpages/idmap_autorid.8.xml | 2 +- + docs-xml/manpages/net.8.xml | 2 +- + docs-xml/manpages/pdbedit.8.xml | 2 +- + docs-xml/manpages/samba.7.xml | 2 +- + docs-xml/manpages/smbclient.1.xml | 2 +- + docs-xml/manpages/smbpasswd.5.xml | 2 +- + docs-xml/manpages/vfs_smb_traffic_analyzer.8.xml | 2 +- + 8 files changed, 8 insertions(+), 8 deletions(-) + +Index: samba-4.1.11/docs-xml/manpages/smbstatus.1.xml +=================================================================== +--- samba-4.1.11.orig/docs-xml/manpages/smbstatus.1.xml ++++ samba-4.1.11/docs-xml/manpages/smbstatus.1.xml +@@ -137,6 +137,13 @@ + + + ++ ++ -n|--numeric ++ causes smbstatus to display numeric UIDs and GIDs instead of ++ resolving them to names. ++ ++ ++ + + + +Index: samba-4.1.11/docs-xml/manpages/sharesec.1.xml +=================================================================== +--- samba-4.1.11.orig/docs-xml/manpages/sharesec.1.xml ++++ samba-4.1.11/docs-xml/manpages/sharesec.1.xml +@@ -129,6 +129,13 @@ + + + ++ ++ -S|--setsddl=STRING ++ ++ Set security descriptor by providing ACL in SDDL format. ++ ++ ++ + &stdarg.help; + &stdarg.server.debug; + &popt.common.samba; +Index: samba-4.1.11/docs-xml/build/DTD/samba.entities +=================================================================== +--- samba-4.1.11.orig/docs-xml/build/DTD/samba.entities ++++ samba-4.1.11/docs-xml/build/DTD/samba.entities +@@ -270,6 +270,44 @@ file. + &popt.common.samba; + '> + ++ ++-S|--signing on|off|required ++Set the client signing state. ++ ++ ++'> ++ ++ ++-P|--machine-pass ++Use stored machine account password. ++ ++ ++'> ++ ++ ++-e|--encrypt ++ ++This command line parameter requires the remote ++server support the UNIX extensions or that the SMB3 protocol has been selected. ++Requests that the connection be encrypted. Negotiates SMB encryption using either ++SMB3 or POSIX extensions via GSSAPI. Uses the given credentials for ++the encryption negotiation (either kerberos or NTLMv1/v2 if given ++domain/username/password triple. Fails the connection if encryption ++cannot be negotiated. ++ ++ ++'> ++ ++ ++--pw-nt-hash ++The supplied password is the NT hash. ++ ++ ++'> + + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/01-fix-force-user-sec-ads.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/01-fix-force-user-sec-ads.patch new file mode 100644 index 00000000..6c08cccc --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/01-fix-force-user-sec-ads.patch @@ -0,0 +1,1448 @@ +From 80f3551d4f594438dcc93dd82a7953c4a913badd Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Mon, 16 Dec 2013 12:57:20 +0100 +Subject: [PATCH 1/7] s3-lib: Add winbind_lookup_usersids(). + +Pair-Programmed-With: Guenther Deschner +Signed-off-by: Guenther Deschner +Signed-off-by: Andreas Schneider +Reviewed-by: Andrew Bartlett + +(cherry picked from commit 241e98d8ee099f9cc5feb835085b4abd2b1ee663) +--- + source3/lib/winbind_util.c | 34 +++++ + source3/lib/winbind_util.h | 4 + + source3/passdb/ABI/pdb-0.1.0.sigs | 311 ++++++++++++++++++++++++++++++++++++++ + source3/wscript_build | 2 +- + 4 files changed, 350 insertions(+), 1 deletion(-) + create mode 100644 source3/passdb/ABI/pdb-0.1.0.sigs + +diff --git a/source3/lib/winbind_util.c b/source3/lib/winbind_util.c +index b458ebe..f62682b 100644 +--- a/source3/lib/winbind_util.c ++++ b/source3/lib/winbind_util.c +@@ -342,6 +342,40 @@ bool winbind_get_sid_aliases(TALLOC_CTX *mem_ctx, + return true; + } + ++bool winbind_lookup_usersids(TALLOC_CTX *mem_ctx, ++ const struct dom_sid *user_sid, ++ uint32_t *p_num_sids, ++ struct dom_sid **p_sids) ++{ ++ wbcErr ret; ++ struct wbcDomainSid dom_sid; ++ struct wbcDomainSid *sid_list = NULL; ++ uint32_t num_sids; ++ ++ memcpy(&dom_sid, user_sid, sizeof(dom_sid)); ++ ++ ret = wbcLookupUserSids(&dom_sid, ++ false, ++ &num_sids, ++ &sid_list); ++ if (ret != WBC_ERR_SUCCESS) { ++ return false; ++ } ++ ++ *p_sids = talloc_array(mem_ctx, struct dom_sid, num_sids); ++ if (*p_sids == NULL) { ++ wbcFreeMemory(sid_list); ++ return false; ++ } ++ ++ memcpy(*p_sids, sid_list, sizeof(dom_sid) * num_sids); ++ ++ *p_num_sids = num_sids; ++ wbcFreeMemory(sid_list); ++ ++ return true; ++} ++ + #else /* WITH_WINBIND */ + + struct passwd * winbind_getpwnam(const char * name) +diff --git a/source3/lib/winbind_util.h b/source3/lib/winbind_util.h +index 541bb95..abbc5a9 100644 +--- a/source3/lib/winbind_util.h ++++ b/source3/lib/winbind_util.h +@@ -58,5 +58,9 @@ bool winbind_get_sid_aliases(TALLOC_CTX *mem_ctx, + size_t num_members, + uint32_t **pp_alias_rids, + size_t *p_num_alias_rids); ++bool winbind_lookup_usersids(TALLOC_CTX *mem_ctx, ++ const struct dom_sid *user_sid, ++ uint32_t *p_num_sids, ++ struct dom_sid **p_sids); + + #endif /* __LIB__WINBIND_UTIL_H__ */ +diff --git a/source3/passdb/ABI/pdb-0.1.0.sigs b/source3/passdb/ABI/pdb-0.1.0.sigs +new file mode 100644 +index 0000000..f4de9c4 +--- /dev/null ++++ b/source3/passdb/ABI/pdb-0.1.0.sigs +@@ -0,0 +1,311 @@ ++PDB_secrets_clear_domain_protection: bool (const char *) ++PDB_secrets_fetch_domain_guid: bool (const char *, struct GUID *) ++PDB_secrets_fetch_domain_sid: bool (const char *, struct dom_sid *) ++PDB_secrets_mark_domain_protected: bool (const char *) ++PDB_secrets_store_domain_guid: bool (const char *, struct GUID *) ++PDB_secrets_store_domain_sid: bool (const char *, const struct dom_sid *) ++account_policy_get: bool (enum pdb_policy_type, uint32_t *) ++account_policy_get_default: bool (enum pdb_policy_type, uint32_t *) ++account_policy_get_desc: const char *(enum pdb_policy_type) ++account_policy_name_to_typenum: enum pdb_policy_type (const char *) ++account_policy_names_list: void (TALLOC_CTX *, const char ***, int *) ++account_policy_set: bool (enum pdb_policy_type, uint32_t) ++add_initial_entry: NTSTATUS (gid_t, const char *, enum lsa_SidType, const char *, const char *) ++algorithmic_pdb_gid_to_group_rid: uint32_t (gid_t) ++algorithmic_pdb_rid_is_user: bool (uint32_t) ++algorithmic_pdb_uid_to_user_rid: uint32_t (uid_t) ++algorithmic_pdb_user_rid_to_uid: uid_t (uint32_t) ++algorithmic_rid_base: int (void) ++builtin_domain_name: const char *(void) ++cache_account_policy_get: bool (enum pdb_policy_type, uint32_t *) ++cache_account_policy_set: bool (enum pdb_policy_type, uint32_t) ++create_builtin_administrators: NTSTATUS (const struct dom_sid *) ++create_builtin_users: NTSTATUS (const struct dom_sid *) ++decode_account_policy_name: const char *(enum pdb_policy_type) ++get_account_pol_db: struct db_context *(void) ++get_account_policy_attr: const char *(enum pdb_policy_type) ++get_domain_group_from_sid: bool (struct dom_sid, GROUP_MAP *) ++get_primary_group_sid: NTSTATUS (TALLOC_CTX *, const char *, struct passwd **, struct dom_sid **) ++get_privileges_for_sid_as_set: NTSTATUS (TALLOC_CTX *, PRIVILEGE_SET **, struct dom_sid *) ++get_privileges_for_sids: bool (uint64_t *, struct dom_sid *, int) ++get_trust_pw_clear: bool (const char *, char **, const char **, enum netr_SchannelType *) ++get_trust_pw_hash: bool (const char *, uint8_t *, const char **, enum netr_SchannelType *) ++gid_to_sid: void (struct dom_sid *, gid_t) ++gid_to_unix_groups_sid: void (gid_t, struct dom_sid *) ++grab_named_mutex: struct named_mutex *(TALLOC_CTX *, const char *, int) ++grant_all_privileges: bool (const struct dom_sid *) ++grant_privilege_by_name: bool (const struct dom_sid *, const char *) ++grant_privilege_set: bool (const struct dom_sid *, struct lsa_PrivilegeSet *) ++groupdb_tdb_init: const struct mapping_backend *(void) ++init_account_policy: bool (void) ++init_buffer_from_samu: uint32_t (uint8_t **, struct samu *, bool) ++init_samu_from_buffer: bool (struct samu *, uint32_t, uint8_t *, uint32_t) ++initialize_password_db: bool (bool, struct tevent_context *) ++is_dc_trusted_domain_situation: bool (const char *) ++is_privileged_sid: bool (const struct dom_sid *) ++local_password_change: NTSTATUS (const char *, int, const char *, char **, char **) ++login_cache_delentry: bool (const struct samu *) ++login_cache_init: bool (void) ++login_cache_read: bool (struct samu *, struct login_cache *) ++login_cache_shutdown: bool (void) ++login_cache_write: bool (const struct samu *, const struct login_cache *) ++lookup_builtin_name: bool (const char *, uint32_t *) ++lookup_builtin_rid: bool (TALLOC_CTX *, uint32_t, const char **) ++lookup_global_sam_name: bool (const char *, int, uint32_t *, enum lsa_SidType *) ++lookup_name: bool (TALLOC_CTX *, const char *, int, const char **, const char **, struct dom_sid *, enum lsa_SidType *) ++lookup_name_smbconf: bool (TALLOC_CTX *, const char *, int, const char **, const char **, struct dom_sid *, enum lsa_SidType *) ++lookup_sid: bool (TALLOC_CTX *, const struct dom_sid *, const char **, const char **, enum lsa_SidType *) ++lookup_sids: NTSTATUS (TALLOC_CTX *, int, const struct dom_sid **, int, struct lsa_dom_info **, struct lsa_name_info **) ++lookup_unix_group_name: bool (const char *, struct dom_sid *) ++lookup_unix_user_name: bool (const char *, struct dom_sid *) ++lookup_wellknown_name: bool (TALLOC_CTX *, const char *, struct dom_sid *, const char **) ++lookup_wellknown_sid: bool (TALLOC_CTX *, const struct dom_sid *, const char **, const char **) ++make_pdb_method: NTSTATUS (struct pdb_methods **) ++make_pdb_method_name: NTSTATUS (struct pdb_methods **, const char *) ++max_algorithmic_gid: gid_t (void) ++max_algorithmic_uid: uid_t (void) ++my_sam_name: const char *(void) ++pdb_add_aliasmem: NTSTATUS (const struct dom_sid *, const struct dom_sid *) ++pdb_add_group_mapping_entry: NTSTATUS (GROUP_MAP *) ++pdb_add_groupmem: NTSTATUS (TALLOC_CTX *, uint32_t, uint32_t) ++pdb_add_sam_account: NTSTATUS (struct samu *) ++pdb_build_fields_present: uint32_t (struct samu *) ++pdb_capabilities: uint32_t (void) ++pdb_copy_sam_account: bool (struct samu *, struct samu *) ++pdb_create_alias: NTSTATUS (const char *, uint32_t *) ++pdb_create_builtin: NTSTATUS (uint32_t) ++pdb_create_builtin_alias: NTSTATUS (uint32_t, gid_t) ++pdb_create_dom_group: NTSTATUS (TALLOC_CTX *, const char *, uint32_t *) ++pdb_create_user: NTSTATUS (TALLOC_CTX *, const char *, uint32_t, uint32_t *) ++pdb_decode_acct_ctrl: uint32_t (const char *) ++pdb_default_add_aliasmem: NTSTATUS (struct pdb_methods *, const struct dom_sid *, const struct dom_sid *) ++pdb_default_add_group_mapping_entry: NTSTATUS (struct pdb_methods *, GROUP_MAP *) ++pdb_default_alias_memberships: NTSTATUS (struct pdb_methods *, TALLOC_CTX *, const struct dom_sid *, const struct dom_sid *, size_t, uint32_t **, size_t *) ++pdb_default_create_alias: NTSTATUS (struct pdb_methods *, const char *, uint32_t *) ++pdb_default_del_aliasmem: NTSTATUS (struct pdb_methods *, const struct dom_sid *, const struct dom_sid *) ++pdb_default_delete_alias: NTSTATUS (struct pdb_methods *, const struct dom_sid *) ++pdb_default_delete_group_mapping_entry: NTSTATUS (struct pdb_methods *, struct dom_sid) ++pdb_default_enum_aliasmem: NTSTATUS (struct pdb_methods *, const struct dom_sid *, TALLOC_CTX *, struct dom_sid **, size_t *) ++pdb_default_enum_group_mapping: NTSTATUS (struct pdb_methods *, const struct dom_sid *, enum lsa_SidType, GROUP_MAP ***, size_t *, bool) ++pdb_default_get_aliasinfo: NTSTATUS (struct pdb_methods *, const struct dom_sid *, struct acct_info *) ++pdb_default_getgrgid: NTSTATUS (struct pdb_methods *, GROUP_MAP *, gid_t) ++pdb_default_getgrnam: NTSTATUS (struct pdb_methods *, GROUP_MAP *, const char *) ++pdb_default_getgrsid: NTSTATUS (struct pdb_methods *, GROUP_MAP *, struct dom_sid) ++pdb_default_set_aliasinfo: NTSTATUS (struct pdb_methods *, const struct dom_sid *, struct acct_info *) ++pdb_default_update_group_mapping_entry: NTSTATUS (struct pdb_methods *, GROUP_MAP *) ++pdb_del_aliasmem: NTSTATUS (const struct dom_sid *, const struct dom_sid *) ++pdb_del_groupmem: NTSTATUS (TALLOC_CTX *, uint32_t, uint32_t) ++pdb_del_trusted_domain: NTSTATUS (const char *) ++pdb_del_trusteddom_pw: bool (const char *) ++pdb_delete_alias: NTSTATUS (const struct dom_sid *) ++pdb_delete_dom_group: NTSTATUS (TALLOC_CTX *, uint32_t) ++pdb_delete_group_mapping_entry: NTSTATUS (struct dom_sid) ++pdb_delete_sam_account: NTSTATUS (struct samu *) ++pdb_delete_secret: NTSTATUS (const char *) ++pdb_delete_user: NTSTATUS (TALLOC_CTX *, struct samu *) ++pdb_element_is_changed: bool (const struct samu *, enum pdb_elements) ++pdb_element_is_set_or_changed: bool (const struct samu *, enum pdb_elements) ++pdb_encode_acct_ctrl: char *(uint32_t, size_t) ++pdb_enum_alias_memberships: NTSTATUS (TALLOC_CTX *, const struct dom_sid *, const struct dom_sid *, size_t, uint32_t **, size_t *) ++pdb_enum_aliasmem: NTSTATUS (const struct dom_sid *, TALLOC_CTX *, struct dom_sid **, size_t *) ++pdb_enum_group_mapping: bool (const struct dom_sid *, enum lsa_SidType, GROUP_MAP ***, size_t *, bool) ++pdb_enum_group_members: NTSTATUS (TALLOC_CTX *, const struct dom_sid *, uint32_t **, size_t *) ++pdb_enum_group_memberships: NTSTATUS (TALLOC_CTX *, struct samu *, struct dom_sid **, gid_t **, uint32_t *) ++pdb_enum_trusted_domains: NTSTATUS (TALLOC_CTX *, uint32_t *, struct pdb_trusted_domain ***) ++pdb_enum_trusteddoms: NTSTATUS (TALLOC_CTX *, uint32_t *, struct trustdom_info ***) ++pdb_enum_upn_suffixes: NTSTATUS (TALLOC_CTX *, uint32_t *, char ***) ++pdb_find_backend_entry: struct pdb_init_function_entry *(const char *) ++pdb_get_account_policy: bool (enum pdb_policy_type, uint32_t *) ++pdb_get_acct_ctrl: uint32_t (const struct samu *) ++pdb_get_acct_desc: const char *(const struct samu *) ++pdb_get_aliasinfo: NTSTATUS (const struct dom_sid *, struct acct_info *) ++pdb_get_backend_private_data: void *(const struct samu *, const struct pdb_methods *) ++pdb_get_backends: const struct pdb_init_function_entry *(void) ++pdb_get_bad_password_count: uint16_t (const struct samu *) ++pdb_get_bad_password_time: time_t (const struct samu *) ++pdb_get_code_page: uint16_t (const struct samu *) ++pdb_get_comment: const char *(const struct samu *) ++pdb_get_country_code: uint16_t (const struct samu *) ++pdb_get_dir_drive: const char *(const struct samu *) ++pdb_get_domain: const char *(const struct samu *) ++pdb_get_domain_info: struct pdb_domain_info *(TALLOC_CTX *) ++pdb_get_fullname: const char *(const struct samu *) ++pdb_get_group_rid: uint32_t (struct samu *) ++pdb_get_group_sid: const struct dom_sid *(struct samu *) ++pdb_get_homedir: const char *(const struct samu *) ++pdb_get_hours: const uint8_t *(const struct samu *) ++pdb_get_hours_len: uint32_t (const struct samu *) ++pdb_get_init_flags: enum pdb_value_state (const struct samu *, enum pdb_elements) ++pdb_get_kickoff_time: time_t (const struct samu *) ++pdb_get_lanman_passwd: const uint8_t *(const struct samu *) ++pdb_get_logoff_time: time_t (const struct samu *) ++pdb_get_logon_count: uint16_t (const struct samu *) ++pdb_get_logon_divs: uint16_t (const struct samu *) ++pdb_get_logon_script: const char *(const struct samu *) ++pdb_get_logon_time: time_t (const struct samu *) ++pdb_get_munged_dial: const char *(const struct samu *) ++pdb_get_nt_passwd: const uint8_t *(const struct samu *) ++pdb_get_nt_username: const char *(const struct samu *) ++pdb_get_pass_can_change: bool (const struct samu *) ++pdb_get_pass_can_change_time: time_t (const struct samu *) ++pdb_get_pass_can_change_time_noncalc: time_t (const struct samu *) ++pdb_get_pass_last_set_time: time_t (const struct samu *) ++pdb_get_pass_must_change_time: time_t (const struct samu *) ++pdb_get_plaintext_passwd: const char *(const struct samu *) ++pdb_get_profile_path: const char *(const struct samu *) ++pdb_get_pw_history: const uint8_t *(const struct samu *, uint32_t *) ++pdb_get_secret: NTSTATUS (TALLOC_CTX *, const char *, DATA_BLOB *, NTTIME *, DATA_BLOB *, NTTIME *, struct security_descriptor **) ++pdb_get_seq_num: bool (time_t *) ++pdb_get_tevent_context: struct tevent_context *(void) ++pdb_get_trusted_domain: NTSTATUS (TALLOC_CTX *, const char *, struct pdb_trusted_domain **) ++pdb_get_trusted_domain_by_sid: NTSTATUS (TALLOC_CTX *, struct dom_sid *, struct pdb_trusted_domain **) ++pdb_get_trusteddom_pw: bool (const char *, char **, struct dom_sid *, time_t *) ++pdb_get_unknown_6: uint32_t (const struct samu *) ++pdb_get_user_rid: uint32_t (const struct samu *) ++pdb_get_user_sid: const struct dom_sid *(const struct samu *) ++pdb_get_username: const char *(const struct samu *) ++pdb_get_workstations: const char *(const struct samu *) ++pdb_getgrgid: bool (GROUP_MAP *, gid_t) ++pdb_getgrnam: bool (GROUP_MAP *, const char *) ++pdb_getgrsid: bool (GROUP_MAP *, struct dom_sid) ++pdb_gethexhours: bool (const char *, unsigned char *) ++pdb_gethexpwd: bool (const char *, unsigned char *) ++pdb_getsampwnam: bool (struct samu *, const char *) ++pdb_getsampwsid: bool (struct samu *, const struct dom_sid *) ++pdb_gid_to_sid: bool (gid_t, struct dom_sid *) ++pdb_group_rid_to_gid: gid_t (uint32_t) ++pdb_increment_bad_password_count: bool (struct samu *) ++pdb_is_password_change_time_max: bool (time_t) ++pdb_is_responsible_for_builtin: bool (void) ++pdb_is_responsible_for_our_sam: bool (void) ++pdb_is_responsible_for_unix_groups: bool (void) ++pdb_is_responsible_for_unix_users: bool (void) ++pdb_is_responsible_for_wellknown: bool (void) ++pdb_lookup_rids: NTSTATUS (const struct dom_sid *, int, uint32_t *, const char **, enum lsa_SidType *) ++pdb_new_rid: bool (uint32_t *) ++pdb_nop_add_group_mapping_entry: NTSTATUS (struct pdb_methods *, GROUP_MAP *) ++pdb_nop_delete_group_mapping_entry: NTSTATUS (struct pdb_methods *, struct dom_sid) ++pdb_nop_enum_group_mapping: NTSTATUS (struct pdb_methods *, enum lsa_SidType, GROUP_MAP **, size_t *, bool) ++pdb_nop_getgrgid: NTSTATUS (struct pdb_methods *, GROUP_MAP *, gid_t) ++pdb_nop_getgrnam: NTSTATUS (struct pdb_methods *, GROUP_MAP *, const char *) ++pdb_nop_getgrsid: NTSTATUS (struct pdb_methods *, GROUP_MAP *, struct dom_sid) ++pdb_nop_update_group_mapping_entry: NTSTATUS (struct pdb_methods *, GROUP_MAP *) ++pdb_rename_sam_account: NTSTATUS (struct samu *, const char *) ++pdb_search_aliases: struct pdb_search *(TALLOC_CTX *, const struct dom_sid *) ++pdb_search_entries: uint32_t (struct pdb_search *, uint32_t, uint32_t, struct samr_displayentry **) ++pdb_search_groups: struct pdb_search *(TALLOC_CTX *) ++pdb_search_init: struct pdb_search *(TALLOC_CTX *, enum pdb_search_type) ++pdb_search_users: struct pdb_search *(TALLOC_CTX *, uint32_t) ++pdb_set_account_policy: bool (enum pdb_policy_type, uint32_t) ++pdb_set_acct_ctrl: bool (struct samu *, uint32_t, enum pdb_value_state) ++pdb_set_acct_desc: bool (struct samu *, const char *, enum pdb_value_state) ++pdb_set_aliasinfo: NTSTATUS (const struct dom_sid *, struct acct_info *) ++pdb_set_backend_private_data: bool (struct samu *, void *, void (*)(void **), const struct pdb_methods *, enum pdb_value_state) ++pdb_set_bad_password_count: bool (struct samu *, uint16_t, enum pdb_value_state) ++pdb_set_bad_password_time: bool (struct samu *, time_t, enum pdb_value_state) ++pdb_set_code_page: bool (struct samu *, uint16_t, enum pdb_value_state) ++pdb_set_comment: bool (struct samu *, const char *, enum pdb_value_state) ++pdb_set_country_code: bool (struct samu *, uint16_t, enum pdb_value_state) ++pdb_set_dir_drive: bool (struct samu *, const char *, enum pdb_value_state) ++pdb_set_domain: bool (struct samu *, const char *, enum pdb_value_state) ++pdb_set_fullname: bool (struct samu *, const char *, enum pdb_value_state) ++pdb_set_group_sid: bool (struct samu *, const struct dom_sid *, enum pdb_value_state) ++pdb_set_group_sid_from_rid: bool (struct samu *, uint32_t, enum pdb_value_state) ++pdb_set_homedir: bool (struct samu *, const char *, enum pdb_value_state) ++pdb_set_hours: bool (struct samu *, const uint8_t *, int, enum pdb_value_state) ++pdb_set_hours_len: bool (struct samu *, uint32_t, enum pdb_value_state) ++pdb_set_init_flags: bool (struct samu *, enum pdb_elements, enum pdb_value_state) ++pdb_set_kickoff_time: bool (struct samu *, time_t, enum pdb_value_state) ++pdb_set_lanman_passwd: bool (struct samu *, const uint8_t *, enum pdb_value_state) ++pdb_set_logoff_time: bool (struct samu *, time_t, enum pdb_value_state) ++pdb_set_logon_count: bool (struct samu *, uint16_t, enum pdb_value_state) ++pdb_set_logon_divs: bool (struct samu *, uint16_t, enum pdb_value_state) ++pdb_set_logon_script: bool (struct samu *, const char *, enum pdb_value_state) ++pdb_set_logon_time: bool (struct samu *, time_t, enum pdb_value_state) ++pdb_set_munged_dial: bool (struct samu *, const char *, enum pdb_value_state) ++pdb_set_nt_passwd: bool (struct samu *, const uint8_t *, enum pdb_value_state) ++pdb_set_nt_username: bool (struct samu *, const char *, enum pdb_value_state) ++pdb_set_pass_can_change: bool (struct samu *, bool) ++pdb_set_pass_can_change_time: bool (struct samu *, time_t, enum pdb_value_state) ++pdb_set_pass_last_set_time: bool (struct samu *, time_t, enum pdb_value_state) ++pdb_set_plaintext_passwd: bool (struct samu *, const char *) ++pdb_set_plaintext_pw_only: bool (struct samu *, const char *, enum pdb_value_state) ++pdb_set_profile_path: bool (struct samu *, const char *, enum pdb_value_state) ++pdb_set_pw_history: bool (struct samu *, const uint8_t *, uint32_t, enum pdb_value_state) ++pdb_set_secret: NTSTATUS (const char *, DATA_BLOB *, DATA_BLOB *, struct security_descriptor *) ++pdb_set_trusted_domain: NTSTATUS (const char *, const struct pdb_trusted_domain *) ++pdb_set_trusteddom_pw: bool (const char *, const char *, const struct dom_sid *) ++pdb_set_unix_primary_group: NTSTATUS (TALLOC_CTX *, struct samu *) ++pdb_set_unknown_6: bool (struct samu *, uint32_t, enum pdb_value_state) ++pdb_set_upn_suffixes: NTSTATUS (uint32_t, const char **) ++pdb_set_user_sid: bool (struct samu *, const struct dom_sid *, enum pdb_value_state) ++pdb_set_user_sid_from_rid: bool (struct samu *, uint32_t, enum pdb_value_state) ++pdb_set_user_sid_from_string: bool (struct samu *, const char *, enum pdb_value_state) ++pdb_set_username: bool (struct samu *, const char *, enum pdb_value_state) ++pdb_set_workstations: bool (struct samu *, const char *, enum pdb_value_state) ++pdb_sethexhours: void (char *, const unsigned char *) ++pdb_sethexpwd: void (char *, const unsigned char *, uint32_t) ++pdb_sid_to_id: bool (const struct dom_sid *, struct unixid *) ++pdb_sid_to_id_unix_users_and_groups: bool (const struct dom_sid *, struct unixid *) ++pdb_uid_to_sid: bool (uid_t, struct dom_sid *) ++pdb_update_autolock_flag: bool (struct samu *, bool *) ++pdb_update_bad_password_count: bool (struct samu *, bool *) ++pdb_update_group_mapping_entry: NTSTATUS (GROUP_MAP *) ++pdb_update_login_attempts: NTSTATUS (struct samu *, bool) ++pdb_update_sam_account: NTSTATUS (struct samu *) ++privilege_create_account: NTSTATUS (const struct dom_sid *) ++privilege_delete_account: NTSTATUS (const struct dom_sid *) ++privilege_enum_sids: NTSTATUS (enum sec_privilege, TALLOC_CTX *, struct dom_sid **, int *) ++privilege_enumerate_accounts: NTSTATUS (struct dom_sid **, int *) ++revoke_all_privileges: bool (const struct dom_sid *) ++revoke_privilege_by_name: bool (const struct dom_sid *, const char *) ++revoke_privilege_set: bool (const struct dom_sid *, struct lsa_PrivilegeSet *) ++samu_alloc_rid_unix: NTSTATUS (struct pdb_methods *, struct samu *, const struct passwd *) ++samu_new: struct samu *(TALLOC_CTX *) ++samu_set_unix: NTSTATUS (struct samu *, const struct passwd *) ++secrets_trusted_domains: NTSTATUS (TALLOC_CTX *, uint32_t *, struct trustdom_info ***) ++sid_check_is_builtin: bool (const struct dom_sid *) ++sid_check_is_for_passdb: bool (const struct dom_sid *) ++sid_check_is_in_builtin: bool (const struct dom_sid *) ++sid_check_is_in_unix_groups: bool (const struct dom_sid *) ++sid_check_is_in_unix_users: bool (const struct dom_sid *) ++sid_check_is_in_wellknown_domain: bool (const struct dom_sid *) ++sid_check_is_unix_groups: bool (const struct dom_sid *) ++sid_check_is_unix_users: bool (const struct dom_sid *) ++sid_check_is_wellknown_builtin: bool (const struct dom_sid *) ++sid_check_is_wellknown_domain: bool (const struct dom_sid *, const char **) ++sid_check_object_is_for_passdb: bool (const struct dom_sid *) ++sid_to_gid: bool (const struct dom_sid *, gid_t *) ++sid_to_uid: bool (const struct dom_sid *, uid_t *) ++sids_to_unixids: bool (const struct dom_sid *, uint32_t, struct unixid *) ++smb_add_user_group: int (const char *, const char *) ++smb_create_group: int (const char *, gid_t *) ++smb_delete_group: int (const char *) ++smb_delete_user_group: int (const char *, const char *) ++smb_nscd_flush_group_cache: void (void) ++smb_nscd_flush_user_cache: void (void) ++smb_register_passdb: NTSTATUS (int, const char *, pdb_init_function) ++smb_set_primary_group: int (const char *, const char *) ++uid_to_sid: void (struct dom_sid *, uid_t) ++uid_to_unix_users_sid: void (uid_t, struct dom_sid *) ++unix_groups_domain_name: const char *(void) ++unix_users_domain_name: const char *(void) ++unixid_from_both: void (struct unixid *, uint32_t) ++unixid_from_gid: void (struct unixid *, uint32_t) ++unixid_from_uid: void (struct unixid *, uint32_t) ++wb_is_trusted_domain: wbcErr (const char *) ++winbind_allocate_gid: bool (gid_t *) ++winbind_allocate_uid: bool (uid_t *) ++winbind_get_groups: bool (TALLOC_CTX *, const char *, uint32_t *, gid_t **) ++winbind_get_sid_aliases: bool (TALLOC_CTX *, const struct dom_sid *, const struct dom_sid *, size_t, uint32_t **, size_t *) ++winbind_getpwnam: struct passwd *(const char *) ++winbind_getpwsid: struct passwd *(const struct dom_sid *) ++winbind_gid_to_sid: bool (struct dom_sid *, gid_t) ++winbind_lookup_name: bool (const char *, const char *, struct dom_sid *, enum lsa_SidType *) ++winbind_lookup_rids: bool (TALLOC_CTX *, const struct dom_sid *, int, uint32_t *, const char **, const char ***, enum lsa_SidType **) ++winbind_lookup_sid: bool (TALLOC_CTX *, const struct dom_sid *, const char **, const char **, enum lsa_SidType *) ++winbind_lookup_usersids: bool (TALLOC_CTX *, const struct dom_sid *, uint32_t *, struct dom_sid **) ++winbind_ping: bool (void) ++winbind_sid_to_gid: bool (gid_t *, const struct dom_sid *) ++winbind_sid_to_uid: bool (uid_t *, const struct dom_sid *) ++winbind_uid_to_sid: bool (struct dom_sid *, uid_t) +diff --git a/source3/wscript_build b/source3/wscript_build +index e0432bf..6d6b6aa 100755 +--- a/source3/wscript_build ++++ b/source3/wscript_build +@@ -736,7 +736,7 @@ bld.SAMBA3_LIBRARY('pdb', + passdb/lookup_sid.h''', + abi_match=private_pdb_match, + abi_directory='passdb/ABI', +- vnum='0', ++ vnum='0.1.0', + vars=locals()) + + bld.SAMBA3_LIBRARY('smbldaphelper', +-- +1.8.5.2 + + +From 91debcafd196a9e821efddce0a9d75c48f8e168d Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Fri, 13 Dec 2013 19:08:34 +0100 +Subject: [PATCH 2/7] s3-auth: Add passwd_to_SamInfo3(). + +First this function tries to contacts winbind if the user is a domain +user to get valid information about it. If winbind isn't running it will +try to create everything from the passwd struct. This is not always +reliable but works in most cases. It improves the current situation +which doesn't talk to winbind at all. + +Pair-Programmed-With: Guenther Deschner +Signed-off-by: Guenther Deschner +Signed-off-by: Andreas Schneider +Reviewed-by: Andrew Bartlett +(cherry picked from commit 1bb11c7744df6928cb8a096373ab920366b38770) +--- + source3/auth/proto.h | 4 ++ + source3/auth/server_info.c | 116 +++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 120 insertions(+) + +diff --git a/source3/auth/proto.h b/source3/auth/proto.h +index 76661fc..8385e66 100644 +--- a/source3/auth/proto.h ++++ b/source3/auth/proto.h +@@ -286,6 +286,10 @@ NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx, + const char *login_server, + struct netr_SamInfo3 **_info3, + struct extra_auth_info *extra); ++NTSTATUS passwd_to_SamInfo3(TALLOC_CTX *mem_ctx, ++ const char *unix_username, ++ const struct passwd *pwd, ++ struct netr_SamInfo3 **pinfo3); + struct netr_SamInfo3 *copy_netr_SamInfo3(TALLOC_CTX *mem_ctx, + struct netr_SamInfo3 *orig); + struct netr_SamInfo3 *wbcAuthUserInfo_to_netr_SamInfo3(TALLOC_CTX *mem_ctx, +diff --git a/source3/auth/server_info.c b/source3/auth/server_info.c +index d2b7d6e..46d8178 100644 +--- a/source3/auth/server_info.c ++++ b/source3/auth/server_info.c +@@ -24,6 +24,7 @@ + #include "../libcli/security/security.h" + #include "rpc_client/util_netlogon.h" + #include "nsswitch/libwbclient/wbclient.h" ++#include "lib/winbind_util.h" + #include "passdb.h" + + #undef DBGC_CLASS +@@ -436,6 +437,121 @@ NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx, + return NT_STATUS_OK; + } + ++NTSTATUS passwd_to_SamInfo3(TALLOC_CTX *mem_ctx, ++ const char *unix_username, ++ const struct passwd *pwd, ++ struct netr_SamInfo3 **pinfo3) ++{ ++ struct netr_SamInfo3 *info3; ++ NTSTATUS status; ++ TALLOC_CTX *tmp_ctx; ++ const char *domain_name = NULL; ++ const char *user_name = NULL; ++ struct dom_sid domain_sid; ++ struct dom_sid user_sid; ++ struct dom_sid group_sid; ++ enum lsa_SidType type; ++ uint32_t num_sids = 0; ++ struct dom_sid *user_sids = NULL; ++ bool ok; ++ ++ tmp_ctx = talloc_stackframe(); ++ ++ ok = lookup_name_smbconf(tmp_ctx, ++ unix_username, ++ LOOKUP_NAME_ALL, ++ &domain_name, ++ &user_name, ++ &user_sid, ++ &type); ++ if (!ok) { ++ status = NT_STATUS_NO_SUCH_USER; ++ goto done; ++ } ++ ++ if (type != SID_NAME_USER) { ++ status = NT_STATUS_NO_SUCH_USER; ++ goto done; ++ } ++ ++ ok = winbind_lookup_usersids(tmp_ctx, ++ &user_sid, ++ &num_sids, ++ &user_sids); ++ /* Check if winbind is running */ ++ if (ok) { ++ /* ++ * Winbind is running and the first element of the user_sids ++ * is the primary group. ++ */ ++ if (num_sids > 0) { ++ group_sid = user_sids[0]; ++ } ++ } else { ++ /* ++ * Winbind is not running, create the group_sid from the ++ * group id. ++ */ ++ gid_to_sid(&group_sid, pwd->pw_gid); ++ } ++ ++ /* Make sure we have a valid group sid */ ++ ok = !is_null_sid(&group_sid); ++ if (!ok) { ++ status = NT_STATUS_NO_SUCH_USER; ++ goto done; ++ } ++ ++ /* Construct a netr_SamInfo3 from the information we have */ ++ info3 = talloc_zero(tmp_ctx, struct netr_SamInfo3); ++ if (!info3) { ++ status = NT_STATUS_NO_MEMORY; ++ goto done; ++ } ++ ++ info3->base.account_name.string = talloc_strdup(info3, unix_username); ++ if (info3->base.account_name.string == NULL) { ++ status = NT_STATUS_NO_MEMORY; ++ goto done; ++ } ++ ++ ZERO_STRUCT(domain_sid); ++ ++ sid_copy(&domain_sid, &user_sid); ++ sid_split_rid(&domain_sid, &info3->base.rid); ++ info3->base.domain_sid = dom_sid_dup(info3, &domain_sid); ++ ++ ok = sid_peek_check_rid(&domain_sid, &group_sid, ++ &info3->base.primary_gid); ++ if (!ok) { ++ DEBUG(1, ("The primary group domain sid(%s) does not " ++ "match the domain sid(%s) for %s(%s)\n", ++ sid_string_dbg(&group_sid), ++ sid_string_dbg(&domain_sid), ++ unix_username, ++ sid_string_dbg(&user_sid))); ++ status = NT_STATUS_INVALID_SID; ++ goto done; ++ } ++ ++ info3->base.acct_flags = ACB_NORMAL; ++ ++ if (num_sids) { ++ status = group_sids_to_info3(info3, user_sids, num_sids); ++ if (!NT_STATUS_IS_OK(status)) { ++ goto done; ++ } ++ } ++ ++ *pinfo3 = talloc_steal(mem_ctx, info3); ++ ++ status = NT_STATUS_OK; ++done: ++ talloc_free(tmp_ctx); ++ ++ return status; ++} ++ + #undef RET_NOMEM + + #define RET_NOMEM(ptr) do { \ +-- +1.8.5.2 + + +From c7b7670dc5cd8dbf727258666b6417d67afafb33 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Fri, 13 Dec 2013 19:11:01 +0100 +Subject: [PATCH 3/7] s3-auth: Pass talloc context to make_server_info_pw(). + +Pair-Programmed-With: Guenther Deschner +Signed-off-by: Guenther Deschner +Signed-off-by: Andreas Schneider +Reviewed-by: Andrew Bartlett +(cherry picked from commit 1b59c9743cf3fbd66b0b8b52162b2cc8d922e5cf) +--- + source3/auth/auth_unix.c | 7 +++++-- + source3/auth/auth_util.c | 52 +++++++++++++++++++++++++++++------------------- + source3/auth/proto.h | 7 ++++--- + source3/auth/user_krb5.c | 5 +---- + 4 files changed, 42 insertions(+), 29 deletions(-) + +diff --git a/source3/auth/auth_unix.c b/source3/auth/auth_unix.c +index c8b5435..7b483a2 100644 +--- a/source3/auth/auth_unix.c ++++ b/source3/auth/auth_unix.c +@@ -67,8 +67,11 @@ static NTSTATUS check_unix_security(const struct auth_context *auth_context, + unbecome_root(); + + if (NT_STATUS_IS_OK(nt_status)) { +- if (pass) { +- make_server_info_pw(server_info, pass->pw_name, pass); ++ if (pass != NULL) { ++ nt_status = make_server_info_pw(mem_ctx, ++ pass->pw_name, ++ pass, ++ server_info); + } else { + /* we need to do somthing more useful here */ + nt_status = NT_STATUS_NO_SUCH_USER; +diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c +index ceaa706..b225b0d 100644 +--- a/source3/auth/auth_util.c ++++ b/source3/auth/auth_util.c +@@ -639,14 +639,15 @@ NTSTATUS create_local_token(TALLOC_CTX *mem_ctx, + to a struct samu + ***************************************************************************/ + +-NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info, +- char *unix_username, +- struct passwd *pwd) ++NTSTATUS make_server_info_pw(TALLOC_CTX *mem_ctx, ++ const char *unix_username, ++ const struct passwd *pwd, ++ struct auth_serversupplied_info **server_info) + { + NTSTATUS status; + struct samu *sampass = NULL; + char *qualified_name = NULL; +- TALLOC_CTX *mem_ctx = NULL; ++ TALLOC_CTX *tmp_ctx; + struct dom_sid u_sid; + enum lsa_SidType type; + struct auth_serversupplied_info *result; +@@ -664,27 +665,27 @@ NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info, + * plaintext passwords were used with no SAM backend. + */ + +- mem_ctx = talloc_init("make_server_info_pw_tmp"); +- if (!mem_ctx) { ++ tmp_ctx = talloc_stackframe(); ++ if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + +- qualified_name = talloc_asprintf(mem_ctx, "%s\\%s", ++ qualified_name = talloc_asprintf(tmp_ctx, "%s\\%s", + unix_users_domain_name(), + unix_username ); + if (!qualified_name) { +- TALLOC_FREE(mem_ctx); ++ TALLOC_FREE(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + +- if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL, ++ if (!lookup_name(tmp_ctx, qualified_name, LOOKUP_NAME_ALL, + NULL, NULL, + &u_sid, &type)) { +- TALLOC_FREE(mem_ctx); ++ TALLOC_FREE(tmp_ctx); + return NT_STATUS_NO_SUCH_USER; + } + +- TALLOC_FREE(mem_ctx); ++ TALLOC_FREE(tmp_ctx); + + if (type != SID_NAME_USER) { + return NT_STATUS_NO_SUCH_USER; +@@ -707,7 +708,7 @@ NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info, + /* set the user sid to be the calculated u_sid */ + pdb_set_user_sid(sampass, &u_sid, PDB_SET); + +- result = make_server_info(NULL); ++ result = make_server_info(mem_ctx); + if (result == NULL) { + TALLOC_FREE(sampass); + return NT_STATUS_NO_MEMORY; +@@ -992,25 +993,36 @@ NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx, + struct passwd *pwd; + NTSTATUS status; + struct auth_serversupplied_info *result; ++ TALLOC_CTX *tmp_ctx; + +- pwd = Get_Pwnam_alloc(talloc_tos(), username); +- if (pwd == NULL) { +- return NT_STATUS_NO_SUCH_USER; ++ tmp_ctx = talloc_stackframe(); ++ if (tmp_ctx == NULL) { ++ return NT_STATUS_NO_MEMORY; + } + +- status = make_server_info_pw(&result, pwd->pw_name, pwd); ++ pwd = Get_Pwnam_alloc(tmp_ctx, username); ++ if (pwd == NULL) { ++ status = NT_STATUS_NO_SUCH_USER; ++ goto done; ++ } + ++ status = make_server_info_pw(tmp_ctx, pwd->pw_name, pwd, &result); + if (!NT_STATUS_IS_OK(status)) { +- return status; ++ goto done; + } + + result->nss_token = true; + result->guest = is_guest; + + /* Now turn the server_info into a session_info with the full token etc */ +- status = create_local_token(mem_ctx, result, NULL, pwd->pw_name, session_info); +- TALLOC_FREE(result); +- TALLOC_FREE(pwd); ++ status = create_local_token(mem_ctx, ++ result, ++ NULL, ++ pwd->pw_name, ++ session_info); ++ ++done: ++ talloc_free(tmp_ctx); + + return status; + } +diff --git a/source3/auth/proto.h b/source3/auth/proto.h +index 8385e66..7abca07 100644 +--- a/source3/auth/proto.h ++++ b/source3/auth/proto.h +@@ -206,9 +206,10 @@ bool user_in_group_sid(const char *username, const struct dom_sid *group_sid); + bool user_sid_in_group_sid(const struct dom_sid *sid, const struct dom_sid *group_sid); + bool user_in_group(const char *username, const char *groupname); + struct passwd; +-NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info, +- char *unix_username, +- struct passwd *pwd); ++NTSTATUS make_server_info_pw(TALLOC_CTX *mem_ctx, ++ const char *unix_username, ++ const struct passwd *pwd, ++ struct auth_serversupplied_info **server_info); + NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx, + const char *username, + bool is_guest, +diff --git a/source3/auth/user_krb5.c b/source3/auth/user_krb5.c +index 974a8aa..7d44285 100644 +--- a/source3/auth/user_krb5.c ++++ b/source3/auth/user_krb5.c +@@ -242,7 +242,7 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, + */ + DEBUG(10, ("didn't find user %s in passdb, calling " + "make_server_info_pw\n", username)); +- status = make_server_info_pw(&tmp, username, pw); ++ status = make_server_info_pw(mem_ctx, username, pw, &tmp); + } + + TALLOC_FREE(sampass); +@@ -253,9 +253,6 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, + return status; + } + +- /* Steal tmp server info into the server_info pointer. */ +- server_info = talloc_move(mem_ctx, &tmp); +- + /* make_server_info_pw does not set the domain. Without this + * we end up with the local netbios name in substitutions for + * %D. */ +-- +1.8.5.2 + + +From 4fbd13598e8bdc6acf41329f71de806de4265f36 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Fri, 13 Dec 2013 19:19:02 +0100 +Subject: [PATCH 4/7] s3-auth: Add passwd_to_SamInfo3(). + +Correctly lookup users which come from smb.conf. passwd_to_SamInfo3() +tries to contact winbind if the user is a domain user to get +valid information about it. If winbind isn't running it will try to +create everything from the passwd struct. This is not always reliable +but works in most cases. It improves the current situation which doesn't +talk to winbind at all. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=8598 + +Pair-Programmed-With: Guenther Deschner +Signed-off-by: Andreas Schneider +Reviewed-by: Andrew Bartlett + +Autobuild-User(master): Andrew Bartlett +Autobuild-Date(master): Wed Feb 5 01:40:38 CET 2014 on sn-devel-104 + +(cherry picked from commit 40e6456b5896e934fcd581c2cac2389984256e09) +--- + source3/auth/auth_util.c | 87 +++++++++------------------------------------- + source3/auth/server_info.c | 22 ++++++++++-- + 2 files changed, 36 insertions(+), 73 deletions(-) + +diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c +index b225b0d..24190af 100644 +--- a/source3/auth/auth_util.c ++++ b/source3/auth/auth_util.c +@@ -645,98 +645,43 @@ NTSTATUS make_server_info_pw(TALLOC_CTX *mem_ctx, + struct auth_serversupplied_info **server_info) + { + NTSTATUS status; +- struct samu *sampass = NULL; +- char *qualified_name = NULL; +- TALLOC_CTX *tmp_ctx; +- struct dom_sid u_sid; +- enum lsa_SidType type; ++ TALLOC_CTX *tmp_ctx = NULL; + struct auth_serversupplied_info *result; + +- /* +- * The SID returned in server_info->sam_account is based +- * on our SAM sid even though for a pure UNIX account this should +- * not be the case as it doesn't really exist in the SAM db. +- * This causes lookups on "[in]valid users" to fail as they +- * will lookup this name as a "Unix User" SID to check against +- * the user token. Fix this by adding the "Unix User"\unix_username +- * SID to the sid array. The correct fix should probably be +- * changing the server_info->sam_account user SID to be a +- * S-1-22 Unix SID, but this might break old configs where +- * plaintext passwords were used with no SAM backend. +- */ +- + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + +- qualified_name = talloc_asprintf(tmp_ctx, "%s\\%s", +- unix_users_domain_name(), +- unix_username ); +- if (!qualified_name) { +- TALLOC_FREE(tmp_ctx); +- return NT_STATUS_NO_MEMORY; +- } +- +- if (!lookup_name(tmp_ctx, qualified_name, LOOKUP_NAME_ALL, +- NULL, NULL, +- &u_sid, &type)) { +- TALLOC_FREE(tmp_ctx); +- return NT_STATUS_NO_SUCH_USER; +- } +- +- TALLOC_FREE(tmp_ctx); +- +- if (type != SID_NAME_USER) { +- return NT_STATUS_NO_SUCH_USER; +- } +- +- if ( !(sampass = samu_new( NULL )) ) { +- return NT_STATUS_NO_MEMORY; +- } +- +- status = samu_set_unix( sampass, pwd ); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- +- /* In pathological cases the above call can set the account +- * name to the DOMAIN\username form. Reset the account name +- * using unix_username */ +- pdb_set_username(sampass, unix_username, PDB_SET); +- +- /* set the user sid to be the calculated u_sid */ +- pdb_set_user_sid(sampass, &u_sid, PDB_SET); +- +- result = make_server_info(mem_ctx); ++ result = make_server_info(tmp_ctx); + if (result == NULL) { +- TALLOC_FREE(sampass); +- return NT_STATUS_NO_MEMORY; ++ status = NT_STATUS_NO_MEMORY; ++ goto done; + } + +- status = samu_to_SamInfo3(result, sampass, lp_netbios_name(), +- &result->info3, &result->extra); +- TALLOC_FREE(sampass); ++ status = passwd_to_SamInfo3(result, ++ unix_username, ++ pwd, ++ &result->info3); + if (!NT_STATUS_IS_OK(status)) { +- DEBUG(10, ("Failed to convert samu to info3: %s\n", +- nt_errstr(status))); +- TALLOC_FREE(result); +- return status; ++ goto done; + } + + result->unix_name = talloc_strdup(result, unix_username); +- + if (result->unix_name == NULL) { +- TALLOC_FREE(result); +- return NT_STATUS_NO_MEMORY; ++ status = NT_STATUS_NO_MEMORY; ++ goto done; + } + + result->utok.uid = pwd->pw_uid; + result->utok.gid = pwd->pw_gid; + +- *server_info = result; ++ *server_info = talloc_steal(mem_ctx, result); ++ status = NT_STATUS_OK; ++done: ++ talloc_free(tmp_ctx); + +- return NT_STATUS_OK; ++ return status; + } + + static NTSTATUS get_system_info3(TALLOC_CTX *mem_ctx, +diff --git a/source3/auth/server_info.c b/source3/auth/server_info.c +index 46d8178..43711d5 100644 +--- a/source3/auth/server_info.c ++++ b/source3/auth/server_info.c +@@ -489,10 +489,28 @@ NTSTATUS passwd_to_SamInfo3(TALLOC_CTX *mem_ctx, + } + } else { + /* +- * Winbind is not running, create the group_sid from the +- * group id. ++ * Winbind is not running, try to create the group_sid from the ++ * passwd group id. ++ */ ++ ++ /* ++ * This can lead to a primary group of S-1-22-2-XX which ++ * will be rejected by other Samba code. + */ + gid_to_sid(&group_sid, pwd->pw_gid); ++ ++ ZERO_STRUCT(domain_sid); ++ ++ /* ++ * If we are a unix group, set the group_sid to the ++ * 'Domain Users' RID of 513 which will always resolve to a ++ * name. ++ */ ++ if (sid_check_is_in_unix_groups(&group_sid)) { ++ sid_compose(&group_sid, ++ get_global_sam_sid(), ++ DOMAIN_RID_USERS); ++ } + } + + /* Make sure we have a valid group sid */ +-- +1.8.5.2 + + +From 76bb5e0888f4131ab773d90160051a51c401c90d Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 18 Feb 2014 10:02:57 +0100 +Subject: [PATCH 5/7] s3-auth: Pass mem_ctx to make_server_info_sam(). + +Coverity-Id: 1168009 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=8598 + +Signed-off-by: Andreas Schneider + +Change-Id: Ie614b0654c3a7eec1ebb10dbb9763696eec795bd +Reviewed-by: Andrew Bartlett +(cherry picked from commit 3dc72266005e87a291f5bf9847257e8c54314d39) +--- + source3/auth/check_samsec.c | 2 +- + source3/auth/proto.h | 5 ++-- + source3/auth/server_info_sam.c | 56 +++++++++++++++++++++++++++--------------- + source3/auth/user_krb5.c | 12 +++++---- + 4 files changed, 47 insertions(+), 28 deletions(-) + +diff --git a/source3/auth/check_samsec.c b/source3/auth/check_samsec.c +index 7ed8cc2..b6cac60 100644 +--- a/source3/auth/check_samsec.c ++++ b/source3/auth/check_samsec.c +@@ -482,7 +482,7 @@ NTSTATUS check_sam_security(const DATA_BLOB *challenge, + } + + become_root(); +- nt_status = make_server_info_sam(server_info, sampass); ++ nt_status = make_server_info_sam(mem_ctx, sampass, server_info); + unbecome_root(); + + TALLOC_FREE(sampass); +diff --git a/source3/auth/proto.h b/source3/auth/proto.h +index 7abca07..eac3e54 100644 +--- a/source3/auth/proto.h ++++ b/source3/auth/proto.h +@@ -190,8 +190,9 @@ bool make_user_info_guest(const struct tsocket_address *remote_address, + struct auth_usersupplied_info **user_info); + + struct samu; +-NTSTATUS make_server_info_sam(struct auth_serversupplied_info **server_info, +- struct samu *sampass); ++NTSTATUS make_server_info_sam(TALLOC_CTX *mem_ctx, ++ struct samu *sampass, ++ struct auth_serversupplied_info **pserver_info); + NTSTATUS create_local_token(TALLOC_CTX *mem_ctx, + const struct auth_serversupplied_info *server_info, + DATA_BLOB *session_key, +diff --git a/source3/auth/server_info_sam.c b/source3/auth/server_info_sam.c +index 5d657f9..47087b1 100644 +--- a/source3/auth/server_info_sam.c ++++ b/source3/auth/server_info_sam.c +@@ -58,39 +58,51 @@ static bool is_our_machine_account(const char *username) + Make (and fill) a user_info struct from a struct samu + ***************************************************************************/ + +-NTSTATUS make_server_info_sam(struct auth_serversupplied_info **server_info, +- struct samu *sampass) ++NTSTATUS make_server_info_sam(TALLOC_CTX *mem_ctx, ++ struct samu *sampass, ++ struct auth_serversupplied_info **pserver_info) + { + struct passwd *pwd; +- struct auth_serversupplied_info *result; ++ struct auth_serversupplied_info *server_info; + const char *username = pdb_get_username(sampass); ++ TALLOC_CTX *tmp_ctx; + NTSTATUS status; + +- if ( !(result = make_server_info(NULL)) ) { ++ tmp_ctx = talloc_stackframe(); ++ if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + +- if ( !(pwd = Get_Pwnam_alloc(result, username)) ) { ++ server_info = make_server_info(tmp_ctx); ++ if (server_info == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ pwd = Get_Pwnam_alloc(tmp_ctx, username); ++ if (pwd == NULL) { + DEBUG(1, ("User %s in passdb, but getpwnam() fails!\n", + pdb_get_username(sampass))); +- TALLOC_FREE(result); +- return NT_STATUS_NO_SUCH_USER; ++ status = NT_STATUS_NO_SUCH_USER; ++ goto out; + } + +- status = samu_to_SamInfo3(result, sampass, lp_netbios_name(), +- &result->info3, &result->extra); ++ status = samu_to_SamInfo3(server_info, ++ sampass, ++ lp_netbios_name(), ++ &server_info->info3, ++ &server_info->extra); + if (!NT_STATUS_IS_OK(status)) { +- TALLOC_FREE(result); +- return status; ++ goto out; + } + +- result->unix_name = pwd->pw_name; +- /* Ensure that we keep pwd->pw_name, because we will free pwd below */ +- talloc_steal(result, pwd->pw_name); +- result->utok.gid = pwd->pw_gid; +- result->utok.uid = pwd->pw_uid; ++ server_info->unix_name = talloc_strdup(server_info, pwd->pw_name); ++ if (server_info->unix_name == NULL) { ++ status = NT_STATUS_NO_MEMORY; ++ goto out; ++ } + +- TALLOC_FREE(pwd); ++ server_info->utok.gid = pwd->pw_gid; ++ server_info->utok.uid = pwd->pw_uid; + + if (IS_DC && is_our_machine_account(username)) { + /* +@@ -110,9 +122,13 @@ NTSTATUS make_server_info_sam(struct auth_serversupplied_info **server_info, + } + + DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n", +- pdb_get_username(sampass), result->unix_name)); ++ pdb_get_username(sampass), server_info->unix_name)); ++ ++ *pserver_info = talloc_steal(mem_ctx, server_info); + +- *server_info = result; ++ status = NT_STATUS_OK; ++out: ++ talloc_free(tmp_ctx); + +- return NT_STATUS_OK; ++ return status; + } +diff --git a/source3/auth/user_krb5.c b/source3/auth/user_krb5.c +index 7d44285..e40c8ac 100644 +--- a/source3/auth/user_krb5.c ++++ b/source3/auth/user_krb5.c +@@ -223,9 +223,6 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, + * SID consistency with ntlmssp session setup + */ + struct samu *sampass; +- /* The stupid make_server_info_XX functions here +- don't take a talloc context. */ +- struct auth_serversupplied_info *tmp = NULL; + + sampass = samu_new(talloc_tos()); + if (sampass == NULL) { +@@ -235,14 +232,19 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, + if (pdb_getsampwnam(sampass, username)) { + DEBUG(10, ("found user %s in passdb, calling " + "make_server_info_sam\n", username)); +- status = make_server_info_sam(&tmp, sampass); ++ status = make_server_info_sam(mem_ctx, ++ sampass, ++ &server_info); + } else { + /* + * User not in passdb, make it up artificially + */ + DEBUG(10, ("didn't find user %s in passdb, calling " + "make_server_info_pw\n", username)); +- status = make_server_info_pw(mem_ctx, username, pw, &tmp); ++ status = make_server_info_pw(mem_ctx, ++ username, ++ pw, ++ &server_info); + } + + TALLOC_FREE(sampass); +-- +1.8.5.2 + + +From f9c0adb6237c6e60c33ee6af21f55c0cdefa132c Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 18 Feb 2014 10:19:57 +0100 +Subject: [PATCH 6/7] s3-auth: Pass mem_ctx to auth_check_ntlm_password(). + +Coverity-Id: 1168009 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=8598 + +Signed-off-by: Andreas Schneider + +Change-Id: Ie01674561a6a75239a13918d3190c2f21c3efc7a +Reviewed-by: Andrew Bartlett +(cherry picked from commit 4d792db03f18aa164b565c7fdc7b446c174fba28) +--- + source3/auth/auth.c | 50 ++++++++++++++++++----------- + source3/auth/auth_ntlmssp.c | 6 ++-- + source3/auth/proto.h | 8 +++-- + source3/rpc_server/netlogon/srv_netlog_nt.c | 6 ++-- + source3/torture/pdbtest.c | 5 ++- + 5 files changed, 48 insertions(+), 27 deletions(-) + +diff --git a/source3/auth/auth.c b/source3/auth/auth.c +index c3797cf..dc9af02 100644 +--- a/source3/auth/auth.c ++++ b/source3/auth/auth.c +@@ -160,18 +160,19 @@ static bool check_domain_match(const char *user, const char *domain) + * + **/ + +-NTSTATUS auth_check_ntlm_password(const struct auth_context *auth_context, +- const struct auth_usersupplied_info *user_info, +- struct auth_serversupplied_info **server_info) ++NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx, ++ const struct auth_context *auth_context, ++ const struct auth_usersupplied_info *user_info, ++ struct auth_serversupplied_info **pserver_info) + { + /* if all the modules say 'not for me' this is reasonable */ + NTSTATUS nt_status = NT_STATUS_NO_SUCH_USER; + const char *unix_username; + auth_methods *auth_method; +- TALLOC_CTX *mem_ctx; + +- if (!user_info || !auth_context || !server_info) ++ if (user_info == NULL || auth_context == NULL || pserver_info == NULL) { + return NT_STATUS_LOGON_FAILURE; ++ } + + DEBUG(3, ("check_ntlm_password: Checking password for unmapped user [%s]\\[%s]@[%s] with the new password interface\n", + user_info->client.domain_name, user_info->client.account_name, user_info->workstation_name)); +@@ -205,17 +206,27 @@ NTSTATUS auth_check_ntlm_password(const struct auth_context *auth_context, + return NT_STATUS_LOGON_FAILURE; + + for (auth_method = auth_context->auth_method_list;auth_method; auth_method = auth_method->next) { ++ struct auth_serversupplied_info *server_info; ++ TALLOC_CTX *tmp_ctx; + NTSTATUS result; + +- mem_ctx = talloc_init("%s authentication for user %s\\%s", auth_method->name, +- user_info->mapped.domain_name, user_info->client.account_name); ++ tmp_ctx = talloc_named(mem_ctx, ++ 0, ++ "%s authentication for user %s\\%s", ++ auth_method->name, ++ user_info->mapped.domain_name, ++ user_info->client.account_name); + +- result = auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info); ++ result = auth_method->auth(auth_context, ++ auth_method->private_data, ++ tmp_ctx, ++ user_info, ++ &server_info); + + /* check if the module did anything */ + if ( NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ) { + DEBUG(10,("check_ntlm_password: %s had nothing to say\n", auth_method->name)); +- talloc_destroy(mem_ctx); ++ TALLOC_FREE(tmp_ctx); + continue; + } + +@@ -229,19 +240,20 @@ NTSTATUS auth_check_ntlm_password(const struct auth_context *auth_context, + auth_method->name, user_info->client.account_name, nt_errstr(nt_status))); + } + +- talloc_destroy(mem_ctx); +- +- if ( NT_STATUS_IS_OK(nt_status)) +- { +- break; ++ if (NT_STATUS_IS_OK(nt_status)) { ++ *pserver_info = talloc_steal(mem_ctx, server_info); ++ TALLOC_FREE(tmp_ctx); ++ break; + } ++ ++ TALLOC_FREE(tmp_ctx); + } + + /* successful authentication */ + + if (NT_STATUS_IS_OK(nt_status)) { +- unix_username = (*server_info)->unix_name; +- if (!(*server_info)->guest) { ++ unix_username = (*pserver_info)->unix_name; ++ if (!(*pserver_info)->guest) { + const char *rhost; + + if (tsocket_address_is_inet(user_info->remote_host, "ip")) { +@@ -270,9 +282,9 @@ NTSTATUS auth_check_ntlm_password(const struct auth_context *auth_context, + } + + if (NT_STATUS_IS_OK(nt_status)) { +- DEBUG((*server_info)->guest ? 5 : 2, ++ DEBUG((*pserver_info)->guest ? 5 : 2, + ("check_ntlm_password: %sauthentication for user [%s] -> [%s] -> [%s] succeeded\n", +- (*server_info)->guest ? "guest " : "", ++ (*pserver_info)->guest ? "guest " : "", + user_info->client.account_name, + user_info->mapped.account_name, + unix_username)); +@@ -286,7 +298,7 @@ NTSTATUS auth_check_ntlm_password(const struct auth_context *auth_context, + DEBUG(2, ("check_ntlm_password: Authentication for user [%s] -> [%s] FAILED with error %s\n", + user_info->client.account_name, user_info->mapped.account_name, + nt_errstr(nt_status))); +- ZERO_STRUCTP(server_info); ++ ZERO_STRUCTP(pserver_info); + + return nt_status; + } +diff --git a/source3/auth/auth_ntlmssp.c b/source3/auth/auth_ntlmssp.c +index f99bd44..cb7726c 100644 +--- a/source3/auth/auth_ntlmssp.c ++++ b/source3/auth/auth_ntlmssp.c +@@ -134,8 +134,10 @@ NTSTATUS auth3_check_password(struct auth4_context *auth4_context, + + mapped_user_info->flags = user_info->flags; + +- nt_status = auth_check_ntlm_password(auth_context, +- mapped_user_info, &server_info); ++ nt_status = auth_check_ntlm_password(mem_ctx, ++ auth_context, ++ mapped_user_info, ++ &server_info); + + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(5,("Checking NTLMSSP password for %s\\%s failed: %s\n", +diff --git a/source3/auth/proto.h b/source3/auth/proto.h +index eac3e54..15b1ba0 100644 +--- a/source3/auth/proto.h ++++ b/source3/auth/proto.h +@@ -65,6 +65,8 @@ NTSTATUS auth_get_ntlm_challenge(struct auth_context *auth_context, + * struct. When the return is other than NT_STATUS_OK the contents + * of that structure is undefined. + * ++ * @param mem_ctx The memory context to use to allocate server_info ++ * + * @param user_info Contains the user supplied components, including the passwords. + * Must be created with make_user_info() or one of its wrappers. + * +@@ -79,9 +81,9 @@ NTSTATUS auth_get_ntlm_challenge(struct auth_context *auth_context, + * @return An NTSTATUS with NT_STATUS_OK or an appropriate error. + * + **/ +- +-NTSTATUS auth_check_ntlm_password(const struct auth_context *auth_context, +- const struct auth_usersupplied_info *user_info, ++NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx, ++ const struct auth_context *auth_context, ++ const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info); + + /* The following definitions come from auth/auth_builtin.c */ +diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c +index e5ca474..0c8c9a5 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -1650,8 +1650,10 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p, + } /* end switch */ + + if ( NT_STATUS_IS_OK(status) ) { +- status = auth_check_ntlm_password(auth_context, +- user_info, &server_info); ++ status = auth_check_ntlm_password(p->mem_ctx, ++ auth_context, ++ user_info, ++ &server_info); + } + + TALLOC_FREE(auth_context); +diff --git a/source3/torture/pdbtest.c b/source3/torture/pdbtest.c +index 17da455..14d58b9 100644 +--- a/source3/torture/pdbtest.c ++++ b/source3/torture/pdbtest.c +@@ -304,7 +304,10 @@ static bool test_auth(TALLOC_CTX *mem_ctx, struct samu *pdb_entry) + return False; + } + +- status = auth_check_ntlm_password(auth_context, user_info, &server_info); ++ status = auth_check_ntlm_password(mem_ctx, ++ auth_context, ++ user_info, ++ &server_info); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Failed to test authentication with auth module: %s\n", nt_errstr(status))); +-- +1.8.5.2 + + +From a48bcd84c59b5b2cb8c3e0f5d68b35065bed81d7 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 18 Feb 2014 13:52:49 +0100 +Subject: [PATCH 7/7] s3-auth: Pass mem_ctx to do_map_to_guest_server_info(). + +Change-Id: If53117023e3ab37c810193edd00a81d247fdde7a +Reviewed-by: Andrew Bartlett + +Autobuild-User(master): Andrew Bartlett +Autobuild-Date(master): Wed Feb 19 01:28:14 CET 2014 on sn-devel-104 + +(cherry picked from commit 79e2725f339e7c5336b4053348c4266268de6ca3) +--- + source3/auth/auth_ntlmssp.c | 7 ++++--- + source3/auth/auth_util.c | 12 +++++++----- + source3/auth/proto.h | 8 +++++--- + 3 files changed, 16 insertions(+), 11 deletions(-) + +diff --git a/source3/auth/auth_ntlmssp.c b/source3/auth/auth_ntlmssp.c +index cb7726c..d4fe901 100644 +--- a/source3/auth/auth_ntlmssp.c ++++ b/source3/auth/auth_ntlmssp.c +@@ -151,10 +151,11 @@ NTSTATUS auth3_check_password(struct auth4_context *auth4_context, + free_user_info(&mapped_user_info); + + if (!NT_STATUS_IS_OK(nt_status)) { +- nt_status = do_map_to_guest_server_info(nt_status, +- &server_info, ++ nt_status = do_map_to_guest_server_info(mem_ctx, ++ nt_status, + user_info->client.account_name, +- user_info->client.domain_name); ++ user_info->client.domain_name, ++ &server_info); + *server_returned_info = talloc_steal(mem_ctx, server_info); + return nt_status; + } +diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c +index 24190af..8cf5cb7 100644 +--- a/source3/auth/auth_util.c ++++ b/source3/auth/auth_util.c +@@ -1536,9 +1536,11 @@ bool is_trusted_domain(const char* dom_name) + on a logon error possibly map the error to success if "map to guest" + is set approriately + */ +-NTSTATUS do_map_to_guest_server_info(NTSTATUS status, +- struct auth_serversupplied_info **server_info, +- const char *user, const char *domain) ++NTSTATUS do_map_to_guest_server_info(TALLOC_CTX *mem_ctx, ++ NTSTATUS status, ++ const char *user, ++ const char *domain, ++ struct auth_serversupplied_info **server_info) + { + user = user ? user : ""; + domain = domain ? domain : ""; +@@ -1548,13 +1550,13 @@ NTSTATUS do_map_to_guest_server_info(NTSTATUS status, + (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { + DEBUG(3,("No such user %s [%s] - using guest account\n", + user, domain)); +- return make_server_info_guest(NULL, server_info); ++ return make_server_info_guest(mem_ctx, server_info); + } + } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) { + if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { + DEBUG(3,("Registered username %s for guest access\n", + user)); +- return make_server_info_guest(NULL, server_info); ++ return make_server_info_guest(mem_ctx, server_info); + } + } + +diff --git a/source3/auth/proto.h b/source3/auth/proto.h +index 15b1ba0..7b8959f 100644 +--- a/source3/auth/proto.h ++++ b/source3/auth/proto.h +@@ -264,9 +264,11 @@ NTSTATUS make_user_info(struct auth_usersupplied_info **ret_user_info, + enum auth_password_state password_state); + void free_user_info(struct auth_usersupplied_info **user_info); + +-NTSTATUS do_map_to_guest_server_info(NTSTATUS status, +- struct auth_serversupplied_info **server_info, +- const char *user, const char *domain); ++NTSTATUS do_map_to_guest_server_info(TALLOC_CTX *mem_ctx, ++ NTSTATUS status, ++ const char *user, ++ const char *domain, ++ struct auth_serversupplied_info **server_info); + + /* The following definitions come from auth/auth_winbind.c */ + +-- +1.8.5.2 + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/02-fix-ipv6-join.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/02-fix-ipv6-join.patch new file mode 100644 index 00000000..daa283e6 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/02-fix-ipv6-join.patch @@ -0,0 +1,266 @@ +From 168627e1877317db86471a4b0360dccd9f469aaa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Mon, 13 Jan 2014 15:59:26 +0100 +Subject: [PATCH 1/2] s3-kerberos: remove print_kdc_line() completely. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Just calling print_canonical_sockaddr() is sufficient, as it already deals with +ipv6 as well. The port handling, which was only done for IPv6 (not IPv4), is +removed as well. It was pointless because it always derived the port number from +the provided address which was either a SMB (usually port 445) or LDAP +connection. No KDC will ever run on port 389 or 445 on a Windows/Samba DC. +Finally, the kerberos libraries that we support and build with, can deal with +ipv6 addresses in krb5.conf, so we no longer put the (unnecessary) burden of +resolving the DC name on the kerberos library anymore. + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider +--- + source3/libads/kerberos.c | 73 ++++------------------------------------------- + 1 file changed, 5 insertions(+), 68 deletions(-) + +diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c +index b026e09..ea14350 100644 +--- a/source3/libads/kerberos.c ++++ b/source3/libads/kerberos.c +@@ -592,70 +592,6 @@ int kerberos_kinit_password(const char *principal, + /************************************************************************ + ************************************************************************/ + +-static char *print_kdc_line(char *mem_ctx, +- const char *prev_line, +- const struct sockaddr_storage *pss, +- const char *kdc_name) +-{ +- char addr[INET6_ADDRSTRLEN]; +- uint16_t port = get_sockaddr_port(pss); +- +- if (pss->ss_family == AF_INET) { +- return talloc_asprintf(mem_ctx, "%s\tkdc = %s\n", +- prev_line, +- print_canonical_sockaddr(mem_ctx, pss)); +- } +- +- /* +- * IPv6 starts here +- */ +- +- DEBUG(10, ("print_kdc_line: IPv6 case for kdc_name: %s, port: %d\n", +- kdc_name, port)); +- +- if (port != 0 && port != DEFAULT_KRB5_PORT) { +- /* Currently for IPv6 we can't specify a non-default +- krb5 port with an address, as this requires a ':'. +- Resolve to a name. */ +- char hostname[MAX_DNS_NAME_LENGTH]; +- int ret = sys_getnameinfo((const struct sockaddr *)pss, +- sizeof(*pss), +- hostname, sizeof(hostname), +- NULL, 0, +- NI_NAMEREQD); +- if (ret) { +- DEBUG(0,("print_kdc_line: can't resolve name " +- "for kdc with non-default port %s. " +- "Error %s\n.", +- print_canonical_sockaddr(mem_ctx, pss), +- gai_strerror(ret))); +- return NULL; +- } +- /* Success, use host:port */ +- return talloc_asprintf(mem_ctx, +- "%s\tkdc = %s:%u\n", +- prev_line, +- hostname, +- (unsigned int)port); +- } +- +- /* no krb5 lib currently supports "kdc = ipv6 address" +- * at all, so just fill in just the kdc_name if we have +- * it and let the krb5 lib figure out the appropriate +- * ipv6 address - gd */ +- +- if (kdc_name) { +- return talloc_asprintf(mem_ctx, "%s\tkdc = %s\n", +- prev_line, kdc_name); +- } +- +- return talloc_asprintf(mem_ctx, "%s\tkdc = %s\n", +- prev_line, +- print_sockaddr(addr, +- sizeof(addr), +- pss)); +-} +- + /************************************************************************ + Create a string list of available kdc's, possibly searching by sitename. + Does DNS queries. +@@ -698,7 +634,8 @@ static char *get_kdc_ip_string(char *mem_ctx, + char *result = NULL; + struct netlogon_samlogon_response **responses = NULL; + NTSTATUS status; +- char *kdc_str = print_kdc_line(mem_ctx, "", pss, kdc_name); ++ char *kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n", "", ++ print_canonical_sockaddr(mem_ctx, pss)); + + if (kdc_str == NULL) { + TALLOC_FREE(frame); +@@ -788,9 +725,9 @@ static char *get_kdc_ip_string(char *mem_ctx, + } + + /* Append to the string - inefficient but not done often. */ +- new_kdc_str = print_kdc_line(mem_ctx, kdc_str, +- &dc_addrs[i], +- kdc_name); ++ new_kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n", ++ kdc_str, ++ print_canonical_sockaddr(mem_ctx, &dc_addrs[i])); + if (new_kdc_str == NULL) { + goto fail; + } +-- +1.8.5.3 + + +From 3edb3d4084548960f03356cf4c44a6892e6efb84 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 7 Mar 2014 14:47:31 +0100 +Subject: [PATCH 2/2] s3-kerberos: remove unused kdc_name from + create_local_private_krb5_conf_for_domain(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider +--- + source3/libads/kerberos.c | 10 ++++------ + source3/libads/kerberos_proto.h | 3 +-- + source3/libnet/libnet_join.c | 3 +-- + source3/libsmb/namequery_dc.c | 6 ++---- + source3/winbindd/winbindd_cm.c | 6 ++---- + 5 files changed, 10 insertions(+), 18 deletions(-) + +diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c +index ea14350..649e568 100644 +--- a/source3/libads/kerberos.c ++++ b/source3/libads/kerberos.c +@@ -618,8 +618,7 @@ static void add_sockaddr_unique(struct sockaddr_storage *addrs, int *num_addrs, + static char *get_kdc_ip_string(char *mem_ctx, + const char *realm, + const char *sitename, +- const struct sockaddr_storage *pss, +- const char *kdc_name) ++ const struct sockaddr_storage *pss) + { + TALLOC_CTX *frame = talloc_stackframe(); + int i; +@@ -756,8 +755,7 @@ fail: + bool create_local_private_krb5_conf_for_domain(const char *realm, + const char *domain, + const char *sitename, +- const struct sockaddr_storage *pss, +- const char *kdc_name) ++ const struct sockaddr_storage *pss) + { + char *dname; + char *tmpname = NULL; +@@ -782,7 +780,7 @@ bool create_local_private_krb5_conf_for_domain(const char *realm, + return false; + } + +- if (domain == NULL || pss == NULL || kdc_name == NULL) { ++ if (domain == NULL || pss == NULL) { + return false; + } + +@@ -815,7 +813,7 @@ bool create_local_private_krb5_conf_for_domain(const char *realm, + goto done; + } + +- kdc_ip_string = get_kdc_ip_string(dname, realm, sitename, pss, kdc_name); ++ kdc_ip_string = get_kdc_ip_string(dname, realm, sitename, pss); + if (!kdc_ip_string) { + goto done; + } +diff --git a/source3/libads/kerberos_proto.h b/source3/libads/kerberos_proto.h +index f7470d2..2559634 100644 +--- a/source3/libads/kerberos_proto.h ++++ b/source3/libads/kerberos_proto.h +@@ -62,8 +62,7 @@ int kerberos_kinit_password(const char *principal, + bool create_local_private_krb5_conf_for_domain(const char *realm, + const char *domain, + const char *sitename, +- const struct sockaddr_storage *pss, +- const char *kdc_name); ++ const struct sockaddr_storage *pss); + + /* The following definitions come from libads/authdata.c */ + +diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c +index a87eb38..68884cd 100644 +--- a/source3/libnet/libnet_join.c ++++ b/source3/libnet/libnet_join.c +@@ -2152,8 +2152,7 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx, + + create_local_private_krb5_conf_for_domain( + r->out.dns_domain_name, r->out.netbios_domain_name, +- NULL, smbXcli_conn_remote_sockaddr(cli->conn), +- smbXcli_conn_remote_name(cli->conn)); ++ NULL, smbXcli_conn_remote_sockaddr(cli->conn)); + + if (r->out.domain_is_ad && r->in.account_ou && + !(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) { +diff --git a/source3/libsmb/namequery_dc.c b/source3/libsmb/namequery_dc.c +index 3cfae79..eb34741 100644 +--- a/source3/libsmb/namequery_dc.c ++++ b/source3/libsmb/namequery_dc.c +@@ -112,14 +112,12 @@ static bool ads_dc_name(const char *domain, + create_local_private_krb5_conf_for_domain(realm, + domain, + sitename, +- &ads->ldap.ss, +- ads->config.ldap_server_name); ++ &ads->ldap.ss); + } else { + create_local_private_krb5_conf_for_domain(realm, + domain, + NULL, +- &ads->ldap.ss, +- ads->config.ldap_server_name); ++ &ads->ldap.ss); + } + } + #endif +diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c +index 669a43e..be13a57 100644 +--- a/source3/winbindd/winbindd_cm.c ++++ b/source3/winbindd/winbindd_cm.c +@@ -1233,8 +1233,7 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx, + create_local_private_krb5_conf_for_domain(domain->alt_name, + domain->name, + sitename, +- pss, +- *name); ++ pss); + + SAFE_FREE(sitename); + } else { +@@ -1242,8 +1241,7 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx, + create_local_private_krb5_conf_for_domain(domain->alt_name, + domain->name, + NULL, +- pss, +- *name); ++ pss); + } + winbindd_set_locator_kdc_envs(domain); + +-- +1.8.5.3 + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/03-net-ads-kerberos-pac.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/03-net-ads-kerberos-pac.patch new file mode 100644 index 00000000..26a4caf0 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/03-net-ads-kerberos-pac.patch @@ -0,0 +1,962 @@ +From 932490ae08578c37523e00e537017603ee00ce7c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 17 Jan 2014 14:29:03 +0100 +Subject: [PATCH 1/8] s3-libads: pass down local_service to + kerberos_return_pac(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider +--- + source3/libads/authdata.c | 6 +----- + source3/libads/kerberos_proto.h | 1 + + source3/utils/net_ads.c | 8 ++++++++ + source3/winbindd/winbindd_pam.c | 9 +++++++++ + 4 files changed, 19 insertions(+), 5 deletions(-) + +diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c +index 801e551..dd80dc2 100644 +--- a/source3/libads/authdata.c ++++ b/source3/libads/authdata.c +@@ -101,13 +101,13 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, + bool add_netbios_addr, + time_t renewable_time, + const char *impersonate_princ_s, ++ const char *local_service, + struct PAC_LOGON_INFO **_logon_info) + { + krb5_error_code ret; + NTSTATUS status = NT_STATUS_INVALID_PARAMETER; + DATA_BLOB tkt, tkt_wrapped, ap_rep, sesskey1; + const char *auth_princ = NULL; +- const char *local_service = NULL; + const char *cc = "MEMORY:kerberos_return_pac"; + struct auth_session_info *session_info; + struct gensec_security *gensec_server_context; +@@ -141,10 +141,6 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, + } + NT_STATUS_HAVE_NO_MEMORY(auth_princ); + +- local_service = talloc_asprintf(mem_ctx, "%s$@%s", +- lp_netbios_name(), lp_realm()); +- NT_STATUS_HAVE_NO_MEMORY(local_service); +- + ret = kerberos_kinit_password_ext(auth_princ, + pass, + time_offset, +diff --git a/source3/libads/kerberos_proto.h b/source3/libads/kerberos_proto.h +index 2559634..1151d66 100644 +--- a/source3/libads/kerberos_proto.h ++++ b/source3/libads/kerberos_proto.h +@@ -77,6 +77,7 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, + bool add_netbios_addr, + time_t renewable_time, + const char *impersonate_princ_s, ++ const char *local_service, + struct PAC_LOGON_INFO **logon_info); + + /* The following definitions come from libads/krb5_setpw.c */ +diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c +index 89eebf3..5a073b1 100644 +--- a/source3/utils/net_ads.c ++++ b/source3/utils/net_ads.c +@@ -2604,6 +2604,7 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar + NTSTATUS status; + int ret = -1; + const char *impersonate_princ_s = NULL; ++ const char *local_service = NULL; + + if (c->display_usage) { + d_printf( "%s\n" +@@ -2623,6 +2624,12 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar + impersonate_princ_s = argv[0]; + } + ++ local_service = talloc_asprintf(mem_ctx, "%s$@%s", ++ lp_netbios_name(), lp_realm()); ++ if (local_service == NULL) { ++ goto out; ++ } ++ + c->opt_password = net_prompt_pass(c, c->opt_user_name); + + status = kerberos_return_pac(mem_ctx, +@@ -2636,6 +2643,7 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar + true, + 2592000, /* one month */ + impersonate_princ_s, ++ local_service, + &info); + if (!NT_STATUS_IS_OK(status)) { + d_printf(_("failed to query kerberos PAC: %s\n"), +diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c +index 3f3ec70..61e2cef 100644 +--- a/source3/winbindd/winbindd_pam.c ++++ b/source3/winbindd/winbindd_pam.c +@@ -576,6 +576,7 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx, + time_t time_offset = 0; + const char *user_ccache_file; + struct PAC_LOGON_INFO *logon_info = NULL; ++ const char *local_service; + + *info3 = NULL; + +@@ -632,6 +633,13 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx, + return NT_STATUS_NO_MEMORY; + } + ++ local_service = talloc_asprintf(mem_ctx, "%s$@%s", ++ lp_netbios_name(), lp_realm()); ++ if (local_service == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ + /* if this is a user ccache, we need to act as the user to let the krb5 + * library handle the chown, etc. */ + +@@ -653,6 +661,7 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx, + true, + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, + NULL, ++ local_service, + &logon_info); + if (user_ccache_file != NULL) { + gain_root_privilege(); +-- +1.8.5.3 + + +From baed403983a5bb2e728249443fdfc9167a87f526 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Mon, 3 Mar 2014 12:14:51 +0100 +Subject: [PATCH 2/8] auth/kerberos: fix a typo. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider +--- + auth/kerberos/kerberos_pac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/auth/kerberos/kerberos_pac.c b/auth/kerberos/kerberos_pac.c +index 81f7f21..8f55c8f 100644 +--- a/auth/kerberos/kerberos_pac.c ++++ b/auth/kerberos/kerberos_pac.c +@@ -79,7 +79,7 @@ krb5_error_code check_pac_checksum(DATA_BLOB pac_data, + } + + /** +-* @brief Decode a blob containing a NDR envoded PAC structure ++* @brief Decode a blob containing a NDR encoded PAC structure + * + * @param mem_ctx - The memory context + * @param pac_data_blob - The data blob containing the NDR encoded data +-- +1.8.5.3 + + +From 9725a86e60bb6ef6e912621e81acc955ae2f70a8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Mon, 10 Mar 2014 15:11:18 +0100 +Subject: [PATCH 3/8] s3-net: change the way impersonation principals are used + in "net ads kerberos pac". +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider +--- + source3/utils/net_ads.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c +index 5a073b1..ac6346f 100644 +--- a/source3/utils/net_ads.c ++++ b/source3/utils/net_ads.c +@@ -2605,6 +2605,7 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar + int ret = -1; + const char *impersonate_princ_s = NULL; + const char *local_service = NULL; ++ int i; + + if (c->display_usage) { + d_printf( "%s\n" +@@ -2615,15 +2616,20 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar + return 0; + } + ++ for (i=0; i 0) { +- impersonate_princ_s = argv[0]; +- } +- + local_service = talloc_asprintf(mem_ctx, "%s$@%s", + lp_netbios_name(), lp_realm()); + if (local_service == NULL) { +-- +1.8.5.3 + + +From 35a1ed22f65473fabb2f4846f6d2b50da1847f6a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Tue, 11 Mar 2014 16:34:36 +0100 +Subject: [PATCH 4/8] s3-net: allow to provide custom local_service in "net ads + kerberos pac". +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider +--- + source3/utils/net_ads.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c +index ac6346f..c53c8c6 100644 +--- a/source3/utils/net_ads.c ++++ b/source3/utils/net_ads.c +@@ -2623,6 +2623,12 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar + return -1; + } + } ++ if (strnequal(argv[i], "local_service", strlen("local_service"))) { ++ local_service = get_string_param(argv[i]); ++ if (local_service == NULL) { ++ return -1; ++ } ++ } + } + + mem_ctx = talloc_init("net_ads_kerberos_pac"); +@@ -2630,10 +2636,12 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar + goto out; + } + +- local_service = talloc_asprintf(mem_ctx, "%s$@%s", +- lp_netbios_name(), lp_realm()); + if (local_service == NULL) { +- goto out; ++ local_service = talloc_asprintf(mem_ctx, "%s$@%s", ++ lp_netbios_name(), lp_realm()); ++ if (local_service == NULL) { ++ goto out; ++ } + } + + c->opt_password = net_prompt_pass(c, c->opt_user_name); +-- +1.8.5.3 + + +From 1270e35ba70a4e4881512d375c767023512f67bd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 21 Feb 2014 18:56:04 +0100 +Subject: [PATCH 5/8] s3-kerberos: return a full PAC in kerberos_return_pac(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider +--- + source3/libads/authdata.c | 28 +++++++++++++++++----------- + source3/libads/kerberos_proto.h | 4 ++-- + source3/utils/net_ads.c | 17 ++++++++++++++++- + source3/winbindd/winbindd_pam.c | 22 +++++++++++++++++++++- + 4 files changed, 56 insertions(+), 15 deletions(-) + +diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c +index dd80dc2..53e40ef 100644 +--- a/source3/libads/authdata.c ++++ b/source3/libads/authdata.c +@@ -52,7 +52,7 @@ static NTSTATUS kerberos_fetch_pac(struct auth4_context *auth_ctx, + struct auth_session_info **session_info) + { + TALLOC_CTX *tmp_ctx; +- struct PAC_LOGON_INFO *logon_info = NULL; ++ struct PAC_DATA *pac_data = NULL; + NTSTATUS status = NT_STATUS_INTERNAL_ERROR; + + tmp_ctx = talloc_new(mem_ctx); +@@ -61,16 +61,22 @@ static NTSTATUS kerberos_fetch_pac(struct auth4_context *auth_ctx, + } + + if (pac_blob) { +- status = kerberos_pac_logon_info(tmp_ctx, *pac_blob, NULL, NULL, +- NULL, NULL, 0, &logon_info); ++ status = kerberos_decode_pac(tmp_ctx, ++ *pac_blob, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ 0, ++ &pac_data); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + } + +- talloc_set_name_const(logon_info, "struct PAC_LOGON_INFO"); ++ talloc_set_name_const(pac_data, "struct PAC_DATA"); + +- auth_ctx->private_data = talloc_steal(auth_ctx, logon_info); ++ auth_ctx->private_data = talloc_steal(auth_ctx, pac_data); + *session_info = talloc_zero(mem_ctx, struct auth_session_info); + if (!*session_info) { + status = NT_STATUS_NO_MEMORY; +@@ -102,7 +108,7 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, + time_t renewable_time, + const char *impersonate_princ_s, + const char *local_service, +- struct PAC_LOGON_INFO **_logon_info) ++ struct PAC_DATA **_pac_data) + { + krb5_error_code ret; + NTSTATUS status = NT_STATUS_INVALID_PARAMETER; +@@ -116,7 +122,7 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, + size_t idx = 0; + struct auth4_context *auth_context; + struct loadparm_context *lp_ctx; +- struct PAC_LOGON_INFO *logon_info = NULL; ++ struct PAC_DATA *pac_data = NULL; + + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); +@@ -272,15 +278,15 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, + goto out; + } + +- logon_info = talloc_get_type_abort(gensec_server_context->auth_context->private_data, +- struct PAC_LOGON_INFO); +- if (logon_info == NULL) { ++ pac_data = talloc_get_type_abort(gensec_server_context->auth_context->private_data, ++ struct PAC_DATA); ++ if (pac_data == NULL) { + DEBUG(1,("no PAC\n")); + status = NT_STATUS_INVALID_PARAMETER; + goto out; + } + +- *_logon_info = talloc_move(mem_ctx, &logon_info); ++ *_pac_data = talloc_move(mem_ctx, &pac_data); + + out: + talloc_free(tmp_ctx); +diff --git a/source3/libads/kerberos_proto.h b/source3/libads/kerberos_proto.h +index 1151d66..b2f7486 100644 +--- a/source3/libads/kerberos_proto.h ++++ b/source3/libads/kerberos_proto.h +@@ -32,7 +32,7 @@ + + #include "system/kerberos.h" + +-struct PAC_LOGON_INFO; ++struct PAC_DATA; + + #include "libads/ads_status.h" + +@@ -78,7 +78,7 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, + time_t renewable_time, + const char *impersonate_princ_s, + const char *local_service, +- struct PAC_LOGON_INFO **logon_info); ++ struct PAC_DATA **pac_data); + + /* The following definitions come from libads/krb5_setpw.c */ + +diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c +index c53c8c6..19da6da 100644 +--- a/source3/utils/net_ads.c ++++ b/source3/utils/net_ads.c +@@ -2600,6 +2600,7 @@ static int net_ads_kerberos_renew(struct net_context *c, int argc, const char ** + static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv) + { + struct PAC_LOGON_INFO *info = NULL; ++ struct PAC_DATA *pac_data = NULL; + TALLOC_CTX *mem_ctx = NULL; + NTSTATUS status; + int ret = -1; +@@ -2658,13 +2659,27 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar + 2592000, /* one month */ + impersonate_princ_s, + local_service, +- &info); ++ &pac_data); + if (!NT_STATUS_IS_OK(status)) { + d_printf(_("failed to query kerberos PAC: %s\n"), + nt_errstr(status)); + goto out; + } + ++ for (i=0; i < pac_data->num_buffers; i++) { ++ ++ if (pac_data->buffers[i].type != PAC_TYPE_LOGON_INFO) { ++ continue; ++ } ++ ++ info = pac_data->buffers[i].info->logon_info.info; ++ if (!info) { ++ goto out; ++ } ++ ++ break; ++ } ++ + if (info) { + const char *s; + s = NDR_PRINT_STRUCT_STRING(mem_ctx, PAC_LOGON_INFO, info); +diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c +index 61e2cef..a8daae51 100644 +--- a/source3/winbindd/winbindd_pam.c ++++ b/source3/winbindd/winbindd_pam.c +@@ -576,7 +576,9 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx, + time_t time_offset = 0; + const char *user_ccache_file; + struct PAC_LOGON_INFO *logon_info = NULL; ++ struct PAC_DATA *pac_data = NULL; + const char *local_service; ++ int i; + + *info3 = NULL; + +@@ -662,7 +664,7 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx, + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, + NULL, + local_service, +- &logon_info); ++ &pac_data); + if (user_ccache_file != NULL) { + gain_root_privilege(); + } +@@ -673,6 +675,24 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx, + goto failed; + } + ++ if (pac_data == NULL) { ++ goto failed; ++ } ++ ++ for (i=0; i < pac_data->num_buffers; i++) { ++ ++ if (pac_data->buffers[i].type != PAC_TYPE_LOGON_INFO) { ++ continue; ++ } ++ ++ logon_info = pac_data->buffers[i].info->logon_info.info; ++ if (!logon_info) { ++ return NT_STATUS_INVALID_PARAMETER; ++ } ++ ++ break; ++ } ++ + *info3 = &logon_info->info3; + + DEBUG(10,("winbindd_raw_kerberos_login: winbindd validated ticket of %s\n", +-- +1.8.5.3 + + +From a8c2807a26d2f1ff094ed7ea5724c0394f79b888 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Tue, 11 Mar 2014 18:07:11 +0100 +Subject: [PATCH 6/8] s3-kerberos: let kerberos_return_pac() return a PAC + container. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider +--- + source3/libads/authdata.c | 29 +++++++++++++++++++++-------- + source3/libads/kerberos_proto.h | 7 ++++++- + source3/utils/net_ads.c | 5 ++++- + source3/winbindd/winbindd_pam.c | 8 +++++++- + 4 files changed, 38 insertions(+), 11 deletions(-) + +diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c +index 53e40ef..276408d 100644 +--- a/source3/libads/authdata.c ++++ b/source3/libads/authdata.c +@@ -53,6 +53,7 @@ static NTSTATUS kerberos_fetch_pac(struct auth4_context *auth_ctx, + { + TALLOC_CTX *tmp_ctx; + struct PAC_DATA *pac_data = NULL; ++ struct PAC_DATA_CTR *pac_data_ctr = NULL; + NTSTATUS status = NT_STATUS_INTERNAL_ERROR; + + tmp_ctx = talloc_new(mem_ctx); +@@ -74,9 +75,21 @@ static NTSTATUS kerberos_fetch_pac(struct auth4_context *auth_ctx, + } + } + +- talloc_set_name_const(pac_data, "struct PAC_DATA"); ++ pac_data_ctr = talloc(mem_ctx, struct PAC_DATA_CTR); ++ if (pac_data_ctr == NULL) { ++ status = NT_STATUS_NO_MEMORY; ++ goto done; ++ } ++ ++ talloc_set_name_const(pac_data_ctr, "struct PAC_DATA_CTR"); ++ ++ pac_data_ctr->pac_data = talloc_steal(pac_data_ctr, pac_data); ++ pac_data_ctr->pac_blob = data_blob_talloc(pac_data_ctr, ++ pac_blob->data, ++ pac_blob->length); ++ ++ auth_ctx->private_data = talloc_steal(auth_ctx, pac_data_ctr); + +- auth_ctx->private_data = talloc_steal(auth_ctx, pac_data); + *session_info = talloc_zero(mem_ctx, struct auth_session_info); + if (!*session_info) { + status = NT_STATUS_NO_MEMORY; +@@ -108,7 +121,7 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, + time_t renewable_time, + const char *impersonate_princ_s, + const char *local_service, +- struct PAC_DATA **_pac_data) ++ struct PAC_DATA_CTR **_pac_data_ctr) + { + krb5_error_code ret; + NTSTATUS status = NT_STATUS_INVALID_PARAMETER; +@@ -122,7 +135,7 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, + size_t idx = 0; + struct auth4_context *auth_context; + struct loadparm_context *lp_ctx; +- struct PAC_DATA *pac_data = NULL; ++ struct PAC_DATA_CTR *pac_data_ctr = NULL; + + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); +@@ -278,15 +291,15 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, + goto out; + } + +- pac_data = talloc_get_type_abort(gensec_server_context->auth_context->private_data, +- struct PAC_DATA); +- if (pac_data == NULL) { ++ pac_data_ctr = talloc_get_type_abort(gensec_server_context->auth_context->private_data, ++ struct PAC_DATA_CTR); ++ if (pac_data_ctr == NULL) { + DEBUG(1,("no PAC\n")); + status = NT_STATUS_INVALID_PARAMETER; + goto out; + } + +- *_pac_data = talloc_move(mem_ctx, &pac_data); ++ *_pac_data_ctr = talloc_move(mem_ctx, &pac_data_ctr); + + out: + talloc_free(tmp_ctx); +diff --git a/source3/libads/kerberos_proto.h b/source3/libads/kerberos_proto.h +index b2f7486..3d0ad4b 100644 +--- a/source3/libads/kerberos_proto.h ++++ b/source3/libads/kerberos_proto.h +@@ -34,6 +34,11 @@ + + struct PAC_DATA; + ++struct PAC_DATA_CTR { ++ DATA_BLOB pac_blob; ++ struct PAC_DATA *pac_data; ++}; ++ + #include "libads/ads_status.h" + + /* The following definitions come from libads/kerberos.c */ +@@ -78,7 +83,7 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, + time_t renewable_time, + const char *impersonate_princ_s, + const char *local_service, +- struct PAC_DATA **pac_data); ++ struct PAC_DATA_CTR **pac_data_ctr); + + /* The following definitions come from libads/krb5_setpw.c */ + +diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c +index 19da6da..19c28b1 100644 +--- a/source3/utils/net_ads.c ++++ b/source3/utils/net_ads.c +@@ -2601,6 +2601,7 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar + { + struct PAC_LOGON_INFO *info = NULL; + struct PAC_DATA *pac_data = NULL; ++ struct PAC_DATA_CTR *pac_data_ctr = NULL; + TALLOC_CTX *mem_ctx = NULL; + NTSTATUS status; + int ret = -1; +@@ -2659,13 +2660,15 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar + 2592000, /* one month */ + impersonate_princ_s, + local_service, +- &pac_data); ++ &pac_data_ctr); + if (!NT_STATUS_IS_OK(status)) { + d_printf(_("failed to query kerberos PAC: %s\n"), + nt_errstr(status)); + goto out; + } + ++ pac_data = pac_data_ctr->pac_data; ++ + for (i=0; i < pac_data->num_buffers; i++) { + + if (pac_data->buffers[i].type != PAC_TYPE_LOGON_INFO) { +diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c +index a8daae51..b41291e 100644 +--- a/source3/winbindd/winbindd_pam.c ++++ b/source3/winbindd/winbindd_pam.c +@@ -577,6 +577,7 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx, + const char *user_ccache_file; + struct PAC_LOGON_INFO *logon_info = NULL; + struct PAC_DATA *pac_data = NULL; ++ struct PAC_DATA_CTR *pac_data_ctr = NULL; + const char *local_service; + int i; + +@@ -664,7 +665,7 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx, + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, + NULL, + local_service, +- &pac_data); ++ &pac_data_ctr); + if (user_ccache_file != NULL) { + gain_root_privilege(); + } +@@ -675,6 +676,11 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx, + goto failed; + } + ++ if (pac_data_ctr == NULL) { ++ goto failed; ++ } ++ ++ pac_data = pac_data_ctr->pac_data; + if (pac_data == NULL) { + goto failed; + } +-- +1.8.5.3 + + +From 9e01f3cbc4752539128e5452f567ff2e73c3ec9d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Tue, 11 Mar 2014 18:14:39 +0100 +Subject: [PATCH 7/8] s3-net: modify the current "net ads kerberos pac" + command. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Rename it to "net ads kerberos pac dump" and add a "type=num" option to allow +dumping of individial pac buffer types. Ommitting type= or using type=0 will +dump the whole PAC structure on stdout. + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider +--- + source3/utils/net_ads.c | 115 ++++++++++++++++++++++++++++++++---------------- + 1 file changed, 77 insertions(+), 38 deletions(-) + +diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c +index 19c28b1..f54cf23 100644 +--- a/source3/utils/net_ads.c ++++ b/source3/utils/net_ads.c +@@ -2597,27 +2597,15 @@ static int net_ads_kerberos_renew(struct net_context *c, int argc, const char ** + return ret; + } + +-static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv) ++static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv, ++ struct PAC_DATA_CTR **pac_data_ctr) + { +- struct PAC_LOGON_INFO *info = NULL; +- struct PAC_DATA *pac_data = NULL; +- struct PAC_DATA_CTR *pac_data_ctr = NULL; +- TALLOC_CTX *mem_ctx = NULL; + NTSTATUS status; + int ret = -1; + const char *impersonate_princ_s = NULL; + const char *local_service = NULL; + int i; + +- if (c->display_usage) { +- d_printf( "%s\n" +- "net ads kerberos pac [impersonation_principal]\n" +- " %s\n", +- _("Usage:"), +- _("Dump the Kerberos PAC")); +- return 0; +- } +- + for (i=0; iopt_password = net_prompt_pass(c, c->opt_user_name); + +- status = kerberos_return_pac(mem_ctx, ++ status = kerberos_return_pac(c, + c->opt_user_name, + c->opt_password, + 0, +@@ -2660,39 +2643,95 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar + 2592000, /* one month */ + impersonate_princ_s, + local_service, +- &pac_data_ctr); ++ pac_data_ctr); + if (!NT_STATUS_IS_OK(status)) { + d_printf(_("failed to query kerberos PAC: %s\n"), + nt_errstr(status)); + goto out; + } + +- pac_data = pac_data_ctr->pac_data; ++ ret = 0; ++ out: ++ return ret; ++} + +- for (i=0; i < pac_data->num_buffers; i++) { ++static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv) ++{ ++ struct PAC_DATA_CTR *pac_data_ctr = NULL; ++ int i; ++ int ret = -1; ++ enum PAC_TYPE type = 0; + +- if (pac_data->buffers[i].type != PAC_TYPE_LOGON_INFO) { +- continue; ++ if (c->display_usage) { ++ d_printf( "%s\n" ++ "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n" ++ " %s\n", ++ _("Usage:"), ++ _("Dump the Kerberos PAC")); ++ return -1; ++ } ++ ++ for (i=0; ibuffers[i].info->logon_info.info; +- if (!info) { +- goto out; ++ ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr); ++ if (ret) { ++ return ret; ++ } ++ ++ if (type == 0) { ++ ++ char *s = NULL; ++ ++ s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA, ++ pac_data_ctr->pac_data); ++ if (s != NULL) { ++ d_printf(_("The Pac: %s\n"), s); ++ talloc_free(s); + } + +- break; ++ return 0; + } + +- if (info) { +- const char *s; +- s = NDR_PRINT_STRUCT_STRING(mem_ctx, PAC_LOGON_INFO, info); +- d_printf(_("The Pac: %s\n"), s); ++ for (i=0; i < pac_data_ctr->pac_data->num_buffers; i++) { ++ ++ char *s = NULL; ++ ++ if (pac_data_ctr->pac_data->buffers[i].type != type) { ++ continue; ++ } ++ ++ s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type, ++ pac_data_ctr->pac_data->buffers[i].info); ++ if (s != NULL) { ++ d_printf(_("The Pac: %s\n"), s); ++ talloc_free(s); ++ } ++ break; + } + +- ret = 0; +- out: +- TALLOC_FREE(mem_ctx); +- return ret; ++ return 0; ++} ++ ++static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv) ++{ ++ struct functable func[] = { ++ { ++ "dump", ++ net_ads_kerberos_pac_dump, ++ NET_TRANSPORT_ADS, ++ N_("Dump Kerberos PAC"), ++ N_("net ads kerberos pac dump\n" ++ " Dump a Kerberos PAC to stdout") ++ }, ++ ++ {NULL, NULL, 0, NULL, NULL} ++ }; ++ ++ return net_run_function(c, argc, argv, "net ads kerberos pac", func); + } + + static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv) +-- +1.8.5.3 + + +From 91ceace4ee8fd141cac5dbe5282bed141c38bee7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Tue, 11 Mar 2014 18:16:40 +0100 +Subject: [PATCH 8/8] s3-net: add a new "net ads kerberos pac save" tool. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use "filename=string" to define a file where to save the unencrypted PAC to. + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider +--- + source3/utils/net_ads.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + +diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c +index f54cf23..8b8e719 100644 +--- a/source3/utils/net_ads.c ++++ b/source3/utils/net_ads.c +@@ -2716,6 +2716,50 @@ static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char + return 0; + } + ++static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv) ++{ ++ struct PAC_DATA_CTR *pac_data_ctr = NULL; ++ char *filename = NULL; ++ int ret = -1; ++ int i; ++ ++ if (c->display_usage) { ++ d_printf( "%s\n" ++ "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n" ++ " %s\n", ++ _("Usage:"), ++ _("Save the Kerberos PAC")); ++ return -1; ++ } ++ ++ for (i=0; i\" to save the PAC\n")); ++ return -1; ++ } ++ ++ /* save the raw format */ ++ if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) { ++ d_printf(_("failed to save PAC in %s\n"), filename); ++ return -1; ++ } ++ ++ return 0; ++} ++ + static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv) + { + struct functable func[] = { +@@ -2727,6 +2771,14 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar + N_("net ads kerberos pac dump\n" + " Dump a Kerberos PAC to stdout") + }, ++ { ++ "save", ++ net_ads_kerberos_pac_save, ++ NET_TRANSPORT_ADS, ++ N_("Save Kerberos PAC"), ++ N_("net ads kerberos pac save\n" ++ " Save a Kerberos PAC in a file") ++ }, + + {NULL, NULL, 0, NULL, NULL} + }; +-- +1.8.5.3 + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/04-ipv6-workaround.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/04-ipv6-workaround.patch new file mode 100644 index 00000000..a2058f11 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/04-ipv6-workaround.patch @@ -0,0 +1,211 @@ +From 942dedb71437cd89932a7f39ca73d65c09aa59be Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 2 Apr 2014 19:37:34 +0200 +Subject: [PATCH] s3-kerberos: make ipv6 support for generated krb5 config + files more robust. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Older MIT Kerberos libraries will add any secondary ipv6 address as +ipv4 address, defining the (default) krb5 port 88 circumvents that. + +Guenther + +Signed-off-by: Günther Deschner +--- + source3/libads/kerberos.c | 29 +++++++++++++++++++++++++++-- + 1 file changed, 27 insertions(+), 2 deletions(-) + +diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c +index 649e568..f3c23ea 100644 +--- a/source3/libads/kerberos.c ++++ b/source3/libads/kerberos.c +@@ -615,6 +615,31 @@ static void add_sockaddr_unique(struct sockaddr_storage *addrs, int *num_addrs, + *num_addrs += 1; + } + ++/* print_canonical_sockaddr prints an ipv6 addr in the form of ++* [ipv6.addr]. This string, when put in a generated krb5.conf file is not ++* always properly dealt with by some older krb5 libraries. Adding the hard-coded ++* portnumber workarounds the issue. - gd */ ++ ++static char *print_canonical_sockaddr_with_port(TALLOC_CTX *mem_ctx, ++ const struct sockaddr_storage *pss) ++{ ++ char *str = NULL; ++ ++ str = print_canonical_sockaddr(mem_ctx, pss); ++ if (str == NULL) { ++ return NULL; ++ } ++ ++ if (pss->ss_family != AF_INET6) { ++ return str; ++ } ++ ++#if defined(HAVE_IPV6) ++ str = talloc_asprintf_append(str, ":88"); ++#endif ++ return str; ++} ++ + static char *get_kdc_ip_string(char *mem_ctx, + const char *realm, + const char *sitename, +@@ -634,7 +659,7 @@ static char *get_kdc_ip_string(char *mem_ctx, + struct netlogon_samlogon_response **responses = NULL; + NTSTATUS status; + char *kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n", "", +- print_canonical_sockaddr(mem_ctx, pss)); ++ print_canonical_sockaddr_with_port(mem_ctx, pss)); + + if (kdc_str == NULL) { + TALLOC_FREE(frame); +@@ -726,7 +751,7 @@ static char *get_kdc_ip_string(char *mem_ctx, + /* Append to the string - inefficient but not done often. */ + new_kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n", + kdc_str, +- print_canonical_sockaddr(mem_ctx, &dc_addrs[i])); ++ print_canonical_sockaddr_with_port(mem_ctx, &dc_addrs[i])); + if (new_kdc_str == NULL) { + goto fail; + } +-- +1.9.0 + +From 60db71015f84dd242be889576d85ccd5c6a1f73b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 16 Apr 2014 16:07:14 +0200 +Subject: [PATCH] s3-libads: allow ads_try_connect() to re-use a resolved ip + address. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Pass down a struct sockaddr_storage to ads_try_connect. + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider + +Autobuild-User(master): Günther Deschner +Autobuild-Date(master): Thu Apr 17 19:56:16 CEST 2014 on sn-devel-104 +--- + source3/libads/ldap.c | 44 ++++++++++++++++++++++++++------------------ + 1 file changed, 26 insertions(+), 18 deletions(-) + +diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c +index d9bb8e2..8fed8fd 100644 +--- a/source3/libads/ldap.c ++++ b/source3/libads/ldap.c +@@ -228,33 +228,27 @@ bool ads_closest_dc(ADS_STRUCT *ads) + try a connection to a given ldap server, returning True and setting the servers IP + in the ads struct if successful + */ +-static bool ads_try_connect(ADS_STRUCT *ads, const char *server, bool gc) ++static bool ads_try_connect(ADS_STRUCT *ads, bool gc, ++ struct sockaddr_storage *ss) + { + struct NETLOGON_SAM_LOGON_RESPONSE_EX cldap_reply; + TALLOC_CTX *frame = talloc_stackframe(); + bool ret = false; +- struct sockaddr_storage ss; + char addr[INET6_ADDRSTRLEN]; + +- if (!server || !*server) { ++ if (ss == NULL) { + TALLOC_FREE(frame); + return False; + } + +- if (!resolve_name(server, &ss, 0x20, true)) { +- DEBUG(5,("ads_try_connect: unable to resolve name %s\n", +- server )); +- TALLOC_FREE(frame); +- return false; +- } +- print_sockaddr(addr, sizeof(addr), &ss); ++ print_sockaddr(addr, sizeof(addr), ss); + + DEBUG(5,("ads_try_connect: sending CLDAP request to %s (realm: %s)\n", + addr, ads->server.realm)); + + ZERO_STRUCT( cldap_reply ); + +- if ( !ads_cldap_netlogon_5(frame, &ss, ads->server.realm, &cldap_reply ) ) { ++ if ( !ads_cldap_netlogon_5(frame, ss, ads->server.realm, &cldap_reply ) ) { + DEBUG(3,("ads_try_connect: CLDAP request %s failed.\n", addr)); + ret = false; + goto out; +@@ -298,7 +292,7 @@ static bool ads_try_connect(ADS_STRUCT *ads, const char *server, bool gc) + ads->server.workgroup = SMB_STRDUP(cldap_reply.domain_name); + + ads->ldap.port = gc ? LDAP_GC_PORT : LDAP_PORT; +- ads->ldap.ss = ss; ++ ads->ldap.ss = *ss; + + /* Store our site name. */ + sitename_store( cldap_reply.domain_name, cldap_reply.client_site); +@@ -330,6 +324,7 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads) + bool use_own_domain = False; + char *sitename; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; ++ bool ok = false; + + /* if the realm and workgroup are both empty, assume they are ours */ + +@@ -384,12 +379,14 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads) + DEBUG(6,("ads_find_dc: (ldap) looking for %s '%s'\n", + (got_realm ? "realm" : "domain"), realm)); + +- if (get_dc_name(domain, realm, srv_name, &ip_out)) { ++ ok = get_dc_name(domain, realm, srv_name, &ip_out); ++ if (ok) { + /* + * we call ads_try_connect() to fill in the + * ads->config details + */ +- if (ads_try_connect(ads, srv_name, false)) { ++ ok = ads_try_connect(ads, false, &ip_out); ++ if (ok) { + return NT_STATUS_OK; + } + } +@@ -445,7 +442,8 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads) + } + } + +- if ( ads_try_connect(ads, server, false) ) { ++ ok = ads_try_connect(ads, false, &ip_list[i].ss); ++ if (ok) { + SAFE_FREE(ip_list); + SAFE_FREE(sitename); + return NT_STATUS_OK; +@@ -630,9 +628,19 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads) + TALLOC_FREE(s); + } + +- if (ads->server.ldap_server) +- { +- if (ads_try_connect(ads, ads->server.ldap_server, ads->server.gc)) { ++ if (ads->server.ldap_server) { ++ bool ok = false; ++ struct sockaddr_storage ss; ++ ++ ok = resolve_name(ads->server.ldap_server, &ss, 0x20, true); ++ if (!ok) { ++ DEBUG(5,("ads_connect: unable to resolve name %s\n", ++ ads->server.ldap_server)); ++ status = ADS_ERROR_NT(NT_STATUS_NOT_FOUND); ++ goto out; ++ } ++ ok = ads_try_connect(ads, ads->server.gc, &ss); ++ if (ok) { + goto got_connection; + } + +-- +1.9.0 + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/05-fix-gecos-field-with-samlogon.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/05-fix-gecos-field-with-samlogon.patch new file mode 100644 index 00000000..c1dfc06e --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/05-fix-gecos-field-with-samlogon.patch @@ -0,0 +1,29894 @@ +From 538f62edb2cc4c17204620d8a9b3075c7453422b Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Thu, 4 Sep 2014 12:55:53 +0200 +Subject: [PATCH 002/249] selftest: Fix selftest where pid is used + uninitialized. + +On my system this gets evaluated to 0 so in the end we detect samba to +be running cause $childpid is set to 0. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=10793 + +Signed-off-by: Andreas Schneider +Reviewed-by: Stefan Metzmacher + +Autobuild-User(master): Andreas Schneider +Autobuild-Date(master): Thu Sep 4 17:09:17 CEST 2014 on sn-devel-104 + +(cherry picked from commit 6d2f56dbaf84203b351f33179cc3feaf557e0683) +Signed-off-by: Andreas Schneider + +Autobuild-User(v4-1-test): Karolin Seeger +Autobuild-Date(v4-1-test): Mon Sep 8 23:19:29 CEST 2014 on sn-devel-104 +--- + selftest/target/Samba.pm | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm +index ab3851f..b0817fd 100644 +--- a/selftest/target/Samba.pm ++++ b/selftest/target/Samba.pm +@@ -188,7 +188,12 @@ sub get_interface($) + sub cleanup_child($$) + { + my ($pid, $name) = @_; +- my $childpid = waitpid($pid, WNOHANG); ++ my $childpid = -1; ++ ++ if (defined($pid)) { ++ $childpid = waitpid($pid, WNOHANG); ++ } ++ + if ($childpid == 0) { + } elsif ($childpid < 0) { + printf STDERR "%s child process %d isn't here any more\n", +-- +1.9.3 + + +From a14c0878c232dcf674008444f80dc0e5d8aada09 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 31 Jul 2013 12:33:25 +0200 +Subject: [PATCH 003/249] auth/credentials: remove pointless talloc_reference() + from cli_credentials_get_unparsed_name() + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 953502925863377b5e566edff4ac68c63e8d151f) +--- + auth/credentials/credentials.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c +index e636123..e597809 100644 +--- a/auth/credentials/credentials.c ++++ b/auth/credentials/credentials.c +@@ -669,7 +669,7 @@ _PUBLIC_ const char *cli_credentials_get_unparsed_name(struct cli_credentials *c + const char *name; + + if (bind_dn) { +- name = talloc_reference(mem_ctx, bind_dn); ++ name = talloc_strdup(mem_ctx, bind_dn); + } else { + cli_credentials_get_ntlm_username_domain(credentials, mem_ctx, &username, &domain); + if (domain && domain[0]) { +-- +1.9.3 + + +From a9bbf2e55d56b9d2cec944ee32a127fc72e6ce6a Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 31 Jul 2013 12:33:25 +0200 +Subject: [PATCH 004/249] auth/credentials: remove pointless talloc_reference() + from cli_credentials_get_principal_and_obtained() + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit b8f09226458dc13cf901f481ede89d8a6bb94ba7) +--- + auth/credentials/credentials.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c +index e597809..7a4b081 100644 +--- a/auth/credentials/credentials.c ++++ b/auth/credentials/credentials.c +@@ -267,7 +267,7 @@ _PUBLIC_ const char *cli_credentials_get_principal_and_obtained(struct cli_crede + } + } + *obtained = cred->principal_obtained; +- return talloc_reference(mem_ctx, cred->principal); ++ return talloc_strdup(mem_ctx, cred->principal); + } + + /** +-- +1.9.3 + + +From 5df785eba8389be9129984c6c5a1e59487685938 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 31 Jul 2013 12:52:17 +0200 +Subject: [PATCH 005/249] auth/credentials: add + cli_credentials_[set_]callback_data* + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 6ff6778bdc60f1cd4d52cba83bd47d3398fe5a20) +--- + auth/credentials/credentials.c | 11 +++++++++++ + auth/credentials/credentials.h | 8 ++++++++ + 2 files changed, 19 insertions(+) + +diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c +index 7a4b081..e6a4710 100644 +--- a/auth/credentials/credentials.c ++++ b/auth/credentials/credentials.c +@@ -114,6 +114,17 @@ _PUBLIC_ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) + return cred; + } + ++_PUBLIC_ void cli_credentials_set_callback_data(struct cli_credentials *cred, ++ void *callback_data) ++{ ++ cred->priv_data = callback_data; ++} ++ ++_PUBLIC_ void *_cli_credentials_callback_data(struct cli_credentials *cred) ++{ ++ return cred->priv_data; ++} ++ + /** + * Create a new anonymous credential + * @param mem_ctx TALLOC_CTX parent for credentials structure +diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h +index dbc014f..0f498ad 100644 +--- a/auth/credentials/credentials.h ++++ b/auth/credentials/credentials.h +@@ -332,6 +332,14 @@ bool cli_credentials_set_realm_callback(struct cli_credentials *cred, + bool cli_credentials_set_workstation_callback(struct cli_credentials *cred, + const char *(*workstation_cb) (struct cli_credentials *)); + ++void cli_credentials_set_callback_data(struct cli_credentials *cred, ++ void *callback_data); ++void *_cli_credentials_callback_data(struct cli_credentials *cred); ++#define cli_credentials_callback_data(_cred, _type) \ ++ talloc_get_type_abort(_cli_credentials_callback_data(_cred), _type) ++#define cli_credentials_callback_data_void(_cred) \ ++ _cli_credentials_callback_data(_cred) ++ + /** + * Return attached NETLOGON credentials + */ +-- +1.9.3 + + +From 8fd0244ac8fe4998a0931bc9d51b9dfbb182a2e1 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 31 Jul 2013 13:21:14 +0200 +Subject: [PATCH 006/249] auth/credentials: add cli_credentials_shallow_copy() + +This is useful for testing. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit b3cd44d50cff99fa77611679d68d2d57434fefa4) +--- + auth/credentials/credentials.c | 15 +++++++++++++++ + auth/credentials/credentials.h | 3 +++ + 2 files changed, 18 insertions(+) + +diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c +index e6a4710..c1c6993 100644 +--- a/auth/credentials/credentials.c ++++ b/auth/credentials/credentials.c +@@ -125,6 +125,21 @@ _PUBLIC_ void *_cli_credentials_callback_data(struct cli_credentials *cred) + return cred->priv_data; + } + ++_PUBLIC_ struct cli_credentials *cli_credentials_shallow_copy(TALLOC_CTX *mem_ctx, ++ struct cli_credentials *src) ++{ ++ struct cli_credentials *dst; ++ ++ dst = talloc(mem_ctx, struct cli_credentials); ++ if (dst == NULL) { ++ return NULL; ++ } ++ ++ *dst = *src; ++ ++ return dst; ++} ++ + /** + * Create a new anonymous credential + * @param mem_ctx TALLOC_CTX parent for credentials structure +diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h +index 0f498ad..1377bfa 100644 +--- a/auth/credentials/credentials.h ++++ b/auth/credentials/credentials.h +@@ -340,6 +340,9 @@ void *_cli_credentials_callback_data(struct cli_credentials *cred); + #define cli_credentials_callback_data_void(_cred) \ + _cli_credentials_callback_data(_cred) + ++struct cli_credentials *cli_credentials_shallow_copy(TALLOC_CTX *mem_ctx, ++ struct cli_credentials *src); ++ + /** + * Return attached NETLOGON credentials + */ +-- +1.9.3 + + +From 52e4028da5db90ce3ee410997ea3464374fec46b Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 31 Jul 2013 13:20:13 +0200 +Subject: [PATCH 007/249] s3:ntlm_auth: remove pointless credentials->priv_data + = NULL; + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit cfeeb3ce3de5d1df07299fb83327ae258da0bf8d) +--- + source3/utils/ntlm_auth.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c +index b3bbaa4..a5e0cd2 100644 +--- a/source3/utils/ntlm_auth.c ++++ b/source3/utils/ntlm_auth.c +@@ -228,7 +228,6 @@ static const char *get_password(struct cli_credentials *credentials) + + /* Ask for a password */ + x_fprintf(x_stdout, "PW\n"); +- credentials->priv_data = NULL; + + manage_squid_request(NUM_HELPER_MODES /* bogus */, NULL, NULL, manage_gensec_get_pw_request, (void **)&password); + talloc_steal(credentials, password); +-- +1.9.3 + + +From bdfb13b91ce8961caeb98b01a75893895e8d484a Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 31 Jul 2013 13:22:10 +0200 +Subject: [PATCH 008/249] s4:torture/shell: simplify + cli_credentials_set_password() call + +All we want is to avoid a possible callback... + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 36b3c9506c1ac5549a38140e7ffd57644290069f) +--- + source4/torture/shell.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/source4/torture/shell.c b/source4/torture/shell.c +index d6cc94c..aa85da3 100644 +--- a/source4/torture/shell.c ++++ b/source4/torture/shell.c +@@ -110,10 +110,7 @@ void torture_shell(struct torture_context *tctx) + * stops the credentials system prompting when we use the "auth" + * command to display the current auth parameters. + */ +- if (cmdline_credentials->password_obtained != CRED_SPECIFIED) { +- cli_credentials_set_password(cmdline_credentials, "", +- CRED_SPECIFIED); +- } ++ cli_credentials_set_password(cmdline_credentials, "", CRED_GUESS_ENV); + + while (1) { + cline = smb_readline("torture> ", NULL, NULL); +-- +1.9.3 + + +From 91c0d6a26823f3057357c6b31bf1f686e5ed0f5e Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 31 Jul 2013 13:23:08 +0200 +Subject: [PATCH 009/249] s4:torture/gentest: make use of + cli_credentials_get_username() + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit d36fcaa5f3c4d1ad54d767f4a7c5fa6c8d69c00e) +--- + source4/torture/gentest.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c +index 91b60e2..586a25b 100644 +--- a/source4/torture/gentest.c ++++ b/source4/torture/gentest.c +@@ -221,7 +221,8 @@ static bool connect_servers(struct tevent_context *ev, + + printf("Connecting to \\\\%s\\%s as %s - instance %d\n", + servers[i].server_name, servers[i].share_name, +- servers[i].credentials->username, j); ++ cli_credentials_get_username(servers[i].credentials), ++ j); + + cli_credentials_set_workstation(servers[i].credentials, + "gentest", CRED_SPECIFIED); +-- +1.9.3 + + +From 9687534ac54b732f73c3f4758055a278eaa0cbb2 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 31 Jul 2013 13:23:41 +0200 +Subject: [PATCH 010/249] s4:torture/rpc: make use of + cli_credentials_set_netlogon_creds() + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit d47bf469b8a9064f4f7033918b1fe519adfa0c26) +--- + source4/torture/rpc/schannel.c | 36 ++++++++++++++++-------------------- + 1 file changed, 16 insertions(+), 20 deletions(-) + +diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c +index e0862d2..8203749 100644 +--- a/source4/torture/rpc/schannel.c ++++ b/source4/torture/rpc/schannel.c +@@ -604,9 +604,9 @@ bool torture_rpc_schannel2(struct torture_context *torture) + torture_assert(torture, join_ctx != NULL, + "Failed to join domain with acct_flags=ACB_WSTRUST"); + +- credentials2 = (struct cli_credentials *)talloc_memdup(torture, credentials1, sizeof(*credentials1)); +- credentials1->netlogon_creds = NULL; +- credentials2->netlogon_creds = NULL; ++ credentials2 = cli_credentials_shallow_copy(torture, credentials1); ++ cli_credentials_set_netlogon_creds(credentials1, NULL); ++ cli_credentials_set_netlogon_creds(credentials2, NULL); + + status = dcerpc_parse_binding(torture, binding, &b); + torture_assert_ntstatus_ok(torture, status, "Bad binding string"); +@@ -624,8 +624,8 @@ bool torture_rpc_schannel2(struct torture_context *torture) + credentials2, torture->ev, torture->lp_ctx); + torture_assert_ntstatus_ok(torture, status, "Failed to connect with schannel"); + +- credentials1->netlogon_creds = NULL; +- credentials2->netlogon_creds = NULL; ++ cli_credentials_set_netlogon_creds(credentials1, NULL); ++ cli_credentials_set_netlogon_creds(credentials2, NULL); + + torture_comment(torture, "Testing logon on pipe1\n"); + if (!test_netlogon_ex_ops(p1, torture, credentials1, NULL)) +@@ -827,16 +827,12 @@ bool torture_rpc_schannel_bench1(struct torture_context *torture) + s->nprocs = torture_setting_int(torture, "nprocs", 4); + s->conns = talloc_zero_array(s, struct torture_schannel_bench_conn, s->nprocs); + +- s->user1_creds = (struct cli_credentials *)talloc_memdup(s, +- cmdline_credentials, +- sizeof(*s->user1_creds)); ++ s->user1_creds = cli_credentials_shallow_copy(s, cmdline_credentials); + tmp = torture_setting_string(s->tctx, "extra_user1", NULL); + if (tmp) { + cli_credentials_parse_string(s->user1_creds, tmp, CRED_SPECIFIED); + } +- s->user2_creds = (struct cli_credentials *)talloc_memdup(s, +- cmdline_credentials, +- sizeof(*s->user1_creds)); ++ s->user2_creds = cli_credentials_shallow_copy(s, cmdline_credentials); + tmp = torture_setting_string(s->tctx, "extra_user2", NULL); + if (tmp) { + cli_credentials_parse_string(s->user1_creds, tmp, CRED_SPECIFIED); +@@ -855,15 +851,16 @@ bool torture_rpc_schannel_bench1(struct torture_context *torture) + cli_credentials_set_kerberos_state(s->wks_creds2, CRED_DONT_USE_KERBEROS); + + for (i=0; i < s->nprocs; i++) { +- s->conns[i].s = s; +- s->conns[i].index = i; +- s->conns[i].wks_creds = (struct cli_credentials *)talloc_memdup( +- s->conns, s->wks_creds1,sizeof(*s->wks_creds1)); ++ struct cli_credentials *wks = s->wks_creds1; ++ + if ((i % 2) && (torture_setting_bool(torture, "multijoin", false))) { +- memcpy(s->conns[i].wks_creds, s->wks_creds2, +- talloc_get_size(s->conns[i].wks_creds)); ++ wks = s->wks_creds2; + } +- s->conns[i].wks_creds->netlogon_creds = NULL; ++ ++ s->conns[i].s = s; ++ s->conns[i].index = i; ++ s->conns[i].wks_creds = cli_credentials_shallow_copy(s->conns, wks); ++ cli_credentials_set_netlogon_creds(s->conns[i].wks_creds, NULL); + } + + status = dcerpc_parse_binding(s, binding, &s->b); +@@ -962,8 +959,7 @@ bool torture_rpc_schannel_bench1(struct torture_context *torture) + + /* Just as a test, connect with the new creds */ + +- talloc_free(s->wks_creds1->netlogon_creds); +- s->wks_creds1->netlogon_creds = NULL; ++ cli_credentials_set_netlogon_creds(s->wks_creds1, NULL); + + status = dcerpc_pipe_connect_b(s, &net_pipe, s->b, + &ndr_table_netlogon, +-- +1.9.3 + + +From de6c67e98d94d003f36fef5472b8133c578b3c01 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 31 Jul 2013 13:24:21 +0200 +Subject: [PATCH 011/249] s4:ntlm_auth: make use of + cli_credentials_[set_]callback_data* + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit bbd63dd8a17468d3e332969a30c06e2b2f1540fc) +--- + source4/utils/ntlm_auth.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/source4/utils/ntlm_auth.c b/source4/utils/ntlm_auth.c +index c363c9d..136e238 100644 +--- a/source4/utils/ntlm_auth.c ++++ b/source4/utils/ntlm_auth.c +@@ -299,10 +299,11 @@ static void manage_gensec_get_pw_request(enum stdio_helper_mode stdio_helper_mod + static const char *get_password(struct cli_credentials *credentials) + { + char *password = NULL; +- ++ void *cb = cli_credentials_callback_data_void(credentials); ++ + /* Ask for a password */ +- mux_printf((unsigned int)(uintptr_t)credentials->priv_data, "PW\n"); +- credentials->priv_data = NULL; ++ mux_printf((unsigned int)(uintptr_t)cb, "PW\n"); ++ cli_credentials_set_callback_data(credentials, NULL); + + manage_squid_request(cmdline_lp_ctx, NUM_HELPER_MODES /* bogus */, manage_gensec_get_pw_request, (void **)&password); + return password; +@@ -505,8 +506,9 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, + if (state->set_password) { + cli_credentials_set_password(creds, state->set_password, CRED_SPECIFIED); + } else { ++ void *cb = (void*)(uintptr_t)mux_id; ++ cli_credentials_set_callback_data(creds, cb); + cli_credentials_set_password_callback(creds, get_password); +- creds->priv_data = (void*)(uintptr_t)mux_id; + } + if (opt_workstation) { + cli_credentials_set_workstation(creds, opt_workstation, CRED_SPECIFIED); +-- +1.9.3 + + +From 80c611a2b424e4e4a7e6de7ed6b9368bff0d9afb Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 31 Jul 2013 12:41:40 +0200 +Subject: [PATCH 012/249] auth/credentials: keep cli_credentials private + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 9325bd9cb6bb942ea989f4e32799c76ea8af3d3e) +--- + auth/credentials/credentials.c | 1 + + auth/credentials/credentials.h | 101 +++------------------------- + auth/credentials/credentials_internal.h | 114 ++++++++++++++++++++++++++++++++ + auth/credentials/credentials_krb5.c | 1 + + auth/credentials/credentials_ntlm.c | 1 + + auth/credentials/credentials_secrets.c | 1 + + 6 files changed, 126 insertions(+), 93 deletions(-) + create mode 100644 auth/credentials/credentials_internal.h + +diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c +index c1c6993..f334465 100644 +--- a/auth/credentials/credentials.c ++++ b/auth/credentials/credentials.c +@@ -24,6 +24,7 @@ + #include "includes.h" + #include "librpc/gen_ndr/samr.h" /* for struct samrPassword */ + #include "auth/credentials/credentials.h" ++#include "auth/credentials/credentials_internal.h" + #include "libcli/auth/libcli_auth.h" + #include "tevent.h" + #include "param/param.h" +diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h +index 1377bfa..cb09dc3 100644 +--- a/auth/credentials/credentials.h ++++ b/auth/credentials/credentials.h +@@ -25,9 +25,17 @@ + #include "../lib/util/data_blob.h" + #include "librpc/gen_ndr/misc.h" + ++struct cli_credentials; + struct ccache_container; + struct tevent_context; + struct netlogon_creds_CredentialState; ++struct ldb_context; ++struct ldb_message; ++struct loadparm_context; ++struct ccache_container; ++struct gssapi_creds_container; ++struct smb_krb5_context; ++struct keytab_container; + + /* In order of priority */ + enum credentials_obtained { +@@ -57,99 +65,6 @@ enum credentials_krb_forwardable { + #define CLI_CRED_NTLM_AUTH 0x08 + #define CLI_CRED_CLEAR_AUTH 0x10 /* TODO: Push cleartext auth with this flag */ + +-struct cli_credentials { +- enum credentials_obtained workstation_obtained; +- enum credentials_obtained username_obtained; +- enum credentials_obtained password_obtained; +- enum credentials_obtained domain_obtained; +- enum credentials_obtained realm_obtained; +- enum credentials_obtained ccache_obtained; +- enum credentials_obtained client_gss_creds_obtained; +- enum credentials_obtained principal_obtained; +- enum credentials_obtained keytab_obtained; +- enum credentials_obtained server_gss_creds_obtained; +- +- /* Threshold values (essentially a MAX() over a number of the +- * above) for the ccache and GSS credentials, to ensure we +- * regenerate/pick correctly */ +- +- enum credentials_obtained ccache_threshold; +- enum credentials_obtained client_gss_creds_threshold; +- +- const char *workstation; +- const char *username; +- const char *password; +- const char *old_password; +- const char *domain; +- const char *realm; +- const char *principal; +- char *salt_principal; +- char *impersonate_principal; +- char *self_service; +- char *target_service; +- +- const char *bind_dn; +- +- /* Allows authentication from a keytab or similar */ +- struct samr_Password *nt_hash; +- +- /* Allows NTLM pass-though authentication */ +- DATA_BLOB lm_response; +- DATA_BLOB nt_response; +- +- struct ccache_container *ccache; +- struct gssapi_creds_container *client_gss_creds; +- struct keytab_container *keytab; +- struct gssapi_creds_container *server_gss_creds; +- +- const char *(*workstation_cb) (struct cli_credentials *); +- const char *(*password_cb) (struct cli_credentials *); +- const char *(*username_cb) (struct cli_credentials *); +- const char *(*domain_cb) (struct cli_credentials *); +- const char *(*realm_cb) (struct cli_credentials *); +- const char *(*principal_cb) (struct cli_credentials *); +- +- /* Private handle for the callback routines to use */ +- void *priv_data; +- +- struct netlogon_creds_CredentialState *netlogon_creds; +- enum netr_SchannelType secure_channel_type; +- int kvno; +- time_t password_last_changed_time; +- +- struct smb_krb5_context *smb_krb5_context; +- +- /* We are flagged to get machine account details from the +- * secrets.ldb when we are asked for a username or password */ +- bool machine_account_pending; +- struct loadparm_context *machine_account_pending_lp_ctx; +- +- /* Is this a machine account? */ +- bool machine_account; +- +- /* Should we be trying to use kerberos? */ +- enum credentials_use_kerberos use_kerberos; +- +- /* Should we get a forwardable ticket? */ +- enum credentials_krb_forwardable krb_forwardable; +- +- /* gensec features which should be used for connections */ +- uint32_t gensec_features; +- +- /* Number of retries left before bailing out */ +- int tries; +- +- /* Whether any callback is currently running */ +- bool callback_running; +-}; +- +-struct ldb_context; +-struct ldb_message; +-struct loadparm_context; +-struct ccache_container; +- +-struct gssapi_creds_container; +- + const char *cli_credentials_get_workstation(struct cli_credentials *cred); + bool cli_credentials_set_workstation(struct cli_credentials *cred, + const char *val, +diff --git a/auth/credentials/credentials_internal.h b/auth/credentials/credentials_internal.h +new file mode 100644 +index 0000000..5a3655b +--- /dev/null ++++ b/auth/credentials/credentials_internal.h +@@ -0,0 +1,114 @@ ++/* ++ samba -- Unix SMB/CIFS implementation. ++ ++ Client credentials structure ++ ++ Copyright (C) Jelmer Vernooij 2004-2006 ++ Copyright (C) Andrew Bartlett 2005 ++ ++ 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 . ++*/ ++#ifndef __CREDENTIALS_INTERNAL_H__ ++#define __CREDENTIALS_INTERNAL_H__ ++ ++#include "../lib/util/data_blob.h" ++#include "librpc/gen_ndr/misc.h" ++ ++struct cli_credentials { ++ enum credentials_obtained workstation_obtained; ++ enum credentials_obtained username_obtained; ++ enum credentials_obtained password_obtained; ++ enum credentials_obtained domain_obtained; ++ enum credentials_obtained realm_obtained; ++ enum credentials_obtained ccache_obtained; ++ enum credentials_obtained client_gss_creds_obtained; ++ enum credentials_obtained principal_obtained; ++ enum credentials_obtained keytab_obtained; ++ enum credentials_obtained server_gss_creds_obtained; ++ ++ /* Threshold values (essentially a MAX() over a number of the ++ * above) for the ccache and GSS credentials, to ensure we ++ * regenerate/pick correctly */ ++ ++ enum credentials_obtained ccache_threshold; ++ enum credentials_obtained client_gss_creds_threshold; ++ ++ const char *workstation; ++ const char *username; ++ const char *password; ++ const char *old_password; ++ const char *domain; ++ const char *realm; ++ const char *principal; ++ char *salt_principal; ++ char *impersonate_principal; ++ char *self_service; ++ char *target_service; ++ ++ const char *bind_dn; ++ ++ /* Allows authentication from a keytab or similar */ ++ struct samr_Password *nt_hash; ++ ++ /* Allows NTLM pass-though authentication */ ++ DATA_BLOB lm_response; ++ DATA_BLOB nt_response; ++ ++ struct ccache_container *ccache; ++ struct gssapi_creds_container *client_gss_creds; ++ struct keytab_container *keytab; ++ struct gssapi_creds_container *server_gss_creds; ++ ++ const char *(*workstation_cb) (struct cli_credentials *); ++ const char *(*password_cb) (struct cli_credentials *); ++ const char *(*username_cb) (struct cli_credentials *); ++ const char *(*domain_cb) (struct cli_credentials *); ++ const char *(*realm_cb) (struct cli_credentials *); ++ const char *(*principal_cb) (struct cli_credentials *); ++ ++ /* Private handle for the callback routines to use */ ++ void *priv_data; ++ ++ struct netlogon_creds_CredentialState *netlogon_creds; ++ enum netr_SchannelType secure_channel_type; ++ int kvno; ++ time_t password_last_changed_time; ++ ++ struct smb_krb5_context *smb_krb5_context; ++ ++ /* We are flagged to get machine account details from the ++ * secrets.ldb when we are asked for a username or password */ ++ bool machine_account_pending; ++ struct loadparm_context *machine_account_pending_lp_ctx; ++ ++ /* Is this a machine account? */ ++ bool machine_account; ++ ++ /* Should we be trying to use kerberos? */ ++ enum credentials_use_kerberos use_kerberos; ++ ++ /* Should we get a forwardable ticket? */ ++ enum credentials_krb_forwardable krb_forwardable; ++ ++ /* gensec features which should be used for connections */ ++ uint32_t gensec_features; ++ ++ /* Number of retries left before bailing out */ ++ int tries; ++ ++ /* Whether any callback is currently running */ ++ bool callback_running; ++}; ++ ++#endif /* __CREDENTIALS_INTERNAL_H__ */ +diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c +index ec6a695..489a959 100644 +--- a/auth/credentials/credentials_krb5.c ++++ b/auth/credentials/credentials_krb5.c +@@ -26,6 +26,7 @@ + #include "system/gssapi.h" + #include "auth/kerberos/kerberos.h" + #include "auth/credentials/credentials.h" ++#include "auth/credentials/credentials_internal.h" + #include "auth/credentials/credentials_proto.h" + #include "auth/credentials/credentials_krb5.h" + #include "auth/kerberos/kerberos_credentials.h" +diff --git a/auth/credentials/credentials_ntlm.c b/auth/credentials/credentials_ntlm.c +index 8f143bf..8c6be39 100644 +--- a/auth/credentials/credentials_ntlm.c ++++ b/auth/credentials/credentials_ntlm.c +@@ -26,6 +26,7 @@ + #include "../lib/crypto/crypto.h" + #include "libcli/auth/libcli_auth.h" + #include "auth/credentials/credentials.h" ++#include "auth/credentials/credentials_internal.h" + + _PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, + int *flags, +diff --git a/auth/credentials/credentials_secrets.c b/auth/credentials/credentials_secrets.c +index 27ee607..678d167 100644 +--- a/auth/credentials/credentials_secrets.c ++++ b/auth/credentials/credentials_secrets.c +@@ -28,6 +28,7 @@ + #include "param/secrets.h" + #include "system/filesys.h" + #include "auth/credentials/credentials.h" ++#include "auth/credentials/credentials_internal.h" + #include "auth/credentials/credentials_proto.h" + #include "auth/credentials/credentials_krb5.h" + #include "auth/kerberos/kerberos_util.h" +-- +1.9.3 + + +From 96ea01159cfee1e384dbd5966c7eb512d495e322 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 31 Jul 2013 13:39:17 +0200 +Subject: [PATCH 013/249] auth/credentials: get the old password from + secrets.tdb + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 26a7420c1c4307023b22676cd85d95010ecbf603) +--- + auth/credentials/credentials_secrets.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/auth/credentials/credentials_secrets.c b/auth/credentials/credentials_secrets.c +index 678d167..6c1cded 100644 +--- a/auth/credentials/credentials_secrets.c ++++ b/auth/credentials/credentials_secrets.c +@@ -238,6 +238,7 @@ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cr + bool secrets_tdb_password_more_recent; + time_t secrets_tdb_lct = 0; + char *secrets_tdb_password = NULL; ++ char *secrets_tdb_old_password = NULL; + char *keystr; + char *keystr_upper = NULL; + char *secrets_tdb; +@@ -285,6 +286,15 @@ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cr + if (NT_STATUS_IS_OK(status)) { + secrets_tdb_password = (char *)dbuf.dptr; + } ++ keystr = talloc_asprintf(tmp_ctx, "%s/%s", ++ SECRETS_MACHINE_PASSWORD_PREV, ++ domain); ++ keystr_upper = strupper_talloc(tmp_ctx, keystr); ++ status = dbwrap_fetch(db_ctx, tmp_ctx, string_tdb_data(keystr_upper), ++ &dbuf); ++ if (NT_STATUS_IS_OK(status)) { ++ secrets_tdb_old_password = (char *)dbuf.dptr; ++ } + } + + filter = talloc_asprintf(cred, SECRETS_PRIMARY_DOMAIN_FILTER, +@@ -308,6 +318,7 @@ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cr + if (secrets_tdb_password_more_recent) { + char *machine_account = talloc_asprintf(tmp_ctx, "%s$", lpcfg_netbios_name(lp_ctx)); + cli_credentials_set_password(cred, secrets_tdb_password, CRED_SPECIFIED); ++ cli_credentials_set_old_password(cred, secrets_tdb_old_password, CRED_SPECIFIED); + cli_credentials_set_domain(cred, domain, CRED_SPECIFIED); + cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED); + } else if (!NT_STATUS_IS_OK(status)) { +-- +1.9.3 + + +From 74f5c14921f53b95b64dbcbf0352a89d50b20af1 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 31 Jul 2013 14:25:54 +0200 +Subject: [PATCH 014/249] auth/credentials: simplify password_tries state + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 8ea36a8e58d499aa7bf342b365ca00cb39f295b6) +--- + auth/credentials/credentials.c | 19 ++++++++++++++----- + auth/credentials/credentials_internal.h | 2 +- + 2 files changed, 15 insertions(+), 6 deletions(-) + +diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c +index f334465..4ac5356 100644 +--- a/auth/credentials/credentials.c ++++ b/auth/credentials/credentials.c +@@ -104,7 +104,7 @@ _PUBLIC_ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) + + cred->machine_account = false; + +- cred->tries = 3; ++ cred->password_tries = 0; + + cred->callback_running = false; + +@@ -397,6 +397,7 @@ _PUBLIC_ bool cli_credentials_set_password(struct cli_credentials *cred, + enum credentials_obtained obtained) + { + if (obtained >= cred->password_obtained) { ++ cred->password_tries = 0; + cred->password = talloc_strdup(cred, val); + if (cred->password) { + /* Don't print the actual password in talloc memory dumps */ +@@ -418,6 +419,7 @@ _PUBLIC_ bool cli_credentials_set_password_callback(struct cli_credentials *cred + const char *(*password_cb) (struct cli_credentials *)) + { + if (cred->password_obtained < CRED_CALLBACK) { ++ cred->password_tries = 3; + cred->password_cb = password_cb; + cred->password_obtained = CRED_CALLBACK; + cli_credentials_invalidate_ccache(cred, cred->password_obtained); +@@ -897,12 +899,19 @@ _PUBLIC_ bool cli_credentials_wrong_password(struct cli_credentials *cred) + if (cred->password_obtained != CRED_CALLBACK_RESULT) { + return false; + } +- +- cred->password_obtained = CRED_CALLBACK; + +- cred->tries--; ++ if (cred->password_tries == 0) { ++ return false; ++ } ++ ++ cred->password_tries--; + +- return (cred->tries > 0); ++ if (cred->password_tries == 0) { ++ return false; ++ } ++ ++ cred->password_obtained = CRED_CALLBACK; ++ return true; + } + + _PUBLIC_ void cli_credentials_get_ntlm_username_domain(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, +diff --git a/auth/credentials/credentials_internal.h b/auth/credentials/credentials_internal.h +index 5a3655b..f2f79b9 100644 +--- a/auth/credentials/credentials_internal.h ++++ b/auth/credentials/credentials_internal.h +@@ -105,7 +105,7 @@ struct cli_credentials { + uint32_t gensec_features; + + /* Number of retries left before bailing out */ +- int tries; ++ uint32_t password_tries; + + /* Whether any callback is currently running */ + bool callback_running; +-- +1.9.3 + + +From 8d2c51caeecebc0b7d16fb7cf7b7fe2f2b5d8edd Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 31 Jul 2013 14:32:36 +0200 +Subject: [PATCH 015/249] auth/credentials: use CRED_CALLBACK_RESULT after a + callback + +We only do this if it's still CRED_CALLBACK after the callback, +this allowes the callback to overwrite it. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett + +Autobuild-User(master): Andrew Bartlett +Autobuild-Date(master): Mon Aug 5 09:36:05 CEST 2013 on sn-devel-104 +(cherry picked from commit b699d404bb5d4385a757b5aa5d0e792cf9d5de59) +--- + auth/credentials/credentials.c | 34 +++++++++++++++++++++++----------- + 1 file changed, 23 insertions(+), 11 deletions(-) + +diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c +index 4ac5356..be497bc 100644 +--- a/auth/credentials/credentials.c ++++ b/auth/credentials/credentials.c +@@ -206,8 +206,10 @@ _PUBLIC_ const char *cli_credentials_get_username(struct cli_credentials *cred) + cred->callback_running = true; + cred->username = cred->username_cb(cred); + cred->callback_running = false; +- cred->username_obtained = CRED_SPECIFIED; +- cli_credentials_invalidate_ccache(cred, cred->username_obtained); ++ if (cred->username_obtained == CRED_CALLBACK) { ++ cred->username_obtained = CRED_CALLBACK_RESULT; ++ cli_credentials_invalidate_ccache(cred, cred->username_obtained); ++ } + } + + return cred->username; +@@ -275,8 +277,10 @@ _PUBLIC_ const char *cli_credentials_get_principal_and_obtained(struct cli_crede + cred->callback_running = true; + cred->principal = cred->principal_cb(cred); + cred->callback_running = false; +- cred->principal_obtained = CRED_SPECIFIED; +- cli_credentials_invalidate_ccache(cred, cred->principal_obtained); ++ if (cred->principal_obtained == CRED_CALLBACK) { ++ cred->principal_obtained = CRED_CALLBACK_RESULT; ++ cli_credentials_invalidate_ccache(cred, cred->principal_obtained); ++ } + } + + if (cred->principal_obtained < cred->username_obtained +@@ -382,8 +386,10 @@ _PUBLIC_ const char *cli_credentials_get_password(struct cli_credentials *cred) + cred->callback_running = true; + cred->password = cred->password_cb(cred); + cred->callback_running = false; +- cred->password_obtained = CRED_CALLBACK_RESULT; +- cli_credentials_invalidate_ccache(cred, cred->password_obtained); ++ if (cred->password_obtained == CRED_CALLBACK) { ++ cred->password_obtained = CRED_CALLBACK_RESULT; ++ cli_credentials_invalidate_ccache(cred, cred->password_obtained); ++ } + } + + return cred->password; +@@ -502,8 +508,10 @@ _PUBLIC_ const char *cli_credentials_get_domain(struct cli_credentials *cred) + cred->callback_running = true; + cred->domain = cred->domain_cb(cred); + cred->callback_running = false; +- cred->domain_obtained = CRED_SPECIFIED; +- cli_credentials_invalidate_ccache(cred, cred->domain_obtained); ++ if (cred->domain_obtained == CRED_CALLBACK) { ++ cred->domain_obtained = CRED_CALLBACK_RESULT; ++ cli_credentials_invalidate_ccache(cred, cred->domain_obtained); ++ } + } + + return cred->domain; +@@ -561,8 +569,10 @@ _PUBLIC_ const char *cli_credentials_get_realm(struct cli_credentials *cred) + cred->callback_running = true; + cred->realm = cred->realm_cb(cred); + cred->callback_running = false; +- cred->realm_obtained = CRED_SPECIFIED; +- cli_credentials_invalidate_ccache(cred, cred->realm_obtained); ++ if (cred->realm_obtained == CRED_CALLBACK) { ++ cred->realm_obtained = CRED_CALLBACK_RESULT; ++ cli_credentials_invalidate_ccache(cred, cred->realm_obtained); ++ } + } + + return cred->realm; +@@ -612,7 +622,9 @@ _PUBLIC_ const char *cli_credentials_get_workstation(struct cli_credentials *cre + cred->callback_running = true; + cred->workstation = cred->workstation_cb(cred); + cred->callback_running = false; +- cred->workstation_obtained = CRED_SPECIFIED; ++ if (cred->workstation_obtained == CRED_CALLBACK) { ++ cred->workstation_obtained = CRED_CALLBACK_RESULT; ++ } + } + + return cred->workstation; +-- +1.9.3 + + +From a498324b38326a874616b0bab1e5a9cd29b664ce Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 17 May 2013 16:02:59 +0200 +Subject: [PATCH 016/249] s3-net: pass down ndr_interface_table to + connect_dst_pipe(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 93e92faca9c99cd91878c2f48fb244233b16aa0f) +--- + source3/utils/net_proto.h | 2 +- + source3/utils/net_rpc.c | 4 ++-- + source3/utils/net_rpc_printer.c | 10 +++++----- + source3/utils/net_util.c | 4 ++-- + 4 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/source3/utils/net_proto.h b/source3/utils/net_proto.h +index 3f99e14..03fb312 100644 +--- a/source3/utils/net_proto.h ++++ b/source3/utils/net_proto.h +@@ -416,7 +416,7 @@ NTSTATUS connect_to_ipc_anonymous(struct net_context *c, + const char *server_name); + NTSTATUS connect_dst_pipe(struct net_context *c, struct cli_state **cli_dst, + struct rpc_pipe_client **pp_pipe_hnd, +- const struct ndr_syntax_id *interface); ++ const struct ndr_interface_table *table); + int net_use_krb_machine_account(struct net_context *c); + int net_use_machine_account(struct net_context *c); + bool net_find_server(struct net_context *c, +diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c +index c5c4d6c..4503f59 100644 +--- a/source3/utils/net_rpc.c ++++ b/source3/utils/net_rpc.c +@@ -3654,7 +3654,7 @@ static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c, + + /* connect destination PI_SRVSVC */ + nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe, +- &ndr_table_srvsvc.syntax_id); ++ &ndr_table_srvsvc); + if (!NT_STATUS_IS_OK(nt_status)) + return nt_status; + +@@ -4140,7 +4140,7 @@ static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c, + + /* connect destination PI_SRVSVC */ + nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe, +- &ndr_table_srvsvc.syntax_id); ++ &ndr_table_srvsvc); + if (!NT_STATUS_IS_OK(nt_status)) + return nt_status; + +diff --git a/source3/utils/net_rpc_printer.c b/source3/utils/net_rpc_printer.c +index ba34de1..1e42e6f 100644 +--- a/source3/utils/net_rpc_printer.c ++++ b/source3/utils/net_rpc_printer.c +@@ -1578,7 +1578,7 @@ NTSTATUS rpc_printer_migrate_security_internals(struct net_context *c, + + /* connect destination PI_SPOOLSS */ + nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst, +- &ndr_table_spoolss.syntax_id); ++ &ndr_table_spoolss); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } +@@ -1730,7 +1730,7 @@ NTSTATUS rpc_printer_migrate_forms_internals(struct net_context *c, + + /* connect destination PI_SPOOLSS */ + nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst, +- &ndr_table_spoolss.syntax_id); ++ &ndr_table_spoolss); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } +@@ -1907,7 +1907,7 @@ NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c, + DEBUG(3,("copying printer-drivers\n")); + + nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst, +- &ndr_table_spoolss.syntax_id); ++ &ndr_table_spoolss); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } +@@ -2126,7 +2126,7 @@ NTSTATUS rpc_printer_migrate_printers_internals(struct net_context *c, + + /* connect destination PI_SPOOLSS */ + nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst, +- &ndr_table_spoolss.syntax_id); ++ &ndr_table_spoolss); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } +@@ -2301,7 +2301,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c, + + /* connect destination PI_SPOOLSS */ + nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst, +- &ndr_table_spoolss.syntax_id); ++ &ndr_table_spoolss); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } +diff --git a/source3/utils/net_util.c b/source3/utils/net_util.c +index 9c4a77e..a4282ec 100644 +--- a/source3/utils/net_util.c ++++ b/source3/utils/net_util.c +@@ -231,7 +231,7 @@ NTSTATUS connect_to_ipc_anonymous(struct net_context *c, + **/ + NTSTATUS connect_dst_pipe(struct net_context *c, struct cli_state **cli_dst, + struct rpc_pipe_client **pp_pipe_hnd, +- const struct ndr_syntax_id *interface) ++ const struct ndr_interface_table *table) + { + NTSTATUS nt_status; + char *server_name = SMB_STRDUP("127.0.0.1"); +@@ -256,7 +256,7 @@ NTSTATUS connect_dst_pipe(struct net_context *c, struct cli_state **cli_dst, + return nt_status; + } + +- nt_status = cli_rpc_pipe_open_noauth(cli_tmp, interface, ++ nt_status = cli_rpc_pipe_open_noauth(cli_tmp, &table->syntax_id, + &pipe_hnd); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("couldn't not initialize pipe\n")); +-- +1.9.3 + + +From d5273069a42d7234daaf3dd043d0a6e455348385 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 17 May 2013 16:24:42 +0200 +Subject: [PATCH 017/249] s3-rpc_cli: remove prototype of nonexisting + cli_rpc_pipe_open_krb5(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit a1368ca6ef8ab4f158c8b303ad058835f1bbf441) +--- + source3/rpc_client/cli_pipe.h | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h +index bf785fb..34ae542 100644 +--- a/source3/rpc_client/cli_pipe.h ++++ b/source3/rpc_client/cli_pipe.h +@@ -131,15 +131,6 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, + const char *domain, + struct rpc_pipe_client **presult); + +-NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli, +- const struct ndr_syntax_id *interface, +- enum dcerpc_transport_t transport, +- enum dcerpc_AuthLevel auth_level, +- const char *service_princ, +- const char *username, +- const char *password, +- struct rpc_pipe_client **presult); +- + NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, + struct rpc_pipe_client *cli, + DATA_BLOB *session_key); +-- +1.9.3 + + +From 1a6c1ddb44aac3f201bbe2cabab10e409ffd042b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 17 May 2013 16:08:16 +0200 +Subject: [PATCH 018/249] s3-libnetapi: pass down ndr_interface_table to + libnetapi_get_binding_handle(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit fa37bbd9d06865d265bf554a3c49920f956f2185) +--- + source3/lib/netapi/cm.c | 4 ++-- + source3/lib/netapi/file.c | 6 +++--- + source3/lib/netapi/getdc.c | 6 +++--- + source3/lib/netapi/netapi_private.h | 3 ++- + source3/lib/netapi/netlogon.c | 4 ++-- + source3/lib/netapi/serverinfo.c | 6 +++--- + source3/lib/netapi/share.c | 10 +++++----- + source3/lib/netapi/shutdown.c | 4 ++-- + 8 files changed, 22 insertions(+), 21 deletions(-) + +diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c +index da3d2e1..c3ae19f 100644 +--- a/source3/lib/netapi/cm.c ++++ b/source3/lib/netapi/cm.c +@@ -269,7 +269,7 @@ WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, + + WERROR libnetapi_get_binding_handle(struct libnetapi_ctx *ctx, + const char *server_name, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + struct dcerpc_binding_handle **binding_handle) + { + struct rpc_pipe_client *pipe_cli; +@@ -277,7 +277,7 @@ WERROR libnetapi_get_binding_handle(struct libnetapi_ctx *ctx, + + *binding_handle = NULL; + +- result = libnetapi_open_pipe(ctx, server_name, interface, &pipe_cli); ++ result = libnetapi_open_pipe(ctx, server_name, &table->syntax_id, &pipe_cli); + if (!W_ERROR_IS_OK(result)) { + return result; + } +diff --git a/source3/lib/netapi/file.c b/source3/lib/netapi/file.c +index 1e406d2..551f9ff 100644 +--- a/source3/lib/netapi/file.c ++++ b/source3/lib/netapi/file.c +@@ -36,7 +36,7 @@ WERROR NetFileClose_r(struct libnetapi_ctx *ctx, + struct dcerpc_binding_handle *b; + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_srvsvc.syntax_id, ++ &ndr_table_srvsvc, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -130,7 +130,7 @@ WERROR NetFileGetInfo_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_srvsvc.syntax_id, ++ &ndr_table_srvsvc, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -201,7 +201,7 @@ WERROR NetFileEnum_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_srvsvc.syntax_id, ++ &ndr_table_srvsvc, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +diff --git a/source3/lib/netapi/getdc.c b/source3/lib/netapi/getdc.c +index 3b26d46..ae976f1 100644 +--- a/source3/lib/netapi/getdc.c ++++ b/source3/lib/netapi/getdc.c +@@ -47,7 +47,7 @@ WERROR NetGetDCName_r(struct libnetapi_ctx *ctx, + void *buffer; + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_netlogon.syntax_id, ++ &ndr_table_netlogon, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -101,7 +101,7 @@ WERROR NetGetAnyDCName_r(struct libnetapi_ctx *ctx, + void *buffer; + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_netlogon.syntax_id, ++ &ndr_table_netlogon, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -173,7 +173,7 @@ WERROR DsGetDcName_r(struct libnetapi_ctx *ctx, + struct dcerpc_binding_handle *b; + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_netlogon.syntax_id, ++ &ndr_table_netlogon, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +diff --git a/source3/lib/netapi/netapi_private.h b/source3/lib/netapi/netapi_private.h +index 349287b..62aa7ef 100644 +--- a/source3/lib/netapi/netapi_private.h ++++ b/source3/lib/netapi/netapi_private.h +@@ -30,6 +30,7 @@ + return fn ## _r(ctx, r); + + struct dcerpc_binding_handle; ++struct ndr_interface_table; + + struct libnetapi_private_ctx { + struct { +@@ -64,7 +65,7 @@ WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, + struct rpc_pipe_client **presult); + WERROR libnetapi_get_binding_handle(struct libnetapi_ctx *ctx, + const char *server_name, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + struct dcerpc_binding_handle **binding_handle); + WERROR libnetapi_samr_open_domain(struct libnetapi_ctx *mem_ctx, + struct rpc_pipe_client *pipe_cli, +diff --git a/source3/lib/netapi/netlogon.c b/source3/lib/netapi/netlogon.c +index a046fb7..136cb48 100644 +--- a/source3/lib/netapi/netlogon.c ++++ b/source3/lib/netapi/netlogon.c +@@ -133,7 +133,7 @@ WERROR I_NetLogonControl_r(struct libnetapi_ctx *ctx, + struct dcerpc_binding_handle *b; + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_netlogon.syntax_id, ++ &ndr_table_netlogon, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -190,7 +190,7 @@ WERROR I_NetLogonControl2_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_netlogon.syntax_id, ++ &ndr_table_netlogon, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +diff --git a/source3/lib/netapi/serverinfo.c b/source3/lib/netapi/serverinfo.c +index 046b693..b2a84d1 100644 +--- a/source3/lib/netapi/serverinfo.c ++++ b/source3/lib/netapi/serverinfo.c +@@ -503,7 +503,7 @@ WERROR NetServerGetInfo_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_srvsvc.syntax_id, ++ &ndr_table_srvsvc, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -616,7 +616,7 @@ WERROR NetServerSetInfo_r(struct libnetapi_ctx *ctx, + struct dcerpc_binding_handle *b; + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_srvsvc.syntax_id, ++ &ndr_table_srvsvc, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -658,7 +658,7 @@ WERROR NetRemoteTOD_r(struct libnetapi_ctx *ctx, + struct dcerpc_binding_handle *b; + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_srvsvc.syntax_id, ++ &ndr_table_srvsvc, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +diff --git a/source3/lib/netapi/share.c b/source3/lib/netapi/share.c +index d12fa1c..090e1a9 100644 +--- a/source3/lib/netapi/share.c ++++ b/source3/lib/netapi/share.c +@@ -200,7 +200,7 @@ WERROR NetShareAdd_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_srvsvc.syntax_id, ++ &ndr_table_srvsvc, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -258,7 +258,7 @@ WERROR NetShareDel_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_srvsvc.syntax_id, ++ &ndr_table_srvsvc, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -321,7 +321,7 @@ WERROR NetShareEnum_r(struct libnetapi_ctx *ctx, + ZERO_STRUCT(info_ctr); + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_srvsvc.syntax_id, ++ &ndr_table_srvsvc, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -428,7 +428,7 @@ WERROR NetShareGetInfo_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_srvsvc.syntax_id, ++ &ndr_table_srvsvc, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -502,7 +502,7 @@ WERROR NetShareSetInfo_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_srvsvc.syntax_id, ++ &ndr_table_srvsvc, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +diff --git a/source3/lib/netapi/shutdown.c b/source3/lib/netapi/shutdown.c +index 78bc2fc..9e1e8e1 100644 +--- a/source3/lib/netapi/shutdown.c ++++ b/source3/lib/netapi/shutdown.c +@@ -38,7 +38,7 @@ WERROR NetShutdownInit_r(struct libnetapi_ctx *ctx, + struct dcerpc_binding_handle *b; + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_initshutdown.syntax_id, ++ &ndr_table_initshutdown, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -82,7 +82,7 @@ WERROR NetShutdownAbort_r(struct libnetapi_ctx *ctx, + struct dcerpc_binding_handle *b; + + werr = libnetapi_get_binding_handle(ctx, r->in.server_name, +- &ndr_table_initshutdown.syntax_id, ++ &ndr_table_initshutdown, + &b); + if (!W_ERROR_IS_OK(werr)) { + goto done; +-- +1.9.3 + + +From e25e7bfe15bdb89a9680708c27b50e14a8a86ca3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 17 May 2013 16:10:13 +0200 +Subject: [PATCH 019/249] s3-libnetapi: pass down ndr_interface_table to + libnetapi_open_pipe(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 77f7f2a976e5b95f3bd9f542b92926adee4f5fa6) +--- + source3/lib/netapi/cm.c | 8 ++++---- + source3/lib/netapi/group.c | 18 +++++++++--------- + source3/lib/netapi/joindomain.c | 10 +++++----- + source3/lib/netapi/localgroup.c | 14 +++++++------- + source3/lib/netapi/netapi_private.h | 2 +- + source3/lib/netapi/user.c | 22 +++++++++++----------- + 6 files changed, 37 insertions(+), 37 deletions(-) + +diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c +index c3ae19f..dd1f1e3 100644 +--- a/source3/lib/netapi/cm.c ++++ b/source3/lib/netapi/cm.c +@@ -234,7 +234,7 @@ static NTSTATUS pipe_cm_open(TALLOC_CTX *ctx, + + WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, + const char *server_name, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult) + { + struct rpc_pipe_client *result = NULL; +@@ -251,10 +251,10 @@ WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, + return werr; + } + +- status = pipe_cm_open(ctx, ipc, interface, &result); ++ status = pipe_cm_open(ctx, ipc, &table->syntax_id, &result); + if (!NT_STATUS_IS_OK(status)) { + libnetapi_set_error_string(ctx, "failed to open PIPE %s: %s", +- get_pipe_name_from_syntax(talloc_tos(), interface), ++ get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), + get_friendly_nt_error_msg(status)); + return WERR_DEST_NOT_FOUND; + } +@@ -277,7 +277,7 @@ WERROR libnetapi_get_binding_handle(struct libnetapi_ctx *ctx, + + *binding_handle = NULL; + +- result = libnetapi_open_pipe(ctx, server_name, &table->syntax_id, &pipe_cli); ++ result = libnetapi_open_pipe(ctx, server_name, table, &pipe_cli); + if (!W_ERROR_IS_OK(result)) { + return result; + } +diff --git a/source3/lib/netapi/group.c b/source3/lib/netapi/group.c +index b806fc4..6d9b248 100644 +--- a/source3/lib/netapi/group.c ++++ b/source3/lib/netapi/group.c +@@ -76,7 +76,7 @@ WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -272,7 +272,7 @@ WERROR NetGroupDel_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -492,7 +492,7 @@ WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -770,7 +770,7 @@ WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -918,7 +918,7 @@ WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -1078,7 +1078,7 @@ WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -1397,7 +1397,7 @@ WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -1544,7 +1544,7 @@ WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx, + + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -1736,7 +1736,7 @@ WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +diff --git a/source3/lib/netapi/joindomain.c b/source3/lib/netapi/joindomain.c +index b6fb57a..d8e624f 100644 +--- a/source3/lib/netapi/joindomain.c ++++ b/source3/lib/netapi/joindomain.c +@@ -116,7 +116,7 @@ WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx, + DATA_BLOB session_key; + + werr = libnetapi_open_pipe(ctx, r->in.server, +- &ndr_table_wkssvc.syntax_id, ++ &ndr_table_wkssvc, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -257,7 +257,7 @@ WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx, + DATA_BLOB session_key; + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_wkssvc.syntax_id, ++ &ndr_table_wkssvc, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -313,7 +313,7 @@ WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx, + struct dcerpc_binding_handle *b; + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_wkssvc.syntax_id, ++ &ndr_table_wkssvc, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -455,7 +455,7 @@ WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx, + DATA_BLOB session_key; + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_wkssvc.syntax_id, ++ &ndr_table_wkssvc, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -508,7 +508,7 @@ WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx, + DATA_BLOB session_key; + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_wkssvc.syntax_id, ++ &ndr_table_wkssvc, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +diff --git a/source3/lib/netapi/localgroup.c b/source3/lib/netapi/localgroup.c +index 17cab68..241970d 100644 +--- a/source3/lib/netapi/localgroup.c ++++ b/source3/lib/netapi/localgroup.c +@@ -185,7 +185,7 @@ WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -319,7 +319,7 @@ WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx, + ZERO_STRUCT(alias_handle); + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -499,7 +499,7 @@ WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx, + ZERO_STRUCT(alias_handle); + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -678,7 +678,7 @@ WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx, + ZERO_STRUCT(alias_handle); + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -828,7 +828,7 @@ WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx, + ZERO_STRUCT(alias_handle); + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -1141,7 +1141,7 @@ static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx, + + if (r->in.level == 3) { + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_lsarpc.syntax_id, ++ &ndr_table_lsarpc, + &lsa_pipe); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -1160,7 +1160,7 @@ static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +diff --git a/source3/lib/netapi/netapi_private.h b/source3/lib/netapi/netapi_private.h +index 62aa7ef..897cf3d 100644 +--- a/source3/lib/netapi/netapi_private.h ++++ b/source3/lib/netapi/netapi_private.h +@@ -61,7 +61,7 @@ NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx, char **debugl + WERROR libnetapi_shutdown_cm(struct libnetapi_ctx *ctx); + WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, + const char *server_name, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult); + WERROR libnetapi_get_binding_handle(struct libnetapi_ctx *ctx, + const char *server_name, +diff --git a/source3/lib/netapi/user.c b/source3/lib/netapi/user.c +index a971e2d..4a39f69 100644 +--- a/source3/lib/netapi/user.c ++++ b/source3/lib/netapi/user.c +@@ -400,7 +400,7 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -552,7 +552,7 @@ WERROR NetUserDel_r(struct libnetapi_ctx *ctx, + ZERO_STRUCT(user_handle); + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + + if (!W_ERROR_IS_OK(werr)) { +@@ -1322,7 +1322,7 @@ WERROR NetUserEnum_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -1630,7 +1630,7 @@ WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -1764,7 +1764,7 @@ WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -1936,7 +1936,7 @@ WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -2395,7 +2395,7 @@ WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -2880,7 +2880,7 @@ WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -3015,7 +3015,7 @@ WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -3206,7 +3206,7 @@ WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +@@ -3547,7 +3547,7 @@ WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx, + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; +-- +1.9.3 + + +From 4157ba43258373cd995b2ee74dcd4d65782dc2ea Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 17 May 2013 16:13:26 +0200 +Subject: [PATCH 020/249] s3-libnetapi: pass down ndr_interface_table to + pipe_cm() and friends. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 0ce2178f2ffeaee324c7e8fef7c87727def7bd77) +--- + source3/lib/netapi/cm.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c +index dd1f1e3..8551521 100644 +--- a/source3/lib/netapi/cm.c ++++ b/source3/lib/netapi/cm.c +@@ -161,7 +161,7 @@ WERROR libnetapi_shutdown_cm(struct libnetapi_ctx *ctx) + ********************************************************************/ + + static NTSTATUS pipe_cm_find(struct client_ipc_connection *ipc, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult) + { + struct client_pipe_connection *p; +@@ -177,7 +177,7 @@ static NTSTATUS pipe_cm_find(struct client_ipc_connection *ipc, + + if (strequal(ipc_remote_name, p->pipe->desthost) + && ndr_syntax_id_equal(&p->pipe->abstract_syntax, +- interface)) { ++ &table->syntax_id)) { + *presult = p->pipe; + return NT_STATUS_OK; + } +@@ -191,7 +191,7 @@ static NTSTATUS pipe_cm_find(struct client_ipc_connection *ipc, + + static NTSTATUS pipe_cm_connect(TALLOC_CTX *mem_ctx, + struct client_ipc_connection *ipc, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult) + { + struct client_pipe_connection *p; +@@ -202,7 +202,7 @@ static NTSTATUS pipe_cm_connect(TALLOC_CTX *mem_ctx, + return NT_STATUS_NO_MEMORY; + } + +- status = cli_rpc_pipe_open_noauth(ipc->cli, interface, &p->pipe); ++ status = cli_rpc_pipe_open_noauth(ipc->cli, &table->syntax_id, &p->pipe); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(p); + return status; +@@ -219,14 +219,14 @@ static NTSTATUS pipe_cm_connect(TALLOC_CTX *mem_ctx, + + static NTSTATUS pipe_cm_open(TALLOC_CTX *ctx, + struct client_ipc_connection *ipc, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult) + { +- if (NT_STATUS_IS_OK(pipe_cm_find(ipc, interface, presult))) { ++ if (NT_STATUS_IS_OK(pipe_cm_find(ipc, table, presult))) { + return NT_STATUS_OK; + } + +- return pipe_cm_connect(ctx, ipc, interface, presult); ++ return pipe_cm_connect(ctx, ipc, table, presult); + } + + /******************************************************************** +@@ -251,7 +251,7 @@ WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, + return werr; + } + +- status = pipe_cm_open(ctx, ipc, &table->syntax_id, &result); ++ status = pipe_cm_open(ctx, ipc, table, &result); + if (!NT_STATUS_IS_OK(status)) { + libnetapi_set_error_string(ctx, "failed to open PIPE %s: %s", + get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), +-- +1.9.3 + + +From ec8ba2a371ce4c4cc14d04e852034dcd92862542 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 17 May 2013 16:16:59 +0200 +Subject: [PATCH 021/249] s3-rpc_cli: pass down ndr_interface_table to + rpc_pipe_open_ncalrpc(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 9b4fb5b074b035eaef98c4a463c9d68006ed52da) +--- + source3/librpc/rpc/dcerpc_ep.c | 2 +- + source3/rpc_client/cli_pipe.c | 4 ++-- + source3/rpc_client/cli_pipe.h | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/source3/librpc/rpc/dcerpc_ep.c b/source3/librpc/rpc/dcerpc_ep.c +index bb080c5..410caa7 100644 +--- a/source3/librpc/rpc/dcerpc_ep.c ++++ b/source3/librpc/rpc/dcerpc_ep.c +@@ -365,7 +365,7 @@ static NTSTATUS ep_register(TALLOC_CTX *mem_ctx, + + status = rpc_pipe_open_ncalrpc(tmp_ctx, + ncalrpc_sock, +- &ndr_table_epmapper.syntax_id, ++ &ndr_table_epmapper, + &cli); + if (!NT_STATUS_IS_OK(status)) { + goto done; +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 385ae25..427b628 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -2682,7 +2682,7 @@ NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host, + Create a rpc pipe client struct, connecting to a unix domain socket + ********************************************************************/ + NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path, +- const struct ndr_syntax_id *abstract_syntax, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult) + { + struct rpc_pipe_client *result; +@@ -2696,7 +2696,7 @@ NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path, + return NT_STATUS_NO_MEMORY; + } + +- result->abstract_syntax = *abstract_syntax; ++ result->abstract_syntax = table->syntax_id; + result->transfer_syntax = ndr_transfer_syntax_ndr; + + result->desthost = get_myname(result); +diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h +index 34ae542..3415db0 100644 +--- a/source3/rpc_client/cli_pipe.h ++++ b/source3/rpc_client/cli_pipe.h +@@ -71,7 +71,7 @@ NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, + struct rpc_pipe_client **presult); + + NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path, +- const struct ndr_syntax_id *abstract_syntax, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult); + + struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c); +-- +1.9.3 + + +From 816b7983c2342ea500e7467f2ab6c04dff89308f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 17 May 2013 16:44:05 +0200 +Subject: [PATCH 022/249] s3-rpc_cli: pass down ndr_interface_table to + rpc_pipe_open_interface(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 6886cff0a7e97864e9094af936cbef08a3c8f6f4) +--- + source3/printing/nt_printing_migrate_internal.c | 2 +- + source3/printing/printspoolss.c | 4 +-- + source3/rpc_server/rpc_ncacn_np.c | 8 +++--- + source3/rpc_server/rpc_ncacn_np.h | 2 +- + source3/smbd/lanman.c | 34 ++++++++++++------------- + source3/smbd/reply.c | 2 +- + 6 files changed, 26 insertions(+), 26 deletions(-) + +diff --git a/source3/printing/nt_printing_migrate_internal.c b/source3/printing/nt_printing_migrate_internal.c +index 200db07f..6bc7ea2 100644 +--- a/source3/printing/nt_printing_migrate_internal.c ++++ b/source3/printing/nt_printing_migrate_internal.c +@@ -211,7 +211,7 @@ bool nt_printing_tdb_migrate(struct messaging_context *msg_ctx) + } + + status = rpc_pipe_open_interface(tmp_ctx, +- &ndr_table_winreg.syntax_id, ++ &ndr_table_winreg, + session_info, + NULL, + msg_ctx, +diff --git a/source3/printing/printspoolss.c b/source3/printing/printspoolss.c +index fc1e9c1..0507e83 100644 +--- a/source3/printing/printspoolss.c ++++ b/source3/printing/printspoolss.c +@@ -154,7 +154,7 @@ NTSTATUS print_spool_open(files_struct *fsp, + * a job id */ + + status = rpc_pipe_open_interface(fsp->conn, +- &ndr_table_spoolss.syntax_id, ++ &ndr_table_spoolss, + fsp->conn->session_info, + fsp->conn->sconn->remote_address, + fsp->conn->sconn->msg_ctx, +@@ -343,7 +343,7 @@ void print_spool_terminate(struct connection_struct *conn, + rap_jobid_delete(print_file->svcname, print_file->jobid); + + status = rpc_pipe_open_interface(conn, +- &ndr_table_spoolss.syntax_id, ++ &ndr_table_spoolss, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +diff --git a/source3/rpc_server/rpc_ncacn_np.c b/source3/rpc_server/rpc_ncacn_np.c +index b4602a9..7389b3e 100644 +--- a/source3/rpc_server/rpc_ncacn_np.c ++++ b/source3/rpc_server/rpc_ncacn_np.c +@@ -758,7 +758,7 @@ done: + */ + + NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx, +- const struct ndr_syntax_id *syntax, ++ const struct ndr_interface_table *table, + const struct auth_session_info *session_info, + const struct tsocket_address *remote_address, + struct messaging_context *msg_ctx, +@@ -783,7 +783,7 @@ NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx, + return NT_STATUS_NO_MEMORY; + } + +- pipe_name = get_pipe_name_from_syntax(tmp_ctx, syntax); ++ pipe_name = get_pipe_name_from_syntax(tmp_ctx, &table->syntax_id); + if (pipe_name == NULL) { + status = NT_STATUS_INVALID_PARAMETER; + goto done; +@@ -800,7 +800,7 @@ NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx, + switch (pipe_mode) { + case RPC_SERVICE_MODE_EMBEDDED: + status = rpc_pipe_open_internal(tmp_ctx, +- syntax, session_info, ++ &table->syntax_id, session_info, + remote_address, msg_ctx, + &cli); + if (!NT_STATUS_IS_OK(status)) { +@@ -813,7 +813,7 @@ NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx, + * to spoolssd. */ + + status = rpc_pipe_open_external(tmp_ctx, +- pipe_name, syntax, ++ pipe_name, &table->syntax_id, + session_info, + &cli); + if (!NT_STATUS_IS_OK(status)) { +diff --git a/source3/rpc_server/rpc_ncacn_np.h b/source3/rpc_server/rpc_ncacn_np.h +index 586d61b..67cd8a1 100644 +--- a/source3/rpc_server/rpc_ncacn_np.h ++++ b/source3/rpc_server/rpc_ncacn_np.h +@@ -50,7 +50,7 @@ NTSTATUS rpcint_binding_handle(TALLOC_CTX *mem_ctx, + struct messaging_context *msg_ctx, + struct dcerpc_binding_handle **binding_handle); + NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx, +- const struct ndr_syntax_id *syntax, ++ const struct ndr_interface_table *table, + const struct auth_session_info *session_info, + const struct tsocket_address *remote_address, + struct messaging_context *msg_ctx, +diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c +index d0dae36..3c488ec 100644 +--- a/source3/smbd/lanman.c ++++ b/source3/smbd/lanman.c +@@ -832,7 +832,7 @@ static bool api_DosPrintQGetInfo(struct smbd_server_connection *sconn, + } + + status = rpc_pipe_open_interface(conn, +- &ndr_table_spoolss.syntax_id, ++ &ndr_table_spoolss, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +@@ -1029,7 +1029,7 @@ static bool api_DosPrintQEnum(struct smbd_server_connection *sconn, + } + + status = rpc_pipe_open_interface(conn, +- &ndr_table_spoolss.syntax_id, ++ &ndr_table_spoolss, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +@@ -2256,7 +2256,7 @@ static bool api_RNetShareAdd(struct smbd_server_connection *sconn, + return false; + } + +- status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc.syntax_id, ++ status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +@@ -2368,7 +2368,7 @@ static bool api_RNetGroupEnum(struct smbd_server_connection *sconn, + } + + status = rpc_pipe_open_interface( +- talloc_tos(), &ndr_table_samr.syntax_id, ++ talloc_tos(), &ndr_table_samr, + conn->session_info, conn->sconn->remote_address, + conn->sconn->msg_ctx, &samr_pipe); + if (!NT_STATUS_IS_OK(status)) { +@@ -2574,7 +2574,7 @@ static bool api_NetUserGetGroups(struct smbd_server_connection *sconn, + endp = *rdata + *rdata_len; + + status = rpc_pipe_open_interface( +- talloc_tos(), &ndr_table_samr.syntax_id, ++ talloc_tos(), &ndr_table_samr, + conn->session_info, conn->sconn->remote_address, + conn->sconn->msg_ctx, &samr_pipe); + if (!NT_STATUS_IS_OK(status)) { +@@ -2774,7 +2774,7 @@ static bool api_RNetUserEnum(struct smbd_server_connection *sconn, + endp = *rdata + *rdata_len; + + status = rpc_pipe_open_interface( +- talloc_tos(), &ndr_table_samr.syntax_id, ++ talloc_tos(), &ndr_table_samr, + conn->session_info, conn->sconn->remote_address, + conn->sconn->msg_ctx, &samr_pipe); + if (!NT_STATUS_IS_OK(status)) { +@@ -3037,7 +3037,7 @@ static bool api_SamOEMChangePassword(struct smbd_server_connection *sconn, + memcpy(password.data, data, 516); + memcpy(hash.hash, data+516, 16); + +- status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id, ++ status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +@@ -3134,7 +3134,7 @@ static bool api_RDosPrintJobDel(struct smbd_server_connection *sconn, + ZERO_STRUCT(handle); + + status = rpc_pipe_open_interface(conn, +- &ndr_table_spoolss.syntax_id, ++ &ndr_table_spoolss, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +@@ -3262,7 +3262,7 @@ static bool api_WPrintQueueCtrl(struct smbd_server_connection *sconn, + ZERO_STRUCT(handle); + + status = rpc_pipe_open_interface(conn, +- &ndr_table_spoolss.syntax_id, ++ &ndr_table_spoolss, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +@@ -3444,7 +3444,7 @@ static bool api_PrintJobInfo(struct smbd_server_connection *sconn, + ZERO_STRUCT(handle); + + status = rpc_pipe_open_interface(conn, +- &ndr_table_spoolss.syntax_id, ++ &ndr_table_spoolss, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +@@ -3621,7 +3621,7 @@ static bool api_RNetServerGetInfo(struct smbd_server_connection *sconn, + p = *rdata; + p2 = p + struct_len; + +- status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc.syntax_id, ++ status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +@@ -4052,7 +4052,7 @@ static bool api_RNetUserGetInfo(struct smbd_server_connection *sconn, + ZERO_STRUCT(domain_handle); + ZERO_STRUCT(user_handle); + +- status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id, ++ status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +@@ -4581,7 +4581,7 @@ static bool api_WPrintJobGetInfo(struct smbd_server_connection *sconn, + ZERO_STRUCT(handle); + + status = rpc_pipe_open_interface(conn, +- &ndr_table_spoolss.syntax_id, ++ &ndr_table_spoolss, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +@@ -4723,7 +4723,7 @@ static bool api_WPrintJobEnumerate(struct smbd_server_connection *sconn, + ZERO_STRUCT(handle); + + status = rpc_pipe_open_interface(conn, +- &ndr_table_spoolss.syntax_id, ++ &ndr_table_spoolss, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +@@ -4923,7 +4923,7 @@ static bool api_WPrintDestGetInfo(struct smbd_server_connection *sconn, + ZERO_STRUCT(handle); + + status = rpc_pipe_open_interface(conn, +- &ndr_table_spoolss.syntax_id, ++ &ndr_table_spoolss, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +@@ -5055,7 +5055,7 @@ static bool api_WPrintDestEnum(struct smbd_server_connection *sconn, + queuecnt = 0; + + status = rpc_pipe_open_interface(conn, +- &ndr_table_spoolss.syntax_id, ++ &ndr_table_spoolss, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +@@ -5366,7 +5366,7 @@ static bool api_RNetSessionEnum(struct smbd_server_connection *sconn, + } + + status = rpc_pipe_open_interface(conn, +- &ndr_table_srvsvc.syntax_id, ++ &ndr_table_srvsvc, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c +index 3f5b950..eace557 100644 +--- a/source3/smbd/reply.c ++++ b/source3/smbd/reply.c +@@ -5637,7 +5637,7 @@ void reply_printqueue(struct smb_request *req) + ZERO_STRUCT(handle); + + status = rpc_pipe_open_interface(conn, +- &ndr_table_spoolss.syntax_id, ++ &ndr_table_spoolss, + conn->session_info, + conn->sconn->remote_address, + conn->sconn->msg_ctx, +-- +1.9.3 + + +From 3dc2d438f0b440f34b7cdd9eeac429a15f679460 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 24 May 2013 13:03:23 +0200 +Subject: [PATCH 023/249] s3-rpc_cli: pass down ndr_interface_table to + cli_rpc_pipe_open_schannel(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit f6d61b571d79ebf1df58513ec728057d00b95f3e) +--- + source3/auth/auth_domain.c | 2 +- + source3/rpc_client/cli_pipe.h | 2 +- + source3/rpc_client/cli_pipe_schannel.c | 4 ++-- + source3/rpcclient/rpcclient.c | 2 +- + source3/utils/net_rpc.c | 2 +- + 5 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c +index 286c75c..a375f11 100644 +--- a/source3/auth/auth_domain.c ++++ b/source3/auth/auth_domain.c +@@ -115,7 +115,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, + if (lp_client_schannel()) { + /* We also setup the creds chain in the open_schannel call. */ + result = cli_rpc_pipe_open_schannel( +- *cli, &ndr_table_netlogon.syntax_id, NCACN_NP, ++ *cli, &ndr_table_netlogon, NCACN_NP, + DCERPC_AUTH_LEVEL_PRIVACY, domain, &netlogon_pipe); + } else { + result = cli_rpc_pipe_open_noauth( +diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h +index 3415db0..d17322a 100644 +--- a/source3/rpc_client/cli_pipe.h ++++ b/source3/rpc_client/cli_pipe.h +@@ -125,7 +125,7 @@ NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, + struct rpc_pipe_client **presult); + + NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + enum dcerpc_transport_t transport, + enum dcerpc_AuthLevel auth_level, + const char *domain, +diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c +index c275720..8bc01a5 100644 +--- a/source3/rpc_client/cli_pipe_schannel.c ++++ b/source3/rpc_client/cli_pipe_schannel.c +@@ -169,7 +169,7 @@ NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, + ****************************************************************************/ + + NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + enum dcerpc_transport_t transport, + enum dcerpc_AuthLevel auth_level, + const char *domain, +@@ -190,7 +190,7 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, + } + + status = cli_rpc_pipe_open_schannel_with_key( +- cli, interface, transport, auth_level, domain, &netlogon_pipe->dc, ++ cli, &table->syntax_id, transport, auth_level, domain, &netlogon_pipe->dc, + &result); + + /* Now we've bound using the session key we can close the netlog pipe. */ +diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c +index d204d7f..6b6478e 100644 +--- a/source3/rpcclient/rpcclient.c ++++ b/source3/rpcclient/rpcclient.c +@@ -734,7 +734,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, + break; + case DCERPC_AUTH_TYPE_SCHANNEL: + ntresult = cli_rpc_pipe_open_schannel( +- cli, &cmd_entry->table->syntax_id, ++ cli, cmd_entry->table, + default_transport, + pipe_default_auth_level, + get_cmdline_auth_info_domain(auth_info), +diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c +index 4503f59..dab9fcd 100644 +--- a/source3/utils/net_rpc.c ++++ b/source3/utils/net_rpc.c +@@ -191,7 +191,7 @@ int run_rpc_command(struct net_context *c, + &ndr_table_netlogon.syntax_id))) { + /* Always try and create an schannel netlogon pipe. */ + nt_status = cli_rpc_pipe_open_schannel( +- cli, &table->syntax_id, NCACN_NP, ++ cli, table, NCACN_NP, + DCERPC_AUTH_LEVEL_PRIVACY, domain_name, + &pipe_hnd); + if (!NT_STATUS_IS_OK(nt_status)) { +-- +1.9.3 + + +From 428596faf89f424c83edb86d45c5a1322e3fb6b5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 24 May 2013 13:08:33 +0200 +Subject: [PATCH 024/249] s3-rpc_cli: pass down ndr_interface_table to + cli_rpc_pipe_open_ntlmssp_auth_schannel(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 7f169474fc86479abe09a5716b8029c6febcfaa9) +--- + source3/rpc_client/cli_pipe.h | 2 +- + source3/rpc_client/cli_pipe_schannel.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h +index d17322a..7026692 100644 +--- a/source3/rpc_client/cli_pipe.h ++++ b/source3/rpc_client/cli_pipe.h +@@ -116,7 +116,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + struct rpc_pipe_client **presult); + + NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + enum dcerpc_transport_t transport, + enum dcerpc_AuthLevel auth_level, + const char *domain, +diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c +index 8bc01a5..261a768 100644 +--- a/source3/rpc_client/cli_pipe_schannel.c ++++ b/source3/rpc_client/cli_pipe_schannel.c +@@ -128,7 +128,7 @@ static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli, + ****************************************************************************/ + + NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + enum dcerpc_transport_t transport, + enum dcerpc_AuthLevel auth_level, + const char *domain, +@@ -151,7 +151,7 @@ NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, + } + + status = cli_rpc_pipe_open_schannel_with_key( +- cli, interface, transport, auth_level, domain, &netlogon_pipe->dc, ++ cli, &table->syntax_id, transport, auth_level, domain, &netlogon_pipe->dc, + &result); + + /* Now we've bound using the session key we can close the netlog pipe. */ +-- +1.9.3 + + +From cda31f4e490942ffc89513f000fa147f535a2713 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 24 May 2013 13:17:24 +0200 +Subject: [PATCH 025/249] s3-rpc_cli: pass down ndr_interface_table to + cli_rpc_pipe_open_schannel_with_key(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 3dc3a6c8483a8de22b483ecf164c81232d4a8d65) +--- + source3/libnet/libnet_join.c | 2 +- + source3/rpc_client/cli_pipe.c | 6 +++--- + source3/rpc_client/cli_pipe.h | 2 +- + source3/rpc_client/cli_pipe_schannel.c | 4 ++-- + source3/utils/net_rpc_join.c | 4 ++-- + source3/winbindd/winbindd_cm.c | 8 ++++---- + 6 files changed, 13 insertions(+), 13 deletions(-) + +diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c +index 1418385..9f47f3b 100644 +--- a/source3/libnet/libnet_join.c ++++ b/source3/libnet/libnet_join.c +@@ -1287,7 +1287,7 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, + } + + status = cli_rpc_pipe_open_schannel_with_key( +- cli, &ndr_table_netlogon.syntax_id, NCACN_NP, ++ cli, &ndr_table_netlogon, NCACN_NP, + DCERPC_AUTH_LEVEL_PRIVACY, + netbios_domain_name, &netlogon_pipe->dc, &pipe_hnd); + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 427b628..34cef32 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -3022,7 +3022,7 @@ NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli, + ****************************************************************************/ + + NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + enum dcerpc_transport_t transport, + enum dcerpc_AuthLevel auth_level, + const char *domain, +@@ -3033,7 +3033,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + struct pipe_auth_data *auth; + NTSTATUS status; + +- status = cli_rpc_pipe_open(cli, transport, interface, &result); ++ status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result); + if (!NT_STATUS_IS_OK(status)) { + return status; + } +@@ -3070,7 +3070,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + + DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s " + "for domain %s and bound using schannel.\n", +- get_pipe_name_from_syntax(talloc_tos(), interface), ++ get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), + result->desthost, domain)); + + *presult = result; +diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h +index 7026692..65bfbc8 100644 +--- a/source3/rpc_client/cli_pipe.h ++++ b/source3/rpc_client/cli_pipe.h +@@ -108,7 +108,7 @@ NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli, + struct rpc_pipe_client **presult); + + NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + enum dcerpc_transport_t transport, + enum dcerpc_AuthLevel auth_level, + const char *domain, +diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c +index 261a768..784e63f 100644 +--- a/source3/rpc_client/cli_pipe_schannel.c ++++ b/source3/rpc_client/cli_pipe_schannel.c +@@ -151,7 +151,7 @@ NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, + } + + status = cli_rpc_pipe_open_schannel_with_key( +- cli, &table->syntax_id, transport, auth_level, domain, &netlogon_pipe->dc, ++ cli, table, transport, auth_level, domain, &netlogon_pipe->dc, + &result); + + /* Now we've bound using the session key we can close the netlog pipe. */ +@@ -190,7 +190,7 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, + } + + status = cli_rpc_pipe_open_schannel_with_key( +- cli, &table->syntax_id, transport, auth_level, domain, &netlogon_pipe->dc, ++ cli, table, transport, auth_level, domain, &netlogon_pipe->dc, + &result); + + /* Now we've bound using the session key we can close the netlog pipe. */ +diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c +index 56799cd..4b43769 100644 +--- a/source3/utils/net_rpc_join.c ++++ b/source3/utils/net_rpc_join.c +@@ -137,7 +137,7 @@ NTSTATUS net_rpc_join_ok(struct net_context *c, const char *domain, + } + + ntret = cli_rpc_pipe_open_schannel_with_key( +- cli, &ndr_table_netlogon.syntax_id, NCACN_NP, ++ cli, &ndr_table_netlogon, NCACN_NP, + DCERPC_AUTH_LEVEL_PRIVACY, + domain, &netlogon_pipe->dc, &pipe_hnd); + +@@ -497,7 +497,7 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) + struct rpc_pipe_client *netlogon_schannel_pipe; + + status = cli_rpc_pipe_open_schannel_with_key( +- cli, &ndr_table_netlogon.syntax_id, NCACN_NP, ++ cli, &ndr_table_netlogon, NCACN_NP, + DCERPC_AUTH_LEVEL_PRIVACY, domain, &pipe_hnd->dc, + &netlogon_schannel_pipe); + +diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c +index 61917db..f17fc68 100644 +--- a/source3/winbindd/winbindd_cm.c ++++ b/source3/winbindd/winbindd_cm.c +@@ -2415,7 +2415,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + goto anonymous; + } + status = cli_rpc_pipe_open_schannel_with_key +- (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP, ++ (conn->cli, &ndr_table_samr, NCACN_NP, + DCERPC_AUTH_LEVEL_PRIVACY, + domain->name, &p_creds, &conn->samr_pipe); + +@@ -2547,7 +2547,7 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain, + } + + status = cli_rpc_pipe_open_schannel_with_key(conn->cli, +- &ndr_table_lsarpc.syntax_id, ++ &ndr_table_lsarpc, + NCACN_IP_TCP, + DCERPC_AUTH_LEVEL_PRIVACY, + domain->name, +@@ -2646,7 +2646,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + goto anonymous; + } + result = cli_rpc_pipe_open_schannel_with_key +- (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP, ++ (conn->cli, &ndr_table_lsarpc, NCACN_NP, + DCERPC_AUTH_LEVEL_PRIVACY, + domain->name, &p_creds, &conn->lsa_pipe); + +@@ -2831,7 +2831,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, + */ + + result = cli_rpc_pipe_open_schannel_with_key( +- conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP, ++ conn->cli, &ndr_table_netlogon, NCACN_NP, + DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc, + &conn->netlogon_pipe); + +-- +1.9.3 + + +From 9b569e91cd22806eedae76d3fb60cdbd7548e4c2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 24 May 2013 13:29:28 +0200 +Subject: [PATCH 026/249] s3-rpc_cli: pass down ndr_interface_table to + cli_rpc_pipe_open_noauth(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 9813fe2b04a5b4abaa95ea1d893b3803edbede4d) +--- + source3/auth/auth_domain.c | 2 +- + source3/client/client.c | 2 +- + source3/lib/netapi/cm.c | 2 +- + source3/libnet/libnet_join.c | 8 ++++---- + source3/libsmb/libsmb_dir.c | 2 +- + source3/libsmb/libsmb_server.c | 2 +- + source3/libsmb/passchange.c | 4 ++-- + source3/libsmb/trustdom_cache.c | 2 +- + source3/libsmb/trusts_util.c | 2 +- + source3/rpc_client/cli_pipe.c | 4 ++-- + source3/rpc_client/cli_pipe.h | 2 +- + source3/rpc_client/cli_pipe_schannel.c | 2 +- + source3/rpc_server/spoolss/srv_spoolss_nt.c | 2 +- + source3/rpcclient/cmd_spoolss.c | 2 +- + source3/rpcclient/cmd_test.c | 4 ++-- + source3/rpcclient/rpcclient.c | 2 +- + source3/torture/test_async_echo.c | 2 +- + source3/utils/net_ads.c | 2 +- + source3/utils/net_rpc.c | 20 ++++++++++---------- + source3/utils/net_rpc_join.c | 6 +++--- + source3/utils/net_rpc_shell.c | 2 +- + source3/utils/net_rpc_trust.c | 2 +- + source3/utils/net_util.c | 8 ++++---- + source3/utils/netlookup.c | 2 +- + source3/utils/smbcacls.c | 7 +++---- + source3/utils/smbcquotas.c | 2 +- + source3/utils/smbtree.c | 2 +- + source3/winbindd/winbindd_cm.c | 10 +++++----- + 28 files changed, 54 insertions(+), 55 deletions(-) + +diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c +index a375f11..54ee5a1 100644 +--- a/source3/auth/auth_domain.c ++++ b/source3/auth/auth_domain.c +@@ -119,7 +119,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, + DCERPC_AUTH_LEVEL_PRIVACY, domain, &netlogon_pipe); + } else { + result = cli_rpc_pipe_open_noauth( +- *cli, &ndr_table_netlogon.syntax_id, &netlogon_pipe); ++ *cli, &ndr_table_netlogon, &netlogon_pipe); + } + + if (!NT_STATUS_IS_OK(result)) { +diff --git a/source3/client/client.c b/source3/client/client.c +index ab46cb8..dafc5f0 100644 +--- a/source3/client/client.c ++++ b/source3/client/client.c +@@ -4227,7 +4227,7 @@ static bool browse_host_rpc(bool sort) + int i; + struct dcerpc_binding_handle *b; + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc, + &pipe_hnd); + + if (!NT_STATUS_IS_OK(status)) { +diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c +index 8551521..1cfdccf 100644 +--- a/source3/lib/netapi/cm.c ++++ b/source3/lib/netapi/cm.c +@@ -202,7 +202,7 @@ static NTSTATUS pipe_cm_connect(TALLOC_CTX *mem_ctx, + return NT_STATUS_NO_MEMORY; + } + +- status = cli_rpc_pipe_open_noauth(ipc->cli, &table->syntax_id, &p->pipe); ++ status = cli_rpc_pipe_open_noauth(ipc->cli, table, &p->pipe); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(p); + return status; +diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c +index 9f47f3b..324c8f3 100644 +--- a/source3/libnet/libnet_join.c ++++ b/source3/libnet/libnet_join.c +@@ -749,7 +749,7 @@ static NTSTATUS libnet_join_lookup_dc_rpc(TALLOC_CTX *mem_ctx, + goto done; + } + +- status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc.syntax_id, ++ status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc, + &pipe_hnd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Error connecting to LSA pipe. Error was %s\n", +@@ -819,7 +819,7 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, + fstring trust_passwd; + NTSTATUS status; + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, + &pipe_hnd); + if (!NT_STATUS_IS_OK(status)) { + return status; +@@ -908,7 +908,7 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx, + + /* Open the domain */ + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr, + &pipe_hnd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Error connecting to SAM pipe. Error was %s\n", +@@ -1377,7 +1377,7 @@ static NTSTATUS libnet_join_unjoindomain_rpc(TALLOC_CTX *mem_ctx, + + /* Open the domain */ + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr, + &pipe_hnd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Error connecting to SAM pipe. Error was %s\n", +diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c +index 87e10d8..3a07f11 100644 +--- a/source3/libsmb/libsmb_dir.c ++++ b/source3/libsmb/libsmb_dir.c +@@ -277,7 +277,7 @@ net_share_enum_rpc(struct cli_state *cli, + struct dcerpc_binding_handle *b; + + /* Open the server service pipe */ +- nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id, ++ nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc, + &pipe_hnd); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(1, ("net_share_enum_rpc pipe open fail!\n")); +diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c +index d4254da..dff0062 100644 +--- a/source3/libsmb/libsmb_server.c ++++ b/source3/libsmb/libsmb_server.c +@@ -802,7 +802,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, + ipc_srv->cli = ipc_cli; + + nt_status = cli_rpc_pipe_open_noauth( +- ipc_srv->cli, &ndr_table_lsarpc.syntax_id, &pipe_hnd); ++ ipc_srv->cli, &ndr_table_lsarpc, &pipe_hnd); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(1, ("cli_nt_session_open fail!\n")); + errno = ENOTSUP; +diff --git a/source3/libsmb/passchange.c b/source3/libsmb/passchange.c +index 3933833..9736ada 100644 +--- a/source3/libsmb/passchange.c ++++ b/source3/libsmb/passchange.c +@@ -169,7 +169,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam + * way. + */ + result = cli_rpc_pipe_open_noauth( +- cli, &ndr_table_samr.syntax_id, &pipe_hnd); ++ cli, &ndr_table_samr, &pipe_hnd); + } + + if (!NT_STATUS_IS_OK(result)) { +@@ -230,7 +230,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam + 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, ++ result = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr, + &pipe_hnd); + + if ( NT_STATUS_IS_OK(result) && +diff --git a/source3/libsmb/trustdom_cache.c b/source3/libsmb/trustdom_cache.c +index 8789d30..dadc751 100644 +--- a/source3/libsmb/trustdom_cache.c ++++ b/source3/libsmb/trustdom_cache.c +@@ -289,7 +289,7 @@ static bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain, + + /* open the LSARPC_PIPE */ + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, + &lsa_pipe); + if (!NT_STATUS_IS_OK(status)) { + goto done; +diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c +index 0d039bc..6156ba0 100644 +--- a/source3/libsmb/trusts_util.c ++++ b/source3/libsmb/trusts_util.c +@@ -182,7 +182,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m + /* Shouldn't we open this with schannel ? JRA. */ + + nt_status = cli_rpc_pipe_open_noauth( +- cli, &ndr_table_netlogon.syntax_id, &netlogon_pipe); ++ cli, &ndr_table_netlogon, &netlogon_pipe); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", + dc_name, nt_errstr(nt_status))); +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 34cef32..1137abd 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -2948,11 +2948,11 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, + ****************************************************************************/ + + NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult) + { + return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP, +- interface, presult); ++ &table->syntax_id, presult); + } + + /**************************************************************************** +diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h +index 65bfbc8..9aae61a 100644 +--- a/source3/rpc_client/cli_pipe.h ++++ b/source3/rpc_client/cli_pipe.h +@@ -77,7 +77,7 @@ NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path, + struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c); + + NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult); + + NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, +diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c +index 784e63f..bc672ef 100644 +--- a/source3/rpc_client/cli_pipe_schannel.c ++++ b/source3/rpc_client/cli_pipe_schannel.c +@@ -217,7 +217,7 @@ NTSTATUS get_schannel_session_key(struct cli_state *cli, + struct rpc_pipe_client *netlogon_pipe = NULL; + NTSTATUS status; + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, + &netlogon_pipe); + if (!NT_STATUS_IS_OK(status)) { + return status; +diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c +index 335647b..c12cd05 100644 +--- a/source3/rpc_server/spoolss/srv_spoolss_nt.c ++++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c +@@ -2504,7 +2504,7 @@ static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, + * Now start the NT Domain stuff :-). + */ + +- ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe); ++ ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss, pp_pipe); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n", + remote_machine, nt_errstr(ret))); +diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c +index 5c499d4..fb011f8 100644 +--- a/source3/rpcclient/cmd_spoolss.c ++++ b/source3/rpcclient/cmd_spoolss.c +@@ -3453,7 +3453,7 @@ static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli, + if ( !NT_STATUS_IS_OK(nt_status) ) + return WERR_GENERAL_FAILURE; + +- nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id, ++ nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss, + &cli2); + if (!NT_STATUS_IS_OK(nt_status)) { + printf("failed to open spoolss pipe on server %s (%s)\n", +diff --git a/source3/rpcclient/cmd_test.c b/source3/rpcclient/cmd_test.c +index 591ae8c..367dc71 100644 +--- a/source3/rpcclient/cmd_test.c ++++ b/source3/rpcclient/cmd_test.c +@@ -36,14 +36,14 @@ static NTSTATUS cmd_testme(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, + d_printf("testme\n"); + + status = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(cli), +- &ndr_table_lsarpc.syntax_id, ++ &ndr_table_lsarpc, + &lsa_pipe); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(cli), +- &ndr_table_samr.syntax_id, ++ &ndr_table_samr, + &samr_pipe); + if (!NT_STATUS_IS_OK(status)) { + goto done; +diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c +index 6b6478e..e3b35bb 100644 +--- a/source3/rpcclient/rpcclient.c ++++ b/source3/rpcclient/rpcclient.c +@@ -167,7 +167,7 @@ static void fetch_machine_sid(struct cli_state *cli) + goto error; + } + +- result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, ++ result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, + &lsapipe); + if (!NT_STATUS_IS_OK(result)) { + fprintf(stderr, "could not initialise lsa pipe. Error was %s\n", nt_errstr(result) ); +diff --git a/source3/torture/test_async_echo.c b/source3/torture/test_async_echo.c +index 6df95dd..f21daa4 100644 +--- a/source3/torture/test_async_echo.c ++++ b/source3/torture/test_async_echo.c +@@ -82,7 +82,7 @@ bool run_async_echo(int dummy) + printf("torture_open_connection failed\n"); + goto fail; + } +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_rpcecho.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_rpcecho, + &p); + if (!NT_STATUS_IS_OK(status)) { + printf("Could not open echo pipe: %s\n", nt_errstr(status)); +diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c +index 5699943..89eebf3 100644 +--- a/source3/utils/net_ads.c ++++ b/source3/utils/net_ads.c +@@ -1957,7 +1957,7 @@ static int net_ads_printer_publish(struct net_context *c, int argc, const char * + SAFE_FREE(srv_cn_escaped); + SAFE_FREE(printername_escaped); + +- nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss.syntax_id, &pipe_hnd); ++ nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd); + if (!NT_STATUS_IS_OK(nt_status)) { + d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"), + servername); +diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c +index dab9fcd..69ff14d 100644 +--- a/source3/utils/net_rpc.c ++++ b/source3/utils/net_rpc.c +@@ -82,7 +82,7 @@ NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx, + union lsa_PolicyInformation *info = NULL; + struct dcerpc_binding_handle *b; + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, + &lsa_pipe); + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, _("Could not initialise lsa pipe\n")); +@@ -212,7 +212,7 @@ int run_rpc_command(struct net_context *c, + c->opt_password, &pipe_hnd); + } else { + nt_status = cli_rpc_pipe_open_noauth( +- cli, &table->syntax_id, ++ cli, table, + &pipe_hnd); + } + if (!NT_STATUS_IS_OK(nt_status)) { +@@ -348,7 +348,7 @@ static NTSTATUS rpc_oldjoin_internals(struct net_context *c, + NTSTATUS result; + enum netr_SchannelType sec_channel_type; + +- result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id, ++ result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, + &pipe_hnd); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. " +@@ -1966,7 +1966,7 @@ static NTSTATUS get_sid_from_name(struct cli_state *cli, + NTSTATUS status, result; + struct dcerpc_binding_handle *b; + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, + &pipe_hnd); + if (!NT_STATUS_IS_OK(status)) { + goto done; +@@ -2980,7 +2980,7 @@ static NTSTATUS rpc_list_alias_members(struct net_context *c, + } + + result = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(pipe_hnd), +- &ndr_table_lsarpc.syntax_id, ++ &ndr_table_lsarpc, + &lsa_pipe); + if (!NT_STATUS_IS_OK(result)) { + d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"), +@@ -6232,7 +6232,7 @@ static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c, + + /* Try netr_GetDcName */ + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, + &netr); + if (!NT_STATUS_IS_OK(status)) { + return status; +@@ -6379,7 +6379,7 @@ static int rpc_trustdom_establish(struct net_context *c, int argc, + * Call LsaOpenPolicy and LsaQueryInfo + */ + +- nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, ++ nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, + &pipe_hnd); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) )); +@@ -6656,7 +6656,7 @@ static int rpc_trustdom_vampire(struct net_context *c, int argc, + return -1; + }; + +- nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, ++ nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, + &pipe_hnd); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", +@@ -6834,7 +6834,7 @@ static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv) + return -1; + }; + +- nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, ++ nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, + &pipe_hnd); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", +@@ -6950,7 +6950,7 @@ static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv) + /* + * Open \PIPE\samr and get needed policy handles + */ +- nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id, ++ nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr, + &pipe_hnd); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status))); +diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c +index 4b43769..aabbe54 100644 +--- a/source3/utils/net_rpc_join.c ++++ b/source3/utils/net_rpc_join.c +@@ -245,7 +245,7 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) + + /* Fetch domain sid */ + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, + &pipe_hnd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n", +@@ -280,7 +280,7 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) + } + + /* Create domain user */ +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr, + &pipe_hnd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n", +@@ -456,7 +456,7 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) + + /* Now check the whole process from top-to-bottom */ + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, + &pipe_hnd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Error connecting to NETLOGON pipe. Error was %s\n", +diff --git a/source3/utils/net_rpc_shell.c b/source3/utils/net_rpc_shell.c +index 6086066..120cfa6 100644 +--- a/source3/utils/net_rpc_shell.c ++++ b/source3/utils/net_rpc_shell.c +@@ -85,7 +85,7 @@ static NTSTATUS net_sh_run(struct net_context *c, + return NT_STATUS_NO_MEMORY; + } + +- status = cli_rpc_pipe_open_noauth(ctx->cli, &cmd->table->syntax_id, ++ status = cli_rpc_pipe_open_noauth(ctx->cli, cmd->table, + &pipe_hnd); + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, _("Could not open pipe: %s\n"), +diff --git a/source3/utils/net_rpc_trust.c b/source3/utils/net_rpc_trust.c +index 9060700..5e58103 100644 +--- a/source3/utils/net_rpc_trust.c ++++ b/source3/utils/net_rpc_trust.c +@@ -210,7 +210,7 @@ static NTSTATUS connect_and_get_info(TALLOC_CTX *mem_ctx, + return status; + } + +- status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc.syntax_id, pipe_hnd); ++ status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc, pipe_hnd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Failed to initialise lsa pipe with error [%s]\n", + nt_errstr(status))); +diff --git a/source3/utils/net_util.c b/source3/utils/net_util.c +index a4282ec..13a0ef1 100644 +--- a/source3/utils/net_util.c ++++ b/source3/utils/net_util.c +@@ -45,7 +45,7 @@ NTSTATUS net_rpc_lookup_name(struct net_context *c, + + ZERO_STRUCT(pol); + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, + &lsa_pipe); + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, _("Could not initialise lsa pipe\n")); +@@ -256,7 +256,7 @@ NTSTATUS connect_dst_pipe(struct net_context *c, struct cli_state **cli_dst, + return nt_status; + } + +- nt_status = cli_rpc_pipe_open_noauth(cli_tmp, &table->syntax_id, ++ nt_status = cli_rpc_pipe_open_noauth(cli_tmp, table, + &pipe_hnd); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("couldn't not initialize pipe\n")); +@@ -571,7 +571,7 @@ static NTSTATUS net_scan_dc_noad(struct net_context *c, + ZERO_STRUCTP(dc_info); + ZERO_STRUCT(pol); + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, + &pipe_hnd); + if (!NT_STATUS_IS_OK(status)) { + return status; +@@ -634,7 +634,7 @@ NTSTATUS net_scan_dc(struct net_context *c, + + ZERO_STRUCTP(dc_info); + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_dssetup.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_dssetup, + &dssetup_pipe); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10,("net_scan_dc: failed to open dssetup pipe with %s, " +diff --git a/source3/utils/netlookup.c b/source3/utils/netlookup.c +index b66c34e..56d3bfe 100644 +--- a/source3/utils/netlookup.c ++++ b/source3/utils/netlookup.c +@@ -122,7 +122,7 @@ static struct con_struct *create_cs(struct net_context *c, + } + + nt_status = cli_rpc_pipe_open_noauth(cs->cli, +- &ndr_table_lsarpc.syntax_id, ++ &ndr_table_lsarpc, + &cs->lsapipe); + + if (!NT_STATUS_IS_OK(nt_status)) { +diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c +index 23a1192..f092839 100644 +--- a/source3/utils/smbcacls.c ++++ b/source3/utils/smbcacls.c +@@ -96,7 +96,7 @@ static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli, + goto tcon_fail; + } + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, + &p); + if (!NT_STATUS_IS_OK(status)) { + goto fail; +@@ -146,7 +146,7 @@ static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli, + goto tcon_fail; + } + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, + &p); + if (!NT_STATUS_IS_OK(status)) { + goto fail; +@@ -187,14 +187,13 @@ static NTSTATUS cli_lsa_lookup_domain_sid(struct cli_state *cli, + struct policy_handle handle; + NTSTATUS status, result; + TALLOC_CTX *frame = talloc_stackframe(); +- const struct ndr_syntax_id *lsarpc_syntax = &ndr_table_lsarpc.syntax_id; + + status = cli_tree_connect(cli, "IPC$", "?????", "", 0); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + +- status = cli_rpc_pipe_open_noauth(cli, lsarpc_syntax, &rpc_pipe); ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, &rpc_pipe); + if (!NT_STATUS_IS_OK(status)) { + goto tdis; + } +diff --git a/source3/utils/smbcquotas.c b/source3/utils/smbcquotas.c +index bf1f95c..2791b93 100644 +--- a/source3/utils/smbcquotas.c ++++ b/source3/utils/smbcquotas.c +@@ -58,7 +58,7 @@ static bool cli_open_policy_hnd(void) + NTSTATUS ret; + cli_ipc = connect_one("IPC$"); + ret = cli_rpc_pipe_open_noauth(cli_ipc, +- &ndr_table_lsarpc.syntax_id, ++ &ndr_table_lsarpc, + &global_pipe_hnd); + if (!NT_STATUS_IS_OK(ret)) { + return False; +diff --git a/source3/utils/smbtree.c b/source3/utils/smbtree.c +index 40b1f09..5c07b12 100644 +--- a/source3/utils/smbtree.c ++++ b/source3/utils/smbtree.c +@@ -177,7 +177,7 @@ static bool get_rpc_shares(struct cli_state *cli, + return False; + } + +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id, ++ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc, + &pipe_hnd); + + if (!NT_STATUS_IS_OK(status)) { +diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c +index f17fc68..facef64 100644 +--- a/source3/winbindd/winbindd_cm.c ++++ b/source3/winbindd/winbindd_cm.c +@@ -2078,7 +2078,7 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) + DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name )); + + status = cli_rpc_pipe_open_noauth(domain->conn.cli, +- &ndr_table_dssetup.syntax_id, ++ &ndr_table_dssetup, + &cli); + + if (!NT_STATUS_IS_OK(status)) { +@@ -2129,7 +2129,7 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) + + no_dssetup: + status = cli_rpc_pipe_open_noauth(domain->conn.cli, +- &ndr_table_lsarpc.syntax_id, &cli); ++ &ndr_table_lsarpc, &cli); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to " +@@ -2447,7 +2447,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + anonymous: + + /* Finally fall back to anonymous. */ +- status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id, ++ status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr, + &conn->samr_pipe); + + if (!NT_STATUS_IS_OK(status)) { +@@ -2674,7 +2674,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + anonymous: + + result = cli_rpc_pipe_open_noauth(conn->cli, +- &ndr_table_lsarpc.syntax_id, ++ &ndr_table_lsarpc, + &conn->lsa_pipe); + if (!NT_STATUS_IS_OK(result)) { + result = NT_STATUS_PIPE_NOT_AVAILABLE; +@@ -2765,7 +2765,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, + TALLOC_FREE(conn->netlogon_pipe); + + result = cli_rpc_pipe_open_noauth(conn->cli, +- &ndr_table_netlogon.syntax_id, ++ &ndr_table_netlogon, + &netlogon_pipe); + if (!NT_STATUS_IS_OK(result)) { + return result; +-- +1.9.3 + + +From fce35e003f655b3564ee4df5ebfe7f3e6ff6d188 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 24 May 2013 13:33:03 +0200 +Subject: [PATCH 027/249] s3-rpc_cli: pass down ndr_interface_table to + cli_rpc_pipe_open_noauth_transport(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 9aa99c3cfb0ff7a290dd4df472a4ff30d0efcb76) +--- + source3/rpc_client/cli_pipe.c | 13 +++++++------ + source3/rpc_client/cli_pipe.h | 2 +- + source3/rpcclient/rpcclient.c | 2 +- + 3 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 1137abd..4523ab7 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -2865,14 +2865,14 @@ static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli, + + NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, + enum dcerpc_transport_t transport, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult) + { + struct rpc_pipe_client *result; + struct pipe_auth_data *auth; + NTSTATUS status; + +- status = cli_rpc_pipe_open(cli, transport, interface, &result); ++ status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result); + if (!NT_STATUS_IS_OK(status)) { + return status; + } +@@ -2921,7 +2921,7 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, + status = rpc_pipe_bind(result, auth); + if (!NT_STATUS_IS_OK(status)) { + int lvl = 0; +- if (ndr_syntax_id_equal(interface, ++ if (ndr_syntax_id_equal(&table->syntax_id, + &ndr_table_dssetup.syntax_id)) { + /* non AD domains just don't have this pipe, avoid + * level 0 statement in that case - gd */ +@@ -2929,7 +2929,8 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, + } + DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe " + "%s failed with error %s\n", +- get_pipe_name_from_syntax(talloc_tos(), interface), ++ get_pipe_name_from_syntax(talloc_tos(), ++ &table->syntax_id), + nt_errstr(status) )); + TALLOC_FREE(result); + return status; +@@ -2937,7 +2938,7 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, + + DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine " + "%s and bound anonymously.\n", +- get_pipe_name_from_syntax(talloc_tos(), interface), ++ get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), + result->desthost)); + + *presult = result; +@@ -2952,7 +2953,7 @@ NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli, + struct rpc_pipe_client **presult) + { + return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP, +- &table->syntax_id, presult); ++ table, presult); + } + + /**************************************************************************** +diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h +index 9aae61a..f37f8a9 100644 +--- a/source3/rpc_client/cli_pipe.h ++++ b/source3/rpc_client/cli_pipe.h +@@ -82,7 +82,7 @@ NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli, + + NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, + enum dcerpc_transport_t transport, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult); + + NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli, +diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c +index e3b35bb..c23ff2d 100644 +--- a/source3/rpcclient/rpcclient.c ++++ b/source3/rpcclient/rpcclient.c +@@ -690,7 +690,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, + case DCERPC_AUTH_TYPE_NONE: + ntresult = cli_rpc_pipe_open_noauth_transport( + cli, default_transport, +- &cmd_entry->table->syntax_id, ++ cmd_entry->table, + &cmd_entry->rpc_pipe); + break; + case DCERPC_AUTH_TYPE_SPNEGO: +-- +1.9.3 + + +From 0d85042853b635486912688102253b2f358b5056 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 24 May 2013 13:38:01 +0200 +Subject: [PATCH 028/249] s3-rpc_cli: pass down ndr_interface_table to + cli_rpc_pipe_open(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 34cc4b409558f229fba24f59e81ef9100a851d24) +--- + source3/rpc_client/cli_pipe.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 4523ab7..4dc7345 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -2843,7 +2843,7 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli, + + static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli, + enum dcerpc_transport_t transport, +- const struct ndr_syntax_id *interface, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult) + { + switch (transport) { +@@ -2851,9 +2851,9 @@ static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli, + return rpc_pipe_open_tcp(NULL, + smbXcli_conn_remote_name(cli->conn), + smbXcli_conn_remote_sockaddr(cli->conn), +- interface, presult); ++ &table->syntax_id, presult); + case NCACN_NP: +- return rpc_pipe_open_np(cli, interface, presult); ++ return rpc_pipe_open_np(cli, &table->syntax_id, presult); + default: + return NT_STATUS_NOT_IMPLEMENTED; + } +@@ -2872,7 +2872,7 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, + struct pipe_auth_data *auth; + NTSTATUS status; + +- status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result); ++ status = cli_rpc_pipe_open(cli, transport, table, &result); + if (!NT_STATUS_IS_OK(status)) { + return status; + } +@@ -2977,7 +2977,7 @@ NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli, + + NTSTATUS status; + +- status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result); ++ status = cli_rpc_pipe_open(cli, transport, table, &result); + if (!NT_STATUS_IS_OK(status)) { + return status; + } +@@ -3034,7 +3034,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + struct pipe_auth_data *auth; + NTSTATUS status; + +- status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result); ++ status = cli_rpc_pipe_open(cli, transport, table, &result); + if (!NT_STATUS_IS_OK(status)) { + return status; + } +@@ -3104,7 +3104,7 @@ NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli, + return NT_STATUS_INVALID_PARAMETER; + } + +- status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result); ++ status = cli_rpc_pipe_open(cli, transport, table, &result); + if (!NT_STATUS_IS_OK(status)) { + return status; + } +-- +1.9.3 + + +From d5e312185a7adc8429f8caba29a9808ab7954a27 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 24 May 2013 13:40:45 +0200 +Subject: [PATCH 029/249] s3-rpc_cli: pass down ndr_interface_table to + rpc_pipe_open_np(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 8cd3a060514ddcc178c938100edfb0b177c00c8c) +--- + source3/rpc_client/cli_pipe.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 4dc7345..0347d76 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -2775,7 +2775,7 @@ static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_r + ****************************************************************************/ + + static NTSTATUS rpc_pipe_open_np(struct cli_state *cli, +- const struct ndr_syntax_id *abstract_syntax, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult) + { + struct rpc_pipe_client *result; +@@ -2793,7 +2793,7 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli, + return NT_STATUS_NO_MEMORY; + } + +- result->abstract_syntax = *abstract_syntax; ++ result->abstract_syntax = table->syntax_id; + result->transfer_syntax = ndr_transfer_syntax_ndr; + result->desthost = talloc_strdup(result, smbXcli_conn_remote_name(cli->conn)); + result->srv_name_slash = talloc_asprintf_strupper_m( +@@ -2807,7 +2807,7 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli, + return NT_STATUS_NO_MEMORY; + } + +- status = rpc_transport_np_init(result, cli, abstract_syntax, ++ status = rpc_transport_np_init(result, cli, &table->syntax_id, + &result->transport); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(result); +@@ -2853,7 +2853,7 @@ static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli, + smbXcli_conn_remote_sockaddr(cli->conn), + &table->syntax_id, presult); + case NCACN_NP: +- return rpc_pipe_open_np(cli, &table->syntax_id, presult); ++ return rpc_pipe_open_np(cli, table, presult); + default: + return NT_STATUS_NOT_IMPLEMENTED; + } +-- +1.9.3 + + +From f1fa7838cb933fd0d390a56d823272f8528eb63c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 24 May 2013 13:44:00 +0200 +Subject: [PATCH 030/249] s3-rpc_cli: pass down ndr_interface_table to + rpc_pipe_open_tcp(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 5c5cff0a722a0925ae75ea7aa11ede0d82d5b92d) +--- + source3/rpc_client/cli_pipe.c | 8 ++++---- + source3/rpc_client/cli_pipe.h | 2 +- + source3/torture/rpc_open_tcp.c | 2 +- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 0347d76..46adf69 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -2663,19 +2663,19 @@ done: + */ + NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host, + const struct sockaddr_storage *addr, +- const struct ndr_syntax_id *abstract_syntax, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult) + { + NTSTATUS status; + uint16_t port = 0; + +- status = rpc_pipe_get_tcp_port(host, addr, abstract_syntax, &port); ++ status = rpc_pipe_get_tcp_port(host, addr, &table->syntax_id, &port); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port, +- abstract_syntax, presult); ++ &table->syntax_id, presult); + } + + /******************************************************************** +@@ -2851,7 +2851,7 @@ static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli, + return rpc_pipe_open_tcp(NULL, + smbXcli_conn_remote_name(cli->conn), + smbXcli_conn_remote_sockaddr(cli->conn), +- &table->syntax_id, presult); ++ table, presult); + case NCACN_NP: + return rpc_pipe_open_np(cli, table, presult); + default: +diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h +index f37f8a9..6fcc587 100644 +--- a/source3/rpc_client/cli_pipe.h ++++ b/source3/rpc_client/cli_pipe.h +@@ -67,7 +67,7 @@ NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, + NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, + const char *host, + const struct sockaddr_storage *ss_addr, +- const struct ndr_syntax_id *abstract_syntax, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult); + + NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path, +diff --git a/source3/torture/rpc_open_tcp.c b/source3/torture/rpc_open_tcp.c +index d29f4cf..cd27b5f 100644 +--- a/source3/torture/rpc_open_tcp.c ++++ b/source3/torture/rpc_open_tcp.c +@@ -95,7 +95,7 @@ int main(int argc, const char **argv) + } + + status = rpc_pipe_open_tcp(mem_ctx, argv[2], NULL, +- &((*table)->syntax_id), ++ *table, + &rpc_pipe); + if (!NT_STATUS_IS_OK(status)) { + d_printf("ERROR calling rpc_pipe_open_tcp(): %s\n", +-- +1.9.3 + + +From 67c01c15af1bbb98916e75f7cad61edcc13c2e2f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 24 May 2013 13:46:07 +0200 +Subject: [PATCH 031/249] s3-rpc_cli: pass down ndr_interface_table to + rpc_pipe_get_tcp_port(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 0ff8c2d508949f732716e24047694cecf38597df) +--- + source3/rpc_client/cli_pipe.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 46adf69..15e77db 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -2518,7 +2518,7 @@ static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host, + */ + static NTSTATUS rpc_pipe_get_tcp_port(const char *host, + const struct sockaddr_storage *addr, +- const struct ndr_syntax_id *abstract_syntax, ++ const struct ndr_interface_table *table, + uint16_t *pport) + { + NTSTATUS status; +@@ -2541,7 +2541,7 @@ static NTSTATUS rpc_pipe_get_tcp_port(const char *host, + goto done; + } + +- if (ndr_syntax_id_equal(abstract_syntax, ++ if (ndr_syntax_id_equal(&table->syntax_id, + &ndr_table_epmapper.syntax_id)) { + *pport = 135; + return NT_STATUS_OK; +@@ -2576,7 +2576,7 @@ static NTSTATUS rpc_pipe_get_tcp_port(const char *host, + } + + map_binding->transport = NCACN_IP_TCP; +- map_binding->object = *abstract_syntax; ++ map_binding->object = table->syntax_id; + map_binding->host = host; /* needed? */ + map_binding->endpoint = "0"; /* correct? needed? */ + +@@ -2612,7 +2612,7 @@ static NTSTATUS rpc_pipe_get_tcp_port(const char *host, + status = dcerpc_epm_Map(epm_handle, + tmp_ctx, + discard_const_p(struct GUID, +- &(abstract_syntax->uuid)), ++ &(table->syntax_id.uuid)), + map_tower, + entry_handle, + max_towers, +@@ -2669,7 +2669,7 @@ NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host, + NTSTATUS status; + uint16_t port = 0; + +- status = rpc_pipe_get_tcp_port(host, addr, &table->syntax_id, &port); ++ status = rpc_pipe_get_tcp_port(host, addr, table, &port); + if (!NT_STATUS_IS_OK(status)) { + return status; + } +-- +1.9.3 + + +From a032ff8c89e479792947af4315ed6eb59a69f8f5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 24 May 2013 13:47:16 +0200 +Subject: [PATCH 032/249] s3-rpc_cli: pass down ndr_interface_table to + rpc_pipe_open_tcp_port(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 7bdcfcb37c5b96ee6aa0cecffd89c6d17291fe62) +--- + source3/rpc_client/cli_pipe.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 15e77db..1b2955f 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -2447,7 +2447,7 @@ NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain, + static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host, + const struct sockaddr_storage *ss_addr, + uint16_t port, +- const struct ndr_syntax_id *abstract_syntax, ++ const struct ndr_interface_table *table, + struct rpc_pipe_client **presult) + { + struct rpc_pipe_client *result; +@@ -2460,7 +2460,7 @@ static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host, + return NT_STATUS_NO_MEMORY; + } + +- result->abstract_syntax = *abstract_syntax; ++ result->abstract_syntax = table->syntax_id; + result->transfer_syntax = ndr_transfer_syntax_ndr; + + result->desthost = talloc_strdup(result, host); +@@ -2549,7 +2549,7 @@ static NTSTATUS rpc_pipe_get_tcp_port(const char *host, + + /* open the connection to the endpoint mapper */ + status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135, +- &ndr_table_epmapper.syntax_id, ++ &ndr_table_epmapper, + &epm_pipe); + + if (!NT_STATUS_IS_OK(status)) { +@@ -2675,7 +2675,7 @@ NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host, + } + + return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port, +- &table->syntax_id, presult); ++ table, presult); + } + + /******************************************************************** +-- +1.9.3 + + +From 0b4ae5ec146e35c364f01c033d6c22efb99b7314 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 24 May 2013 13:52:05 +0200 +Subject: [PATCH 033/249] s3-rpc_cli: pass down ndr_interface_table to + rpc_transport_np_init(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit c41b6e5c5e7fcdbd98c1eb2bea08378b47d343d4) +--- + source3/rpc_client/cli_pipe.c | 2 +- + source3/rpc_client/rpc_transport.h | 2 +- + source3/rpc_client/rpc_transport_np.c | 4 ++-- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 1b2955f..1fa8d91 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -2807,7 +2807,7 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli, + return NT_STATUS_NO_MEMORY; + } + +- status = rpc_transport_np_init(result, cli, &table->syntax_id, ++ status = rpc_transport_np_init(result, cli, table, + &result->transport); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(result); +diff --git a/source3/rpc_client/rpc_transport.h b/source3/rpc_client/rpc_transport.h +index bc115dd..2b4a323 100644 +--- a/source3/rpc_client/rpc_transport.h ++++ b/source3/rpc_client/rpc_transport.h +@@ -89,7 +89,7 @@ NTSTATUS rpc_transport_np_init_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct rpc_cli_transport **presult); + NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli, +- const struct ndr_syntax_id *abstract_syntax, ++ const struct ndr_interface_table *table, + struct rpc_cli_transport **presult); + + /* The following definitions come from rpc_client/rpc_transport_sock.c */ +diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c +index f0696ad..7bd1ca3 100644 +--- a/source3/rpc_client/rpc_transport_np.c ++++ b/source3/rpc_client/rpc_transport_np.c +@@ -152,7 +152,7 @@ NTSTATUS rpc_transport_np_init_recv(struct tevent_req *req, + } + + NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli, +- const struct ndr_syntax_id *abstract_syntax, ++ const struct ndr_interface_table *table, + struct rpc_cli_transport **presult) + { + TALLOC_CTX *frame = talloc_stackframe(); +@@ -166,7 +166,7 @@ NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli, + goto fail; + } + +- req = rpc_transport_np_init_send(frame, ev, cli, abstract_syntax); ++ req = rpc_transport_np_init_send(frame, ev, cli, &table->syntax_id); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; +-- +1.9.3 + + +From 739d05d91f23c4c6e17078c84192f30911cbdfcd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 24 May 2013 13:56:53 +0200 +Subject: [PATCH 034/249] s3-rpc_cli: pass down ndr_interface_table to + rpc_transport_np_init_send(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit b19e7e6638a5dd53e3c6e6701f78bf31184ed493) +--- + source3/rpc_client/rpc_transport.h | 2 +- + source3/rpc_client/rpc_transport_np.c | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/source3/rpc_client/rpc_transport.h b/source3/rpc_client/rpc_transport.h +index 2b4a323..72e7609 100644 +--- a/source3/rpc_client/rpc_transport.h ++++ b/source3/rpc_client/rpc_transport.h +@@ -84,7 +84,7 @@ struct cli_state; + struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli, +- const struct ndr_syntax_id *abstract_syntax); ++ const struct ndr_interface_table *table); + NTSTATUS rpc_transport_np_init_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct rpc_cli_transport **presult); +diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c +index 7bd1ca3..c0f313e 100644 +--- a/source3/rpc_client/rpc_transport_np.c ++++ b/source3/rpc_client/rpc_transport_np.c +@@ -40,7 +40,7 @@ static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq); + struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli, +- const struct ndr_syntax_id *abstract_syntax) ++ const struct ndr_interface_table *table) + { + struct tevent_req *req; + struct rpc_transport_np_init_state *state; +@@ -55,7 +55,7 @@ struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, + state->ev = ev; + state->cli = cli; + state->abs_timeout = timeval_current_ofs_msec(cli->timeout); +- state->pipe_name = get_pipe_name_from_syntax(state, abstract_syntax); ++ state->pipe_name = get_pipe_name_from_syntax(state, &table->syntax_id); + if (tevent_req_nomem(state->pipe_name, req)) { + return tevent_req_post(req, ev); + } +@@ -166,7 +166,7 @@ NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli, + goto fail; + } + +- req = rpc_transport_np_init_send(frame, ev, cli, &table->syntax_id); ++ req = rpc_transport_np_init_send(frame, ev, cli, table); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; +-- +1.9.3 + + +From c5529ee9045c44114ab1716b05d3408baa1b4e42 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 24 Sep 2008 11:04:42 +0200 +Subject: [PATCH 035/249] s3: libnet_join: add admin_domain. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit c11a79c5a054e862f61c97093fa2ce5e5040f111) +--- + source3/librpc/idl/libnet_join.idl | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/source3/librpc/idl/libnet_join.idl b/source3/librpc/idl/libnet_join.idl +index 4f28bb6..ac0a350 100644 +--- a/source3/librpc/idl/libnet_join.idl ++++ b/source3/librpc/idl/libnet_join.idl +@@ -21,6 +21,7 @@ interface libnetjoin + [in,ref] string *domain_name, + [in] string account_ou, + [in] string admin_account, ++ [in] string admin_domain, + [in,noprint] string admin_password, + [in] string machine_password, + [in] wkssvc_joinflags join_flags, +@@ -51,6 +52,7 @@ interface libnetjoin + [in] string domain_name, + [in] string account_ou, + [in] string admin_account, ++ [in] string admin_domain, + [in,noprint] string admin_password, + [in] string machine_password, + [in] wkssvc_joinflags unjoin_flags, +-- +1.9.3 + + +From a0d8f42ac44d279ae7bc599792cd1d564925dcbf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 24 Sep 2008 11:05:37 +0200 +Subject: [PATCH 036/249] s3: libnet_join: use admin_domain in libnetjoin. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit cc0cbd4fdc6e07538d67cc41ca07bad1eaebf493) +--- + source3/libnet/libnet_join.c | 27 ++++++++++++++++++++++++++- + 1 file changed, 26 insertions(+), 1 deletion(-) + +diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c +index 324c8f3..2253079 100644 +--- a/source3/libnet/libnet_join.c ++++ b/source3/libnet/libnet_join.c +@@ -701,6 +701,7 @@ static bool libnet_join_joindomain_store_secrets(TALLOC_CTX *mem_ctx, + + static NTSTATUS libnet_join_connect_dc_ipc(const char *dc, + const char *user, ++ const char *domain, + const char *pass, + bool use_kerberos, + struct cli_state **cli) +@@ -720,7 +721,7 @@ static NTSTATUS libnet_join_connect_dc_ipc(const char *dc, + NULL, 0, + "IPC$", "IPC", + user, +- NULL, ++ domain, + pass, + flags, + SMB_SIGNING_DEFAULT); +@@ -742,6 +743,7 @@ static NTSTATUS libnet_join_lookup_dc_rpc(TALLOC_CTX *mem_ctx, + + status = libnet_join_connect_dc_ipc(r->in.dc_name, + r->in.admin_account, ++ r->in.admin_domain, + r->in.admin_password, + r->in.use_kerberos, + cli); +@@ -1368,6 +1370,7 @@ static NTSTATUS libnet_join_unjoindomain_rpc(TALLOC_CTX *mem_ctx, + + status = libnet_join_connect_dc_ipc(r->in.dc_name, + r->in.admin_account, ++ r->in.admin_domain, + r->in.admin_password, + r->in.use_kerberos, + &cli); +@@ -1755,6 +1758,17 @@ static WERROR libnet_join_pre_processing(TALLOC_CTX *mem_ctx, + return WERR_SETUP_DOMAIN_CONTROLLER; + } + ++ if (!r->in.admin_domain) { ++ char *admin_domain = NULL; ++ char *admin_account = NULL; ++ split_domain_user(mem_ctx, ++ r->in.admin_account, ++ &admin_domain, ++ &admin_account); ++ r->in.admin_domain = admin_domain; ++ r->in.admin_account = admin_account; ++ } ++ + if (!secrets_init()) { + libnet_join_set_error_string(mem_ctx, r, + "Unable to open secrets database"); +@@ -2316,6 +2330,17 @@ static WERROR libnet_unjoin_pre_processing(TALLOC_CTX *mem_ctx, + return WERR_SETUP_DOMAIN_CONTROLLER; + } + ++ if (!r->in.admin_domain) { ++ char *admin_domain = NULL; ++ char *admin_account = NULL; ++ split_domain_user(mem_ctx, ++ r->in.admin_account, ++ &admin_domain, ++ &admin_account); ++ r->in.admin_domain = admin_domain; ++ r->in.admin_account = admin_account; ++ } ++ + if (!secrets_init()) { + libnet_unjoin_set_error_string(mem_ctx, r, + "Unable to open secrets database"); +-- +1.9.3 + + +From 46f8496292a12b7acdd045d126b61fa9d8afee74 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Thu, 6 Nov 2008 11:40:03 +0100 +Subject: [PATCH 037/249] s3-libnetjoin: add machine_name length check. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit c4d6d75cf48aed7b17728e283581366143fa4233) +--- + source3/libnet/libnet_join.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c +index 2253079..b731d9b 100644 +--- a/source3/libnet/libnet_join.c ++++ b/source3/libnet/libnet_join.c +@@ -1746,6 +1746,15 @@ static WERROR libnet_join_pre_processing(TALLOC_CTX *mem_ctx, + return WERR_INVALID_PARAM; + } + ++ if (strlen(r->in.machine_name) > 15) { ++ libnet_join_set_error_string(mem_ctx, r, ++ "Our netbios name can be at most 15 chars long, " ++ "\"%s\" is %u chars long\n", ++ r->in.machine_name, ++ (unsigned int)strlen(r->in.machine_name)); ++ return WERR_INVALID_PARAM; ++ } ++ + if (!libnet_parse_domain_dc(mem_ctx, r->in.domain_name, + &r->in.domain_name, + &r->in.dc_name)) { +-- +1.9.3 + + +From a60cf7ddd4e2d41d92cdd35ab05f2d6a30b055c9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Thu, 6 Nov 2008 13:37:45 +0100 +Subject: [PATCH 038/249] s3-libnetjoin: move "net rpc oldjoin" to use + libnetjoin. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit d398a12f7907866189c1b253ca6a40e5454f42a1) +--- + source3/utils/net_rpc.c | 182 ++++++++++++++++++++++-------------------------- + 1 file changed, 84 insertions(+), 98 deletions(-) + +diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c +index 69ff14d..720e9d2 100644 +--- a/source3/utils/net_rpc.c ++++ b/source3/utils/net_rpc.c +@@ -37,6 +37,8 @@ + #include "secrets.h" + #include "lib/netapi/netapi.h" + #include "lib/netapi/netapi_net.h" ++#include "librpc/gen_ndr/libnet_join.h" ++#include "libnet/libnet_join.h" + #include "rpc_client/init_lsa.h" + #include "../libcli/security/security.h" + #include "libsmb/libsmb.h" +@@ -314,48 +316,46 @@ int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv) + } + + /** +- * Join a domain, the old way. ++ * Join a domain, the old way. This function exists to allow ++ * the message to be displayed when oldjoin was explicitly ++ * requested, but not when it was implied by "net rpc join". + * + * This uses 'machinename' as the inital password, and changes it. + * + * The password should be created with 'server manager' or equiv first. + * +- * 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_oldjoin_internals(struct net_context *c, +- const struct 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 net_rpc_oldjoin(struct net_context *c, int argc, const char **argv) + { ++ struct libnet_JoinCtx *r = NULL; ++ TALLOC_CTX *mem_ctx; ++ WERROR werr; ++ const char *domain = lp_workgroup(); /* FIXME */ ++ bool modify_config = lp_config_backend_is_registry(); ++ enum netr_SchannelType sec_chan_type; ++ char *pw = NULL; + +- fstring trust_passwd; +- unsigned char orig_trust_passwd_hash[16]; +- NTSTATUS result; +- enum netr_SchannelType sec_channel_type; ++ if (c->display_usage) { ++ d_printf("Usage:\n" ++ "net rpc oldjoin\n" ++ " Join a domain the old way\n"); ++ return 0; ++ } + +- result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, +- &pipe_hnd); +- if (!NT_STATUS_IS_OK(result)) { +- DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. " +- "error was %s\n", +- smbXcli_conn_remote_name(cli->conn), +- nt_errstr(result) )); +- return result; ++ mem_ctx = talloc_init("net_rpc_oldjoin"); ++ if (!mem_ctx) { ++ return -1; ++ } ++ ++ werr = libnet_init_JoinCtx(mem_ctx, &r); ++ if (!W_ERROR_IS_OK(werr)) { ++ goto fail; + } + + /* +@@ -363,92 +363,78 @@ static NTSTATUS rpc_oldjoin_internals(struct net_context *c, + a BDC, the server must agree that we are a BDC. + */ + if (argc >= 0) { +- sec_channel_type = get_sec_channel_type(argv[0]); ++ sec_chan_type = get_sec_channel_type(argv[0]); + } else { +- sec_channel_type = get_sec_channel_type(NULL); ++ sec_chan_type = get_sec_channel_type(NULL); + } + +- fstrcpy(trust_passwd, lp_netbios_name()); +- if (!strlower_m(trust_passwd)) { +- return NT_STATUS_UNSUCCESSFUL; ++ if (!c->msg_ctx) { ++ d_fprintf(stderr, _("Could not initialise message context. " ++ "Try running as root\n")); ++ werr = WERR_ACCESS_DENIED; ++ goto fail; + } + +- /* +- * Machine names can be 15 characters, but the max length on +- * a password is 14. --jerry +- */ +- +- trust_passwd[14] = '\0'; +- +- E_md4hash(trust_passwd, orig_trust_passwd_hash); +- +- result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup, +- lp_netbios_name(), +- orig_trust_passwd_hash, +- sec_channel_type); +- +- if (NT_STATUS_IS_OK(result)) +- printf(_("Joined domain %s.\n"), c->opt_target_workgroup); ++ pw = talloc_strndup(r, lp_netbios_name(), 14); ++ if (pw == NULL) { ++ werr = WERR_NOMEM; ++ goto fail; ++ } + ++ r->in.msg_ctx = c->msg_ctx; ++ r->in.domain_name = domain; ++ r->in.secure_channel_type = sec_chan_type; ++ r->in.dc_name = c->opt_host; ++ r->in.admin_account = ""; ++ r->in.admin_password = strlower_talloc(r, pw); ++ if (r->in.admin_password == NULL) { ++ werr = WERR_NOMEM; ++ goto fail; ++ } ++ r->in.debug = true; ++ r->in.modify_config = modify_config; ++ r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE | ++ WKSSVC_JOIN_FLAGS_JOIN_UNSECURE | ++ WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED; + +- if (!secrets_store_domain_sid(c->opt_target_workgroup, domain_sid)) { +- DEBUG(0, ("error storing domain sid for %s\n", c->opt_target_workgroup)); +- result = NT_STATUS_UNSUCCESSFUL; ++ werr = libnet_Join(mem_ctx, r); ++ if (!W_ERROR_IS_OK(werr)) { ++ goto fail; + } + +- return result; +-} ++ /* Check the short name of the domain */ + +-/** +- * Join a domain, the old way. +- * +- * @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). +- **/ ++ if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) { ++ d_printf("The workgroup in %s does not match the short\n", get_dyn_CONFIGFILE()); ++ d_printf("domain name obtained from the server.\n"); ++ d_printf("Using the name [%s] from the server.\n", r->out.netbios_domain_name); ++ d_printf("You should set \"workgroup = %s\" in %s.\n", ++ r->out.netbios_domain_name, get_dyn_CONFIGFILE()); ++ } + +-static int net_rpc_perform_oldjoin(struct net_context *c, int argc, const char **argv) +-{ +- return run_rpc_command(c, NULL, &ndr_table_netlogon, +- NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, +- rpc_oldjoin_internals, +- argc, argv); +-} ++ d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name); + +-/** +- * Join a domain, the old way. This function exists to allow +- * the message to be displayed when oldjoin was explicitly +- * requested, but not when it was implied by "net rpc join". +- * +- * @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). +- **/ ++ if (r->out.dns_domain_name) { ++ d_printf("Joined '%s' to realm '%s'\n", r->in.machine_name, ++ r->out.dns_domain_name); ++ } else { ++ d_printf("Joined '%s' to domain '%s'\n", r->in.machine_name, ++ r->out.netbios_domain_name); ++ } + +-static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv) +-{ +- int rc = -1; ++ TALLOC_FREE(mem_ctx); + +- if (c->display_usage) { +- d_printf( "%s\n" +- "net rpc oldjoin\n" +- " %s\n", +- _("Usage:"), +- _("Join a domain the old way")); +- return 0; +- } ++ return 0; + +- rc = net_rpc_perform_oldjoin(c, argc, argv); ++fail: ++ /* issue an overall failure message at the end. */ ++ d_fprintf(stderr, _("Failed to join domain: %s\n"), ++ r && r->out.error_string ? r->out.error_string : ++ get_friendly_werror_msg(werr)); + +- if (rc) { +- d_fprintf(stderr, _("Failed to join domain\n")); +- } ++ TALLOC_FREE(mem_ctx); + +- return rc; ++ return -1; + } + + /** +@@ -492,7 +478,7 @@ int net_rpc_join(struct net_context *c, int argc, const char **argv) + return -1; + } + +- if ((net_rpc_perform_oldjoin(c, argc, argv) == 0)) ++ if ((net_rpc_oldjoin(c, argc, argv) == 0)) + return 0; + + return net_rpc_join_newstyle(c, argc, argv); +-- +1.9.3 + + +From 3185251186366984b5ec06322c75cfda71dccdbc Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 13 Jun 2013 19:12:27 +0200 +Subject: [PATCH 039/249] s3:libnet: let the caller truncate the pw in + libnet_join_joindomain_rpc_unsecure() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 1242ab0cb3bf575b695b39313604af9d0a7f1b3a) +--- + source3/libnet/libnet_join.c | 15 +-------------- + 1 file changed, 1 insertion(+), 14 deletions(-) + +diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c +index b731d9b..d8ec235 100644 +--- a/source3/libnet/libnet_join.c ++++ b/source3/libnet/libnet_join.c +@@ -818,7 +818,6 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, + struct rpc_pipe_client *pipe_hnd = NULL; + unsigned char orig_trust_passwd_hash[16]; + unsigned char new_trust_passwd_hash[16]; +- fstring trust_passwd; + NTSTATUS status; + + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, +@@ -837,19 +836,7 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, + E_md4hash(r->in.machine_password, new_trust_passwd_hash); + + /* according to WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED */ +- fstrcpy(trust_passwd, r->in.admin_password); +- if (!strlower_m(trust_passwd)) { +- return NT_STATUS_INVALID_PARAMETER; +- } +- +- /* +- * Machine names can be 15 characters, but the max length on +- * a password is 14. --jerry +- */ +- +- trust_passwd[14] = '\0'; +- +- E_md4hash(trust_passwd, orig_trust_passwd_hash); ++ E_md4hash(r->in.admin_password, orig_trust_passwd_hash); + + status = rpccli_netlogon_set_trust_password(pipe_hnd, mem_ctx, + r->in.machine_name, +-- +1.9.3 + + +From e1e15a73a9a5215866f6471c5e583457c516b47e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Tue, 3 Feb 2009 20:10:05 +0100 +Subject: [PATCH 040/249] s3-net: use libnetjoin for "net rpc testjoin". +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 9cfa6251600ddea0e821f2bd3fd359c28eb1b7f9) +--- + source3/utils/net_proto.h | 2 +- + source3/utils/net_rpc.c | 66 ++++++++++++++++++++++++++++++++++++++++++++ + source3/utils/net_rpc_join.c | 29 ------------------- + 3 files changed, 67 insertions(+), 30 deletions(-) + +diff --git a/source3/utils/net_proto.h b/source3/utils/net_proto.h +index 03fb312..d791708 100644 +--- a/source3/utils/net_proto.h ++++ b/source3/utils/net_proto.h +@@ -145,6 +145,7 @@ int run_rpc_command(struct net_context *c, + int argc, + const char **argv); + int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv); ++int net_rpc_testjoin(struct net_context *c, int argc, const char **argv); + int net_rpc_join(struct net_context *c, int argc, const char **argv); + NTSTATUS rpc_info_internals(struct net_context *c, + const struct dom_sid *domain_sid, +@@ -205,7 +206,6 @@ NTSTATUS net_rpc_join_ok(struct net_context *c, const char *domain, + const char *server, + const struct sockaddr_storage *server_ss); + int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv); +-int net_rpc_testjoin(struct net_context *c, int argc, const char **argv); + + /* The following definitions come from utils/net_rpc_printer.c */ + +diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c +index 720e9d2..592be44 100644 +--- a/source3/utils/net_rpc.c ++++ b/source3/utils/net_rpc.c +@@ -438,6 +438,72 @@ fail: + } + + /** ++ * check that a join is OK ++ * ++ * @return A shell status integer (0 for success) ++ * ++ **/ ++int net_rpc_testjoin(struct net_context *c, int argc, const char **argv) ++{ ++ NTSTATUS status; ++ TALLOC_CTX *mem_ctx; ++ const char *domain = c->opt_target_workgroup; ++ const char *dc = c->opt_host; ++ ++ if (c->display_usage) { ++ d_printf("Usage\n" ++ "net rpc testjoin\n" ++ " Test if a join is OK\n"); ++ return 0; ++ } ++ ++ mem_ctx = talloc_init("net_rpc_testjoin"); ++ if (!mem_ctx) { ++ return -1; ++ } ++ ++ if (!dc) { ++ struct netr_DsRGetDCNameInfo *info; ++ ++ if (!c->msg_ctx) { ++ d_fprintf(stderr, _("Could not initialise message context. " ++ "Try running as root\n")); ++ talloc_destroy(mem_ctx); ++ return -1; ++ } ++ ++ status = dsgetdcname(mem_ctx, ++ c->msg_ctx, ++ domain, ++ NULL, ++ NULL, ++ DS_RETURN_DNS_NAME, ++ &info); ++ if (!NT_STATUS_IS_OK(status)) { ++ talloc_destroy(mem_ctx); ++ return -1; ++ } ++ ++ dc = strip_hostname(info->dc_unc); ++ } ++ ++ /* Display success or failure */ ++ status = libnet_join_ok(c->opt_workgroup, lp_netbios_name(), dc, ++ c->opt_kerberos); ++ if (!NT_STATUS_IS_OK(status)) { ++ fprintf(stderr,"Join to domain '%s' is not valid: %s\n", ++ domain, nt_errstr(status)); ++ talloc_destroy(mem_ctx); ++ return -1; ++ } ++ ++ printf("Join to '%s' is OK\n",domain); ++ talloc_destroy(mem_ctx); ++ ++ return 0; ++} ++ ++/** + * 'net rpc join' entrypoint. + * @param argc Standard main() style argc. + * @param argv Standard main() style argv. Initial components are already +diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c +index aabbe54..ee39a5c 100644 +--- a/source3/utils/net_rpc_join.c ++++ b/source3/utils/net_rpc_join.c +@@ -561,32 +561,3 @@ done: + + return retval; + } +- +-/** +- * check that a join is OK +- * +- * @return A shell status integer (0 for success) +- * +- **/ +-int net_rpc_testjoin(struct net_context *c, int argc, const char **argv) +-{ +- NTSTATUS nt_status; +- +- if (c->display_usage) { +- d_printf(_("Usage\n" +- "net rpc testjoin\n" +- " Test if a join is OK\n")); +- return 0; +- } +- +- /* Display success or failure */ +- nt_status = net_rpc_join_ok(c, c->opt_target_workgroup, NULL, NULL); +- if (!NT_STATUS_IS_OK(nt_status)) { +- fprintf(stderr, _("Join to domain '%s' is not valid: %s\n"), +- c->opt_target_workgroup, nt_errstr(nt_status)); +- return -1; +- } +- +- printf(_("Join to '%s' is OK\n"), c->opt_target_workgroup); +- return 0; +-} +-- +1.9.3 + + +From a0474baa59c0991c2b2d8e3f425c9a6845162f45 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Tue, 3 Feb 2009 20:21:05 +0100 +Subject: [PATCH 041/249] s3-net: use libnetjoin for "net rpc join" newstyle. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 3e4ded48bbeacdcd128f3c667cbdd12a3efca312) +--- + source3/utils/net_proto.h | 8 +--- + source3/utils/net_rpc.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++ + source3/wscript_build | 2 +- + 3 files changed, 108 insertions(+), 8 deletions(-) + +diff --git a/source3/utils/net_proto.h b/source3/utils/net_proto.h +index d791708..1809ba9 100644 +--- a/source3/utils/net_proto.h ++++ b/source3/utils/net_proto.h +@@ -146,6 +146,7 @@ int run_rpc_command(struct net_context *c, + const char **argv); + int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv); + int net_rpc_testjoin(struct net_context *c, int argc, const char **argv); ++int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv); + int net_rpc_join(struct net_context *c, int argc, const char **argv); + NTSTATUS rpc_info_internals(struct net_context *c, + const struct dom_sid *domain_sid, +@@ -200,13 +201,6 @@ int net_rpc(struct net_context *c, int argc, const char **argv); + + int net_rpc_audit(struct net_context *c, int argc, const char **argv); + +-/* The following definitions come from utils/net_rpc_join.c */ +- +-NTSTATUS net_rpc_join_ok(struct net_context *c, const char *domain, +- const char *server, +- const struct sockaddr_storage *server_ss); +-int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv); +- + /* The following definitions come from utils/net_rpc_printer.c */ + + NTSTATUS net_copy_fileattr(struct net_context *c, +diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c +index 592be44..6358460 100644 +--- a/source3/utils/net_rpc.c ++++ b/source3/utils/net_rpc.c +@@ -504,6 +504,112 @@ int net_rpc_testjoin(struct net_context *c, int argc, const char **argv) + } + + /** ++ * Join a domain using the administrator username and password ++ * ++ * @param argc Standard main() style argc ++ * @param argc Standard main() style argv. Initial components are already ++ * stripped. Currently not used. ++ * @return A shell status integer (0 for success) ++ * ++ **/ ++ ++int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) ++{ ++ struct libnet_JoinCtx *r = NULL; ++ TALLOC_CTX *mem_ctx; ++ WERROR werr; ++ const char *domain = lp_workgroup(); /* FIXME */ ++ bool modify_config = lp_config_backend_is_registry(); ++ enum netr_SchannelType sec_chan_type; ++ ++ if (c->display_usage) { ++ d_printf("Usage:\n" ++ "net rpc join\n" ++ " Join a domain the new way\n"); ++ return 0; ++ } ++ ++ mem_ctx = talloc_init("net_rpc_join_newstyle"); ++ if (!mem_ctx) { ++ return -1; ++ } ++ ++ werr = libnet_init_JoinCtx(mem_ctx, &r); ++ if (!W_ERROR_IS_OK(werr)) { ++ goto fail; ++ } ++ ++ /* ++ check what type of join - if the user want's to join as ++ a BDC, the server must agree that we are a BDC. ++ */ ++ if (argc >= 0) { ++ sec_chan_type = get_sec_channel_type(argv[0]); ++ } else { ++ sec_chan_type = get_sec_channel_type(NULL); ++ } ++ ++ if (!c->msg_ctx) { ++ d_fprintf(stderr, _("Could not initialise message context. " ++ "Try running as root\n")); ++ werr = WERR_ACCESS_DENIED; ++ goto fail; ++ } ++ ++ r->in.msg_ctx = c->msg_ctx; ++ r->in.domain_name = domain; ++ r->in.secure_channel_type = sec_chan_type; ++ r->in.dc_name = c->opt_host; ++ r->in.admin_account = c->opt_user_name; ++ r->in.admin_password = net_prompt_pass(c, c->opt_user_name); ++ r->in.debug = true; ++ r->in.use_kerberos = c->opt_kerberos; ++ r->in.modify_config = modify_config; ++ r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE | ++ WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE | ++ WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED; ++ ++ werr = libnet_Join(mem_ctx, r); ++ if (!W_ERROR_IS_OK(werr)) { ++ goto fail; ++ } ++ ++ /* Check the short name of the domain */ ++ ++ if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) { ++ d_printf("The workgroup in %s does not match the short\n", get_dyn_CONFIGFILE()); ++ d_printf("domain name obtained from the server.\n"); ++ d_printf("Using the name [%s] from the server.\n", r->out.netbios_domain_name); ++ d_printf("You should set \"workgroup = %s\" in %s.\n", ++ r->out.netbios_domain_name, get_dyn_CONFIGFILE()); ++ } ++ ++ d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name); ++ ++ if (r->out.dns_domain_name) { ++ d_printf("Joined '%s' to realm '%s'\n", r->in.machine_name, ++ r->out.dns_domain_name); ++ } else { ++ d_printf("Joined '%s' to domain '%s'\n", r->in.machine_name, ++ r->out.netbios_domain_name); ++ } ++ ++ TALLOC_FREE(mem_ctx); ++ ++ return 0; ++ ++fail: ++ /* issue an overall failure message at the end. */ ++ d_printf("Failed to join domain: %s\n", ++ r && r->out.error_string ? r->out.error_string : ++ get_friendly_werror_msg(werr)); ++ ++ TALLOC_FREE(mem_ctx); ++ ++ return -1; ++} ++ ++/** + * 'net rpc join' entrypoint. + * @param argc Standard main() style argc. + * @param argv Standard main() style argv. Initial components are already +diff --git a/source3/wscript_build b/source3/wscript_build +index 9461b05..0bf84e2 100755 +--- a/source3/wscript_build ++++ b/source3/wscript_build +@@ -507,7 +507,7 @@ LIBNET_SAMSYNC_SRC = '''libnet/libnet_samsync.c + + NET_SRC1 = '''utils/net.c utils/net_ads.c utils/net_help.c + utils/net_rap.c utils/net_rpc.c utils/net_rpc_samsync.c +- utils/net_rpc_join.c utils/net_time.c utils/net_lookup.c ++ utils/net_time.c utils/net_lookup.c + utils/net_cache.c utils/net_groupmap.c + utils/net_idmap.c utils/net_idmap_check.c + utils/interact.c +-- +1.9.3 + + +From b2aad96d2ffd5545c250cce605dfdb7f0852806c Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 15 Jul 2013 13:28:34 +0200 +Subject: [PATCH 042/249] s3-net: avoid confusing output in net_rpc_oldjoin() + if NET_FLAGS_EXPECT_FALLBACK is passed + +"net rpc join" tries net_rpc_oldjoin() first and falls back to +net_rpc_join_newstyle(). We should not print the join failed +if just net_rpc_oldjoin() failed. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 05d9b4165af9e7f03d3fbeb64db4fc305fcec4df) +--- + source3/utils/net.h | 1 + + source3/utils/net_proto.h | 1 - + source3/utils/net_rpc.c | 15 +++++++++++++-- + 3 files changed, 14 insertions(+), 3 deletions(-) + +diff --git a/source3/utils/net.h b/source3/utils/net.h +index 2056d89..e97734a 100644 +--- a/source3/utils/net.h ++++ b/source3/utils/net.h +@@ -182,6 +182,7 @@ enum netdom_domain_t { ND_TYPE_NT4, ND_TYPE_AD }; + #define NET_FLAGS_SIGN 0x00000040 /* sign RPC connection */ + #define NET_FLAGS_SEAL 0x00000080 /* seal RPC connection */ + #define NET_FLAGS_TCP 0x00000100 /* use ncacn_ip_tcp */ ++#define NET_FLAGS_EXPECT_FALLBACK 0x00000200 /* the caller will fallback */ + + /* net share operation modes */ + #define NET_MODE_SHARE_MIGRATE 1 +diff --git a/source3/utils/net_proto.h b/source3/utils/net_proto.h +index 1809ba9..25e9db2 100644 +--- a/source3/utils/net_proto.h ++++ b/source3/utils/net_proto.h +@@ -146,7 +146,6 @@ int run_rpc_command(struct net_context *c, + const char **argv); + int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv); + int net_rpc_testjoin(struct net_context *c, int argc, const char **argv); +-int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv); + int net_rpc_join(struct net_context *c, int argc, const char **argv); + NTSTATUS rpc_info_internals(struct net_context *c, + const struct dom_sid *domain_sid, +diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c +index 6358460..dff8801 100644 +--- a/source3/utils/net_rpc.c ++++ b/source3/utils/net_rpc.c +@@ -427,11 +427,16 @@ static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv) + return 0; + + fail: ++ if (c->opt_flags & NET_FLAGS_EXPECT_FALLBACK) { ++ goto cleanup; ++ } ++ + /* issue an overall failure message at the end. */ + d_fprintf(stderr, _("Failed to join domain: %s\n"), + r && r->out.error_string ? r->out.error_string : + get_friendly_werror_msg(werr)); + ++cleanup: + TALLOC_FREE(mem_ctx); + + return -1; +@@ -513,7 +518,7 @@ int net_rpc_testjoin(struct net_context *c, int argc, const char **argv) + * + **/ + +-int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) ++static int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) + { + struct libnet_JoinCtx *r = NULL; + TALLOC_CTX *mem_ctx; +@@ -623,6 +628,8 @@ fail: + + int net_rpc_join(struct net_context *c, int argc, const char **argv) + { ++ int ret; ++ + if (c->display_usage) { + d_printf("%s\n%s", + _("Usage:"), +@@ -650,8 +657,12 @@ int net_rpc_join(struct net_context *c, int argc, const char **argv) + return -1; + } + +- if ((net_rpc_oldjoin(c, argc, argv) == 0)) ++ c->opt_flags |= NET_FLAGS_EXPECT_FALLBACK; ++ ret = net_rpc_oldjoin(c, argc, argv); ++ c->opt_flags &= ~NET_FLAGS_EXPECT_FALLBACK; ++ if (ret == 0) { + return 0; ++ } + + return net_rpc_join_newstyle(c, argc, argv); + } +-- +1.9.3 + + +From 8e8a2602d1c793f9a46e5219dea91a46e34d24ca Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 16 Jul 2013 10:07:30 +0200 +Subject: [PATCH 043/249] s4:librpc: fix netlogon connections against servers + without AES support + +LogonGetCapabilities() only works on the credential chain if +the server supports AES, so we need to work on a temporary copy +until we know the server replied a valid return authenticator. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 34fa7946993506fde2c6b30e4a41bea27390a814) +--- + source4/librpc/rpc/dcerpc_schannel.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c +index 1480486..130ebeb 100644 +--- a/source4/librpc/rpc/dcerpc_schannel.c ++++ b/source4/librpc/rpc/dcerpc_schannel.c +@@ -385,6 +385,7 @@ struct auth_schannel_state { + struct loadparm_context *lp_ctx; + uint8_t auth_level; + struct netlogon_creds_CredentialState *creds_state; ++ struct netlogon_creds_CredentialState save_creds_state; + struct netr_Authenticator auth; + struct netr_Authenticator return_auth; + union netr_Capabilities capabilities; +@@ -449,7 +450,8 @@ static void continue_bind_auth(struct composite_context *ctx) + s->creds_state = cli_credentials_get_netlogon_creds(s->credentials); + if (composite_nomem(s->creds_state, c)) return; + +- netlogon_creds_client_authenticator(s->creds_state, &s->auth); ++ s->save_creds_state = *s->creds_state; ++ netlogon_creds_client_authenticator(&s->save_creds_state, &s->auth); + + s->c.in.server_name = talloc_asprintf(c, + "\\\\%s", +@@ -519,12 +521,14 @@ static void continue_get_capabilities(struct tevent_req *subreq) + } + + /* verify credentials */ +- if (!netlogon_creds_client_check(s->creds_state, ++ if (!netlogon_creds_client_check(&s->save_creds_state, + &s->c.out.return_authenticator->cred)) { + composite_error(c, NT_STATUS_UNSUCCESSFUL); + return; + } + ++ *s->creds_state = s->save_creds_state; ++ + if (!NT_STATUS_IS_OK(s->c.out.result)) { + composite_error(c, s->c.out.result); + return; +-- +1.9.3 + + +From 300fb415d5a6a60702b0c8464e0e76cf0e11fdeb Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 22 Mar 2013 15:07:10 +0100 +Subject: [PATCH 044/249] s3:rpcclient: use talloc_stackframe() in do_cmd() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit d54c908ff5bef774f5cca038741558089ff6baeb) +--- + source3/rpcclient/rpcclient.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c +index c23ff2d..9bf296e 100644 +--- a/source3/rpcclient/rpcclient.c ++++ b/source3/rpcclient/rpcclient.c +@@ -678,7 +678,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, + + /* Create mem_ctx */ + +- if (!(mem_ctx = talloc_init("do_cmd"))) { ++ if (!(mem_ctx = talloc_stackframe())) { + DEBUG(0, ("talloc_init() failed\n")); + return NT_STATUS_NO_MEMORY; + } +@@ -745,12 +745,14 @@ static NTSTATUS do_cmd(struct cli_state *cli, + "auth type %u\n", + cmd_entry->table->name, + pipe_default_auth_type )); ++ talloc_free(mem_ctx); + return NT_STATUS_UNSUCCESSFUL; + } + if (!NT_STATUS_IS_OK(ntresult)) { + DEBUG(0, ("Could not initialise %s. Error was %s\n", + cmd_entry->table->name, + nt_errstr(ntresult) )); ++ talloc_free(mem_ctx); + return ntresult; + } + +@@ -765,6 +767,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, + trust_password, &machine_account, + &sec_channel_type)) + { ++ talloc_free(mem_ctx); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + +@@ -780,6 +783,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, + if (!NT_STATUS_IS_OK(ntresult)) { + DEBUG(0, ("Could not initialise credentials for %s.\n", + cmd_entry->table->name)); ++ talloc_free(mem_ctx); + return ntresult; + } + } +@@ -803,7 +807,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, + + /* Cleanup */ + +- talloc_destroy(mem_ctx); ++ talloc_free(mem_ctx); + + return ntresult; + } +-- +1.9.3 + + +From 95972ec54aafcf8a66e0164cd1fb478b6f4c58f6 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 24 Apr 2013 12:36:04 +0200 +Subject: [PATCH 045/249] libcli/auth: make + netlogon_creds_crypt_samlogon_validation more robust + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 39fedd27182d9e1985418ea79b86aef69999dd57) +--- + libcli/auth/credentials.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c +index fb77ede..5c8b25b 100644 +--- a/libcli/auth/credentials.c ++++ b/libcli/auth/credentials.c +@@ -493,8 +493,12 @@ static void netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_Crede + bool encrypt) + { + static const char zeros[16]; +- + struct netr_SamBaseInfo *base = NULL; ++ ++ if (validation == NULL) { ++ return; ++ } ++ + switch (validation_level) { + case 2: + if (validation->sam2) { +-- +1.9.3 + + +From ac092a319c388cc2577bcbd87e16522ba37dc2d0 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 14 Jun 2013 09:47:50 +0200 +Subject: [PATCH 046/249] libcli/auth: fix shadowed declaration in + netlogon_creds_crypt_samlogon_validation() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 291f6a1e031dc9db7d03b3ca924c4309b313cae5) +--- + libcli/auth/credentials.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c +index 5c8b25b..2e9c87e 100644 +--- a/libcli/auth/credentials.c ++++ b/libcli/auth/credentials.c +@@ -490,7 +490,7 @@ NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState + static void netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_CredentialState *creds, + uint16_t validation_level, + union netr_Validation *validation, +- bool encrypt) ++ bool do_encrypt) + { + static const char zeros[16]; + struct netr_SamBaseInfo *base = NULL; +@@ -531,7 +531,7 @@ static void netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_Crede + /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */ + if (memcmp(base->key.key, zeros, + sizeof(base->key.key)) != 0) { +- if (encrypt) { ++ if (do_encrypt) { + netlogon_creds_aes_encrypt(creds, + base->key.key, + sizeof(base->key.key)); +@@ -544,7 +544,7 @@ static void netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_Crede + + if (memcmp(base->LMSessKey.key, zeros, + sizeof(base->LMSessKey.key)) != 0) { +- if (encrypt) { ++ if (do_encrypt) { + netlogon_creds_aes_encrypt(creds, + base->LMSessKey.key, + sizeof(base->LMSessKey.key)); +@@ -574,7 +574,7 @@ static void netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_Crede + /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */ + if (memcmp(base->LMSessKey.key, zeros, + sizeof(base->LMSessKey.key)) != 0) { +- if (encrypt) { ++ if (do_encrypt) { + netlogon_creds_des_encrypt_LMKey(creds, + &base->LMSessKey); + } else { +-- +1.9.3 + + +From c535bfb9ead2175ae68b9d18a1692218a0fcf800 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 25 Apr 2013 17:01:00 +0200 +Subject: [PATCH 047/249] libcli/auth: add + netlogon_creds_[de|en]crypt_samlogon_logon() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit c7319fce604d5f89a89094b6b18ef459a347aef8) +--- + libcli/auth/credentials.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++ + libcli/auth/proto.h | 6 +++ + 2 files changed, 124 insertions(+) + +diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c +index 2e9c87e..78a8d7a 100644 +--- a/libcli/auth/credentials.c ++++ b/libcli/auth/credentials.c +@@ -601,6 +601,124 @@ void netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_Credential + validation, true); + } + ++static void netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, ++ enum netr_LogonInfoClass level, ++ union netr_LogonLevel *logon, ++ bool encrypt) ++{ ++ static const char zeros[16]; ++ ++ if (logon == NULL) { ++ return; ++ } ++ ++ switch (level) { ++ case NetlogonInteractiveInformation: ++ case NetlogonInteractiveTransitiveInformation: ++ case NetlogonServiceInformation: ++ case NetlogonServiceTransitiveInformation: ++ if (logon->password == NULL) { ++ return; ++ } ++ ++ if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { ++ uint8_t *h; ++ ++ h = logon->password->lmpassword.hash; ++ if (memcmp(h, zeros, 16) != 0) { ++ if (encrypt) { ++ netlogon_creds_aes_encrypt(creds, h, 16); ++ } else { ++ netlogon_creds_aes_decrypt(creds, h, 16); ++ } ++ } ++ ++ h = logon->password->ntpassword.hash; ++ if (memcmp(h, zeros, 16) != 0) { ++ if (encrypt) { ++ netlogon_creds_aes_encrypt(creds, h, 16); ++ } else { ++ netlogon_creds_aes_decrypt(creds, h, 16); ++ } ++ } ++ } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { ++ uint8_t *h; ++ ++ h = logon->password->lmpassword.hash; ++ if (memcmp(h, zeros, 16) != 0) { ++ netlogon_creds_arcfour_crypt(creds, h, 16); ++ } ++ ++ h = logon->password->ntpassword.hash; ++ if (memcmp(h, zeros, 16) != 0) { ++ netlogon_creds_arcfour_crypt(creds, h, 16); ++ } ++ } else { ++ struct samr_Password *p; ++ ++ p = &logon->password->lmpassword; ++ if (memcmp(p->hash, zeros, 16) != 0) { ++ if (encrypt) { ++ netlogon_creds_des_encrypt(creds, p); ++ } else { ++ netlogon_creds_des_decrypt(creds, p); ++ } ++ } ++ p = &logon->password->ntpassword; ++ if (memcmp(p->hash, zeros, 16) != 0) { ++ if (encrypt) { ++ netlogon_creds_des_encrypt(creds, p); ++ } else { ++ netlogon_creds_des_decrypt(creds, p); ++ } ++ } ++ } ++ break; ++ ++ case NetlogonNetworkInformation: ++ case NetlogonNetworkTransitiveInformation: ++ break; ++ ++ case NetlogonGenericInformation: ++ if (logon->generic == NULL) { ++ return; ++ } ++ ++ if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { ++ if (encrypt) { ++ netlogon_creds_aes_encrypt(creds, ++ logon->generic->data, ++ logon->generic->length); ++ } else { ++ netlogon_creds_aes_decrypt(creds, ++ logon->generic->data, ++ logon->generic->length); ++ } ++ } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { ++ netlogon_creds_arcfour_crypt(creds, ++ logon->generic->data, ++ logon->generic->length); ++ } else { ++ /* Using DES to verify kerberos tickets makes no sense */ ++ } ++ break; ++ } ++} ++ ++void netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, ++ enum netr_LogonInfoClass level, ++ union netr_LogonLevel *logon) ++{ ++ netlogon_creds_crypt_samlogon_logon(creds, level, logon, false); ++} ++ ++void netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, ++ enum netr_LogonInfoClass level, ++ union netr_LogonLevel *logon) ++{ ++ netlogon_creds_crypt_samlogon_logon(creds, level, logon, true); ++} ++ + /* + copy a netlogon_creds_CredentialState struct + */ +diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h +index 6bc18d7..110e039 100644 +--- a/libcli/auth/proto.h ++++ b/libcli/auth/proto.h +@@ -64,6 +64,12 @@ void netlogon_creds_decrypt_samlogon_validation(struct netlogon_creds_Credential + void netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds, + uint16_t validation_level, + union netr_Validation *validation); ++void netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, ++ enum netr_LogonInfoClass level, ++ union netr_LogonLevel *logon); ++void netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, ++ enum netr_LogonInfoClass level, ++ union netr_LogonLevel *logon); + + /* The following definitions come from /home/jeremy/src/samba/git/master/source3/../source4/../libcli/auth/session.c */ + +-- +1.9.3 + + +From d4f36f187d7c87c8daae3f94cdba52225faa19b8 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 24 Apr 2013 12:53:27 +0200 +Subject: [PATCH 048/249] libcli/auth: add netlogon_creds_shallow_copy_logon() + +This can be used before netlogon_creds_encrypt_samlogon_logon() +in order to keep the provided buffers unchanged. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 2ea749a1a43a6539b01d36dbe0402a99619444e1) +--- + libcli/auth/credentials.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++ + libcli/auth/proto.h | 3 ++ + 2 files changed, 76 insertions(+) + +diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c +index 78a8d7a..1f664d3 100644 +--- a/libcli/auth/credentials.c ++++ b/libcli/auth/credentials.c +@@ -719,6 +719,79 @@ void netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState + netlogon_creds_crypt_samlogon_logon(creds, level, logon, true); + } + ++union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx, ++ enum netr_LogonInfoClass level, ++ const union netr_LogonLevel *in) ++{ ++ union netr_LogonLevel *out; ++ ++ if (in == NULL) { ++ return NULL; ++ } ++ ++ out = talloc(mem_ctx, union netr_LogonLevel); ++ if (out == NULL) { ++ return NULL; ++ } ++ ++ *out = *in; ++ ++ switch (level) { ++ case NetlogonInteractiveInformation: ++ case NetlogonInteractiveTransitiveInformation: ++ case NetlogonServiceInformation: ++ case NetlogonServiceTransitiveInformation: ++ if (in->password == NULL) { ++ return out; ++ } ++ ++ out->password = talloc(out, struct netr_PasswordInfo); ++ if (out->password == NULL) { ++ talloc_free(out); ++ return NULL; ++ } ++ *out->password = *in->password; ++ ++ return out; ++ ++ case NetlogonNetworkInformation: ++ case NetlogonNetworkTransitiveInformation: ++ break; ++ ++ case NetlogonGenericInformation: ++ if (in->generic == NULL) { ++ return out; ++ } ++ ++ out->generic = talloc(out, struct netr_GenericInfo); ++ if (out->generic == NULL) { ++ talloc_free(out); ++ return NULL; ++ } ++ *out->generic = *in->generic; ++ ++ if (in->generic->data == NULL) { ++ return out; ++ } ++ ++ if (in->generic->length == 0) { ++ return out; ++ } ++ ++ out->generic->data = talloc_memdup(out->generic, ++ in->generic->data, ++ in->generic->length); ++ if (out->generic->data == NULL) { ++ talloc_free(out); ++ return NULL; ++ } ++ ++ return out; ++ } ++ ++ return out; ++} ++ + /* + copy a netlogon_creds_CredentialState struct + */ +diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h +index 110e039..0c319d3 100644 +--- a/libcli/auth/proto.h ++++ b/libcli/auth/proto.h +@@ -70,6 +70,9 @@ void netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState + void netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, + enum netr_LogonInfoClass level, + union netr_LogonLevel *logon); ++union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx, ++ enum netr_LogonInfoClass level, ++ const union netr_LogonLevel *in); + + /* The following definitions come from /home/jeremy/src/samba/git/master/source3/../source4/../libcli/auth/session.c */ + +-- +1.9.3 + + +From 8cf11ba846fc31ce26020aabcf463817b56580a7 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 24 Apr 2013 16:00:18 +0200 +Subject: [PATCH 049/249] s4:netlogon: make use of + netlogon_creds_decrypt_samlogon_logon() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 9d548318da11247ffe8acf505cdb5299090c16f0) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 28 ++++++--------------------- + 1 file changed, 6 insertions(+), 22 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index 70239a4..c41cd02 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -712,29 +712,15 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal + user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info); + NT_STATUS_HAVE_NO_MEMORY(user_info); + ++ netlogon_creds_decrypt_samlogon_logon(creds, ++ r->in.logon_level, ++ r->in.logon); ++ + switch (r->in.logon_level) { + case NetlogonInteractiveInformation: + case NetlogonServiceInformation: + case NetlogonInteractiveTransitiveInformation: + case NetlogonServiceTransitiveInformation: +- if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { +- netlogon_creds_aes_decrypt(creds, +- r->in.logon->password->lmpassword.hash, +- sizeof(r->in.logon->password->lmpassword.hash)); +- netlogon_creds_aes_decrypt(creds, +- r->in.logon->password->ntpassword.hash, +- sizeof(r->in.logon->password->ntpassword.hash)); +- } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { +- netlogon_creds_arcfour_crypt(creds, +- r->in.logon->password->lmpassword.hash, +- sizeof(r->in.logon->password->lmpassword.hash)); +- netlogon_creds_arcfour_crypt(creds, +- r->in.logon->password->ntpassword.hash, +- sizeof(r->in.logon->password->ntpassword.hash)); +- } else { +- netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword); +- netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword); +- } + + /* TODO: we need to deny anonymous access here */ + nt_status = auth_context_create(mem_ctx, +@@ -788,11 +774,9 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal + case NetlogonGenericInformation: + { + if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { +- netlogon_creds_aes_decrypt(creds, +- r->in.logon->generic->data, r->in.logon->generic->length); ++ /* OK */ + } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { +- netlogon_creds_arcfour_crypt(creds, +- r->in.logon->generic->data, r->in.logon->generic->length); ++ /* OK */ + } else { + /* Using DES to verify kerberos tickets makes no sense */ + return NT_STATUS_INVALID_PARAMETER; +-- +1.9.3 + + +From 22bdc484af1b1a4ebd9451fd5cde4d3993dd6f0a Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 24 Apr 2013 16:00:44 +0200 +Subject: [PATCH 050/249] s3:netlogon: make use of + netlogon_creds_decrypt_samlogon_logon() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 7b3ddd1a0bb41fe84c115555113362044620e484) +--- + source3/rpc_server/netlogon/srv_netlog_nt.c | 45 ++++++++++++++--------------- + 1 file changed, 21 insertions(+), 24 deletions(-) + +diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c +index e5ca474..09857b6 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -1467,6 +1467,15 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p, + struct auth_context *auth_context = NULL; + const char *fn; + ++#ifdef DEBUG_PASSWORD ++ logon = netlogon_creds_shallow_copy_logon(p->mem_ctx, ++ r->in.logon_level, ++ r->in.logon); ++ if (logon == NULL) { ++ logon = r->in.logon; ++ } ++#endif ++ + switch (p->opnum) { + case NDR_NETR_LOGONSAMLOGON: + fn = "_netr_LogonSamLogon"; +@@ -1547,6 +1556,10 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p, + + status = NT_STATUS_OK; + ++ netlogon_creds_decrypt_samlogon_logon(creds, ++ r->in.logon_level, ++ logon); ++ + switch (r->in.logon_level) { + case NetlogonNetworkInformation: + case NetlogonNetworkTransitiveInformation: +@@ -1592,32 +1605,16 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p, + uint8_t chal[8]; + + #ifdef DEBUG_PASSWORD +- DEBUG(100,("lm owf password:")); +- dump_data(100, logon->password->lmpassword.hash, 16); +- +- DEBUG(100,("nt owf password:")); +- dump_data(100, logon->password->ntpassword.hash, 16); +-#endif +- if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { +- netlogon_creds_aes_decrypt(creds, +- logon->password->lmpassword.hash, +- 16); +- netlogon_creds_aes_decrypt(creds, +- logon->password->ntpassword.hash, +- 16); +- } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { +- netlogon_creds_arcfour_crypt(creds, +- logon->password->lmpassword.hash, +- 16); +- netlogon_creds_arcfour_crypt(creds, +- logon->password->ntpassword.hash, +- 16); +- } else { +- netlogon_creds_des_decrypt(creds, &logon->password->lmpassword); +- netlogon_creds_des_decrypt(creds, &logon->password->ntpassword); ++ if (logon != r->in.logon) { ++ DEBUG(100,("lm owf password:")); ++ dump_data(100, ++ r->in.logon->password->lmpassword.hash, 16); ++ ++ DEBUG(100,("nt owf password:")); ++ dump_data(100, ++ r->in.logon->password->ntpassword.hash, 16); + } + +-#ifdef DEBUG_PASSWORD + DEBUG(100,("decrypt of lm owf password:")); + dump_data(100, logon->password->lmpassword.hash, 16); + +-- +1.9.3 + + +From b25c7249bdca17d4b4720a2e8f8ba329c4105e94 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 25 Apr 2013 18:27:57 +0200 +Subject: [PATCH 051/249] s3:rpc_client: make rpccli_schannel_bind_data() + static + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 6ce645e03c279cbb2ed8a94f033b8e0601b61ef4) +--- + source3/rpc_client/cli_pipe.c | 9 +++++---- + source3/rpc_client/cli_pipe.h | 6 ------ + 2 files changed, 5 insertions(+), 10 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 1fa8d91..66fa2d2 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -2401,10 +2401,11 @@ static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx, + return status; + } + +-NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain, +- enum dcerpc_AuthLevel auth_level, +- struct netlogon_creds_CredentialState *creds, +- struct pipe_auth_data **presult) ++static NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, ++ const char *domain, ++ enum dcerpc_AuthLevel auth_level, ++ struct netlogon_creds_CredentialState *creds, ++ struct pipe_auth_data **presult) + { + struct schannel_state *schannel_auth; + struct pipe_auth_data *result; +diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h +index 6fcc587..8eb6040 100644 +--- a/source3/rpc_client/cli_pipe.h ++++ b/source3/rpc_client/cli_pipe.h +@@ -58,12 +58,6 @@ NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx, + NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx, + struct pipe_auth_data **presult); + +-NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, +- const char *domain, +- enum dcerpc_AuthLevel auth_level, +- struct netlogon_creds_CredentialState *creds, +- struct pipe_auth_data **presult); +- + NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, + const char *host, + const struct sockaddr_storage *ss_addr, +-- +1.9.3 + + +From 9f56e42ba78ce4e1248f06a0cecfc97789aea260 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 25 Apr 2013 18:29:31 +0200 +Subject: [PATCH 052/249] s3:rpc_client: use the correct context for + netlogon_creds_copy() in rpccli_schannel_bind_data() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 8a302fc353de8d373a0ec8544da4da6f305ec923) +--- + source3/rpc_client/cli_pipe.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 66fa2d2..afe8030 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -2431,7 +2431,10 @@ static NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, + + schannel_auth->state = SCHANNEL_STATE_START; + schannel_auth->initiator = true; +- schannel_auth->creds = netlogon_creds_copy(result, creds); ++ schannel_auth->creds = netlogon_creds_copy(schannel_auth, creds); ++ if (schannel_auth->creds == NULL) { ++ goto fail; ++ } + + result->auth_ctx = schannel_auth; + *presult = result; +-- +1.9.3 + + +From 08d78b16f0adf1d223f29d613a498878230522be Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 25 Apr 2013 19:43:58 +0200 +Subject: [PATCH 053/249] s3:rpc_client: rename same variables in + cli_rpc_pipe_open_schannel_with_key() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +(cherry picked from commit 94be8d63cd21fbb9e31bf7a92af82e19c596f94f) +--- + source3/rpc_client/cli_pipe.c | 30 +++++++++++++++--------------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index afe8030..ec804e7 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -3032,32 +3032,32 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + enum dcerpc_AuthLevel auth_level, + const char *domain, + struct netlogon_creds_CredentialState **pdc, +- struct rpc_pipe_client **presult) ++ struct rpc_pipe_client **_rpccli) + { +- struct rpc_pipe_client *result; +- struct pipe_auth_data *auth; ++ struct rpc_pipe_client *rpccli; ++ struct pipe_auth_data *rpcauth; + NTSTATUS status; + +- status = cli_rpc_pipe_open(cli, transport, table, &result); ++ status = cli_rpc_pipe_open(cli, transport, table, &rpccli); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + +- status = rpccli_schannel_bind_data(result, domain, auth_level, +- *pdc, &auth); ++ status = rpccli_schannel_bind_data(rpccli, domain, auth_level, ++ *pdc, &rpcauth); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("rpccli_schannel_bind_data returned %s\n", + nt_errstr(status))); +- TALLOC_FREE(result); ++ TALLOC_FREE(rpccli); + return status; + } + +- status = rpc_pipe_bind(result, auth); ++ status = rpc_pipe_bind(rpccli, rpcauth); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: " + "cli_rpc_pipe_bind failed with error %s\n", + nt_errstr(status) )); +- TALLOC_FREE(result); ++ TALLOC_FREE(rpccli); + return status; + } + +@@ -3065,10 +3065,10 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + * The credentials on a new netlogon pipe are the ones we are passed + * in - copy them over + */ +- if (result->dc == NULL) { +- result->dc = netlogon_creds_copy(result, *pdc); +- if (result->dc == NULL) { +- TALLOC_FREE(result); ++ if (rpccli->dc == NULL) { ++ rpccli->dc = netlogon_creds_copy(rpccli, *pdc); ++ if (rpccli->dc == NULL) { ++ TALLOC_FREE(rpccli); + return NT_STATUS_NO_MEMORY; + } + } +@@ -3076,9 +3076,9 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s " + "for domain %s and bound using schannel.\n", + get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), +- result->desthost, domain)); ++ rpccli->desthost, domain)); + +- *presult = result; ++ *_rpccli = rpccli; + return NT_STATUS_OK; + } + +-- +1.9.3 + + +From 33991d3ea286fc5da1458ca64aa4fc004547ae04 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 5 Aug 2013 20:26:54 +0200 +Subject: [PATCH 054/249] s3:libsmb: remove unused cli_state->is_guestlogin + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 11e0be0e72cfc4bc65ba2b0ffd10cbae3ad69b2d) +--- + source3/include/client.h | 1 - + source3/libsmb/cliconnect.c | 5 ----- + 2 files changed, 6 deletions(-) + +diff --git a/source3/include/client.h b/source3/include/client.h +index 3f92d6d..59fb104 100644 +--- a/source3/include/client.h ++++ b/source3/include/client.h +@@ -72,7 +72,6 @@ struct cli_state { + int timeout; /* in milliseconds. */ + int initialised; + int win95; +- bool is_guestlogin; + /* What the server offered. */ + uint32_t server_posix_capabilities; + /* What the client requested. */ +diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c +index 13e7704..81bc028 100644 +--- a/source3/libsmb/cliconnect.c ++++ b/source3/libsmb/cliconnect.c +@@ -240,7 +240,6 @@ static void cli_session_setup_lanman2_done(struct tevent_req *subreq) + p = bytes; + + cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID)); +- cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0); + + status = smb_bytes_talloc_string(cli, + inhdr, +@@ -448,7 +447,6 @@ static void cli_session_setup_guest_done(struct tevent_req *subreq) + p = bytes; + + cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID)); +- cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0); + + status = smb_bytes_talloc_string(cli, + inhdr, +@@ -613,7 +611,6 @@ static void cli_session_setup_plain_done(struct tevent_req *subreq) + p = bytes; + + cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID)); +- cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0); + + status = smb_bytes_talloc_string(cli, + inhdr, +@@ -930,7 +927,6 @@ static void cli_session_setup_nt1_done(struct tevent_req *subreq) + p = bytes; + + cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID)); +- cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0); + + status = smb_bytes_talloc_string(cli, + inhdr, +@@ -1180,7 +1176,6 @@ static void cli_sesssetup_blob_done(struct tevent_req *subreq) + state->inbuf = in; + inhdr = in + NBT_HDR_SIZE; + cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID)); +- cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0); + + blob_length = SVAL(vwv+3, 0); + if (blob_length > num_bytes) { +-- +1.9.3 + + +From 937a0f2fc020e12c21c10597a889275614603add Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sat, 15 Jun 2013 09:41:52 +0200 +Subject: [PATCH 055/249] s3:auth_domain: try to use NETLOGON_NEG_SUPPORTS_AES + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit d82ab70579ff2bcb69f997068482b198f321d1ef) +--- + source3/auth/auth_domain.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c +index 54ee5a1..06078e2 100644 +--- a/source3/auth/auth_domain.c ++++ b/source3/auth/auth_domain.c +@@ -133,7 +133,8 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); + + if (!lp_client_schannel()) { + /* We need to set up a creds chain on an unauthenticated netlogon pipe. */ +- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | ++ NETLOGON_NEG_SUPPORTS_AES; + enum netr_SchannelType sec_chan_type = 0; + unsigned char machine_pwd[16]; + const char *account_name; +-- +1.9.3 + + +From 981a88bb20cef572e5573ee2f18115a6e395fbf9 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sat, 15 Jun 2013 09:41:52 +0200 +Subject: [PATCH 056/249] s3:libnet_join: try to use NETLOGON_NEG_SUPPORTS_AES + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit beba32619a91977543f882432fd08acc9de78fd3) +--- + source3/libnet/libnet_join.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c +index d8ec235..c1eccda 100644 +--- a/source3/libnet/libnet_join.c ++++ b/source3/libnet/libnet_join.c +@@ -1194,7 +1194,8 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, + const char *dc_name, + const bool use_kerberos) + { +- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | ++ NETLOGON_NEG_SUPPORTS_AES; + struct cli_state *cli = NULL; + struct rpc_pipe_client *pipe_hnd = NULL; + struct rpc_pipe_client *netlogon_pipe = NULL; +-- +1.9.3 + + +From 846a35f004850695ca7c9d4597cd8729bb7c99e3 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sat, 15 Jun 2013 09:41:52 +0200 +Subject: [PATCH 057/249] s3:rpc_client: try to use NETLOGON_NEG_SUPPORTS_AES + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 04600634b3e761d7c56f699fd4ba80b4cd2926a1) +--- + source3/rpc_client/cli_netlogon.c | 3 ++- + source3/rpc_client/cli_pipe_schannel.c | 6 ++++-- + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index 3d6a3e1..5e8a2fc 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -610,7 +610,8 @@ NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, + struct dcerpc_binding_handle *b = cli->binding_handle; + + if (!cli->dc) { +- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | ++ NETLOGON_NEG_SUPPORTS_AES; + result = rpccli_netlogon_setup_creds(cli, + cli->desthost, /* server name */ + lp_workgroup(), /* domain */ +diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c +index bc672ef..de745c0 100644 +--- a/source3/rpc_client/cli_pipe_schannel.c ++++ b/source3/rpc_client/cli_pipe_schannel.c +@@ -136,7 +136,8 @@ NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, + const char *password, + struct rpc_pipe_client **presult) + { +- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | ++ NETLOGON_NEG_SUPPORTS_AES; + struct rpc_pipe_client *netlogon_pipe = NULL; + struct rpc_pipe_client *result = NULL; + NTSTATUS status; +@@ -175,7 +176,8 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, + const char *domain, + struct rpc_pipe_client **presult) + { +- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | ++ NETLOGON_NEG_SUPPORTS_AES; + struct rpc_pipe_client *netlogon_pipe = NULL; + struct rpc_pipe_client *result = NULL; + NTSTATUS status; +-- +1.9.3 + + +From a56391bc8cbe1fa9142d0a20f4bf977538f27e67 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sat, 15 Jun 2013 09:41:52 +0200 +Subject: [PATCH 058/249] s3:rpcclient: try to use NETLOGON_NEG_SUPPORTS_AES + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit e77a64f505fc43628e487e832033d0cd8ec4de8e) +--- + source3/rpcclient/cmd_netlogon.c | 3 ++- + source3/rpcclient/rpcclient.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c +index 01d6da4..d92434b 100644 +--- a/source3/rpcclient/cmd_netlogon.c ++++ b/source3/rpcclient/cmd_netlogon.c +@@ -1120,7 +1120,8 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + NTSTATUS result; + const char *server_name = cli->desthost; +- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | ++ NETLOGON_NEG_SUPPORTS_AES; + struct netr_Authenticator clnt_creds, srv_cred; + struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; + unsigned char trust_passwd_hash[16]; +diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c +index 9bf296e..cb7b70f 100644 +--- a/source3/rpcclient/rpcclient.c ++++ b/source3/rpcclient/rpcclient.c +@@ -758,7 +758,8 @@ static NTSTATUS do_cmd(struct cli_state *cli, + + if (ndr_syntax_id_equal(&cmd_entry->table->syntax_id, + &ndr_table_netlogon.syntax_id)) { +- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | ++ NETLOGON_NEG_SUPPORTS_AES; + enum netr_SchannelType sec_channel_type; + uchar trust_password[16]; + const char *machine_account; +-- +1.9.3 + + +From 06c4ff36efc63ef014c449602dc314ca4e7016bd Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 25 Apr 2013 19:57:09 +0200 +Subject: [PATCH 059/249] s3:rpc_client: fix/add AES downgrade detection to + rpc_pipe_bind_step_two_done() + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 90e28c1825b2c48714d7b34fdb57d3878116d07e) +--- + source3/rpc_client/cli_pipe.c | 19 +++++++------------ + 1 file changed, 7 insertions(+), 12 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index ec804e7..c354a6f 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -1828,8 +1828,7 @@ static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq) + status = dcerpc_netr_LogonGetCapabilities_r_recv(subreq, talloc_tos()); + TALLOC_FREE(subreq); + if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { +- if (state->cli->dc && state->cli->dc->negotiate_flags & +- NETLOGON_NEG_SUPPORTS_AES) { ++ if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + DEBUG(5, ("AES is not supported and the error was %s\n", + nt_errstr(status))); + tevent_req_nterror(req, +@@ -1880,9 +1879,6 @@ static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq) + return; + } + +- TALLOC_FREE(state->cli->dc); +- state->cli->dc = talloc_steal(state->cli, state->creds); +- + if (!NT_STATUS_IS_OK(state->r.out.result)) { + DEBUG(0, ("dcerpc_netr_LogonGetCapabilities_r_recv failed with %s\n", + nt_errstr(state->r.out.result))); +@@ -1890,18 +1886,17 @@ static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq) + return; + } + +- if (state->creds->negotiate_flags != +- state->r.out.capabilities->server_capabilities) { +- DEBUG(0, ("The client capabilities don't match the server " +- "capabilities: local[0x%08X] remote[0x%08X]\n", +- state->creds->negotiate_flags, +- state->capabilities.server_capabilities)); ++ if (!(state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)) { ++ DEBUG(0, ("netr_LogonGetCapabilities is supported by %s, " ++ "but AES was not negotiated - downgrade detected", ++ state->cli->desthost)); + tevent_req_nterror(req, + NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } + +- /* TODO: Add downgrade dectection. */ ++ TALLOC_FREE(state->cli->dc); ++ state->cli->dc = talloc_move(state->cli, &state->creds); + + tevent_req_done(req); + return; +-- +1.9.3 + + +From e6416b9fe5019c3ce1aa8ecf42d73125a049338f Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 25 Apr 2013 19:45:52 +0200 +Subject: [PATCH 060/249] s3:rpc_client: use netlogon_creds_copy before + rpc_pipe_bind + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit e9c8e3fb92143525f846523e446e2213e5b55d9d) +--- + source3/rpc_client/cli_pipe.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index c354a6f..eb172db 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -3047,6 +3047,18 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + return status; + } + ++ /* ++ * The credentials on a new netlogon pipe are the ones we are passed ++ * in - copy them over ++ * ++ * This may get overwritten... in rpc_pipe_bind()... ++ */ ++ rpccli->dc = netlogon_creds_copy(rpccli, *pdc); ++ if (rpccli->dc == NULL) { ++ TALLOC_FREE(rpccli); ++ return NT_STATUS_NO_MEMORY; ++ } ++ + status = rpc_pipe_bind(rpccli, rpcauth); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: " +@@ -3056,18 +3068,6 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + return status; + } + +- /* +- * The credentials on a new netlogon pipe are the ones we are passed +- * in - copy them over +- */ +- if (rpccli->dc == NULL) { +- rpccli->dc = netlogon_creds_copy(rpccli, *pdc); +- if (rpccli->dc == NULL) { +- TALLOC_FREE(rpccli); +- return NT_STATUS_NO_MEMORY; +- } +- } +- + DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s " + "for domain %s and bound using schannel.\n", + get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), +-- +1.9.3 + + +From 1836ea96ed7dd055278fd6cac3f69a06ea979ea2 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 25 Apr 2013 19:34:13 +0200 +Subject: [PATCH 061/249] s3:rpc_client: add netr_LogonGetCapabilities to + cli_rpc_pipe_open_schannel_with_key() + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit eecb5bafba5b362d4fdf33d6a2a32e4ee56f30a4) +--- + source3/rpc_client/cli_pipe.c | 101 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 101 insertions(+) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index eb172db..314eb92 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -3032,6 +3032,11 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + struct rpc_pipe_client *rpccli; + struct pipe_auth_data *rpcauth; + NTSTATUS status; ++ NTSTATUS result; ++ struct netlogon_creds_CredentialState save_creds; ++ struct netr_Authenticator auth; ++ struct netr_Authenticator return_auth; ++ union netr_Capabilities capabilities; + + status = cli_rpc_pipe_open(cli, transport, table, &rpccli); + if (!NT_STATUS_IS_OK(status)) { +@@ -3068,6 +3073,102 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + return status; + } + ++ if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) { ++ goto done; ++ } ++ ++ save_creds = *rpccli->dc; ++ ZERO_STRUCT(return_auth); ++ ZERO_STRUCT(capabilities); ++ ++ netlogon_creds_client_authenticator(&save_creds, &auth); ++ ++ status = dcerpc_netr_LogonGetCapabilities(rpccli->binding_handle, ++ talloc_tos(), ++ rpccli->srv_name_slash, ++ save_creds.computer_name, ++ &auth, &return_auth, ++ 1, &capabilities, ++ &result); ++ if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { ++ if (save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { ++ DEBUG(5, ("AES was negotiated and the error was %s - " ++ "downgrade detected\n", ++ nt_errstr(status))); ++ TALLOC_FREE(rpccli); ++ return NT_STATUS_INVALID_NETWORK_RESPONSE; ++ } ++ ++ /* This is probably an old Samba Version */ ++ DEBUG(5, ("We are checking against an NT or old Samba - %s\n", ++ nt_errstr(status))); ++ goto done; ++ } ++ ++ if (!NT_STATUS_IS_OK(status)) { ++ DEBUG(0, ("dcerpc_netr_LogonGetCapabilities failed with %s\n", ++ nt_errstr(status))); ++ TALLOC_FREE(rpccli); ++ return status; ++ } ++ ++ if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) { ++ if (save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { ++ /* This means AES isn't supported. */ ++ DEBUG(5, ("AES was negotiated and the result was %s - " ++ "downgrade detected\n", ++ nt_errstr(result))); ++ TALLOC_FREE(rpccli); ++ return NT_STATUS_INVALID_NETWORK_RESPONSE; ++ } ++ ++ /* This is probably an old Windows version */ ++ DEBUG(5, ("We are checking against an win2k3 or Samba - %s\n", ++ nt_errstr(result))); ++ goto done; ++ } ++ ++ /* ++ * We need to check the credential state here, cause win2k3 and earlier ++ * returns NT_STATUS_NOT_IMPLEMENTED ++ */ ++ if (!netlogon_creds_client_check(&save_creds, &return_auth.cred)) { ++ /* ++ * Server replied with bad credential. Fail. ++ */ ++ DEBUG(0,("cli_rpc_pipe_open_schannel_with_key: server %s " ++ "replied with bad credential\n", ++ rpccli->desthost)); ++ TALLOC_FREE(rpccli); ++ return NT_STATUS_INVALID_NETWORK_RESPONSE; ++ } ++ *rpccli->dc = save_creds; ++ ++ if (!NT_STATUS_IS_OK(result)) { ++ DEBUG(0, ("dcerpc_netr_LogonGetCapabilities failed with %s\n", ++ nt_errstr(result))); ++ TALLOC_FREE(rpccli); ++ return result; ++ } ++ ++ if (!(save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)) { ++ /* This means AES isn't supported. */ ++ DEBUG(5, ("AES is not negotiated, but netr_LogonGetCapabilities " ++ "was OK - downgrade detected\n")); ++ TALLOC_FREE(rpccli); ++ return NT_STATUS_INVALID_NETWORK_RESPONSE; ++ } ++ ++ if (save_creds.negotiate_flags != capabilities.server_capabilities) { ++ DEBUG(0, ("The client capabilities don't match the server " ++ "capabilities: local[0x%08X] remote[0x%08X]\n", ++ save_creds.negotiate_flags, ++ capabilities.server_capabilities)); ++ TALLOC_FREE(rpccli); ++ return NT_STATUS_INVALID_NETWORK_RESPONSE; ++ } ++ ++done: + DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s " + "for domain %s and bound using schannel.\n", + get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), +-- +1.9.3 + + +From 675be19880c2ac4bca14d69592ce39bb66a34dec Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 25 Apr 2013 18:30:36 +0200 +Subject: [PATCH 062/249] s3:rpc_client: remove netr_LogonGetCapabilities check + from rpc_pipe_bind* + +It's done in the caller now. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 3302356226cca474f0afab9a129220241c16663f) +--- + source3/rpc_client/cli_pipe.c | 150 +----------------------------------------- + 1 file changed, 1 insertion(+), 149 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 314eb92..cba055a 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -1568,15 +1568,9 @@ struct rpc_pipe_bind_state { + DATA_BLOB rpc_out; + bool auth3; + uint32_t rpc_call_id; +- struct netr_Authenticator auth; +- struct netr_Authenticator return_auth; +- struct netlogon_creds_CredentialState *creds; +- union netr_Capabilities capabilities; +- struct netr_LogonGetCapabilities r; + }; + + static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq); +-static void rpc_pipe_bind_step_two_trigger(struct tevent_req *req); + static NTSTATUS rpc_bind_next_send(struct tevent_req *req, + struct rpc_pipe_bind_state *state, + DATA_BLOB *credentials); +@@ -1679,14 +1673,11 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) + + case DCERPC_AUTH_TYPE_NONE: + case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM: ++ case DCERPC_AUTH_TYPE_SCHANNEL: + /* Bind complete. */ + tevent_req_done(req); + return; + +- case DCERPC_AUTH_TYPE_SCHANNEL: +- rpc_pipe_bind_step_two_trigger(req); +- return; +- + case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_SPNEGO: + case DCERPC_AUTH_TYPE_KRB5: +@@ -1763,145 +1754,6 @@ err_out: + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + } + +-static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq); +- +-static void rpc_pipe_bind_step_two_trigger(struct tevent_req *req) +-{ +- struct rpc_pipe_bind_state *state = +- tevent_req_data(req, +- struct rpc_pipe_bind_state); +- struct dcerpc_binding_handle *b = state->cli->binding_handle; +- struct schannel_state *schannel_auth = +- talloc_get_type_abort(state->cli->auth->auth_ctx, +- struct schannel_state); +- struct tevent_req *subreq; +- +- if (schannel_auth == NULL || +- !ndr_syntax_id_equal(&state->cli->abstract_syntax, +- &ndr_table_netlogon.syntax_id)) { +- tevent_req_done(req); +- return; +- } +- +- ZERO_STRUCT(state->return_auth); +- +- state->creds = netlogon_creds_copy(state, schannel_auth->creds); +- if (state->creds == NULL) { +- tevent_req_nterror(req, NT_STATUS_NO_MEMORY); +- return; +- } +- +- netlogon_creds_client_authenticator(state->creds, &state->auth); +- +- state->r.in.server_name = state->cli->srv_name_slash; +- state->r.in.computer_name = state->creds->computer_name; +- state->r.in.credential = &state->auth; +- state->r.in.query_level = 1; +- state->r.in.return_authenticator = &state->return_auth; +- +- state->r.out.capabilities = &state->capabilities; +- state->r.out.return_authenticator = &state->return_auth; +- +- subreq = dcerpc_netr_LogonGetCapabilities_r_send(talloc_tos(), +- state->ev, +- b, +- &state->r); +- if (subreq == NULL) { +- tevent_req_nterror(req, NT_STATUS_NO_MEMORY); +- return; +- } +- +- tevent_req_set_callback(subreq, rpc_pipe_bind_step_two_done, req); +- return; +-} +- +-static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq) +-{ +- struct tevent_req *req = +- tevent_req_callback_data(subreq, +- struct tevent_req); +- struct rpc_pipe_bind_state *state = +- tevent_req_data(req, +- struct rpc_pipe_bind_state); +- NTSTATUS status; +- +- status = dcerpc_netr_LogonGetCapabilities_r_recv(subreq, talloc_tos()); +- TALLOC_FREE(subreq); +- if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { +- if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { +- DEBUG(5, ("AES is not supported and the error was %s\n", +- nt_errstr(status))); +- tevent_req_nterror(req, +- NT_STATUS_INVALID_NETWORK_RESPONSE); +- return; +- } +- +- /* This is probably NT */ +- DEBUG(5, ("We are checking against an NT - %s\n", +- nt_errstr(status))); +- tevent_req_done(req); +- return; +- } else if (!NT_STATUS_IS_OK(status)) { +- DEBUG(0, ("dcerpc_netr_LogonGetCapabilities_r_recv failed with %s\n", +- nt_errstr(status))); +- tevent_req_nterror(req, status); +- return; +- } +- +- if (NT_STATUS_EQUAL(state->r.out.result, NT_STATUS_NOT_IMPLEMENTED)) { +- if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { +- /* This means AES isn't supported. */ +- DEBUG(5, ("AES is not supported and the error was %s\n", +- nt_errstr(state->r.out.result))); +- tevent_req_nterror(req, +- NT_STATUS_INVALID_NETWORK_RESPONSE); +- return; +- } +- +- /* This is probably an old Samba version */ +- DEBUG(5, ("We are checking against an old Samba version - %s\n", +- nt_errstr(state->r.out.result))); +- tevent_req_done(req); +- return; +- } +- +- /* We need to check the credential state here, cause win2k3 and earlier +- * returns NT_STATUS_NOT_IMPLEMENTED */ +- if (!netlogon_creds_client_check(state->creds, +- &state->r.out.return_authenticator->cred)) { +- /* +- * Server replied with bad credential. Fail. +- */ +- DEBUG(0,("rpc_pipe_bind_step_two_done: server %s " +- "replied with bad credential\n", +- state->cli->desthost)); +- tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL); +- return; +- } +- +- if (!NT_STATUS_IS_OK(state->r.out.result)) { +- DEBUG(0, ("dcerpc_netr_LogonGetCapabilities_r_recv failed with %s\n", +- nt_errstr(state->r.out.result))); +- tevent_req_nterror(req, state->r.out.result); +- return; +- } +- +- if (!(state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)) { +- DEBUG(0, ("netr_LogonGetCapabilities is supported by %s, " +- "but AES was not negotiated - downgrade detected", +- state->cli->desthost)); +- tevent_req_nterror(req, +- NT_STATUS_INVALID_NETWORK_RESPONSE); +- return; +- } +- +- TALLOC_FREE(state->cli->dc); +- state->cli->dc = talloc_move(state->cli, &state->creds); +- +- tevent_req_done(req); +- return; +-} +- + static NTSTATUS rpc_bind_next_send(struct tevent_req *req, + struct rpc_pipe_bind_state *state, + DATA_BLOB *auth_token) +-- +1.9.3 + + +From f9b4e38b8458ec905b5f78e402f21f23c4a967e1 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 25 Apr 2013 19:33:28 +0200 +Subject: [PATCH 063/249] s3:rpc_client: remove unused + cli_rpc_pipe_open_ntlmssp_auth_schannel() + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 04938cbeecc777f7b799a11f1ca0461b351d968a) +--- + source3/rpc_client/cli_pipe.h | 9 ---- + source3/rpc_client/cli_pipe_schannel.c | 80 ---------------------------------- + 2 files changed, 89 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h +index 8eb6040..ab99373 100644 +--- a/source3/rpc_client/cli_pipe.h ++++ b/source3/rpc_client/cli_pipe.h +@@ -109,15 +109,6 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + struct netlogon_creds_CredentialState **pdc, + struct rpc_pipe_client **presult); + +-NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, +- const struct ndr_interface_table *table, +- enum dcerpc_transport_t transport, +- enum dcerpc_AuthLevel auth_level, +- const char *domain, +- const char *username, +- const char *password, +- struct rpc_pipe_client **presult); +- + NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, + const struct ndr_interface_table *table, + enum dcerpc_transport_t transport, +diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c +index de745c0..aaae44b 100644 +--- a/source3/rpc_client/cli_pipe_schannel.c ++++ b/source3/rpc_client/cli_pipe_schannel.c +@@ -86,86 +86,6 @@ static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon + + /**************************************************************************** + Open a named pipe to an SMB server and bind using schannel (bind type 68). +- Fetch the session key ourselves using a temporary netlogon pipe. This +- version uses an ntlmssp auth bound netlogon pipe to get the key. +- ****************************************************************************/ +- +-static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli, +- const char *domain, +- const char *username, +- const char *password, +- uint32 *pneg_flags, +- struct rpc_pipe_client **presult) +-{ +- struct rpc_pipe_client *netlogon_pipe = NULL; +- NTSTATUS status; +- +- status = cli_rpc_pipe_open_spnego( +- cli, &ndr_table_netlogon, NCACN_NP, +- GENSEC_OID_NTLMSSP, +- DCERPC_AUTH_LEVEL_PRIVACY, +- smbXcli_conn_remote_name(cli->conn), +- domain, username, password, &netlogon_pipe); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- +- status = get_schannel_session_key_common(netlogon_pipe, cli, domain, +- pneg_flags); +- if (!NT_STATUS_IS_OK(status)) { +- TALLOC_FREE(netlogon_pipe); +- return status; +- } +- +- *presult = netlogon_pipe; +- return NT_STATUS_OK; +-} +- +-/**************************************************************************** +- Open a named pipe to an SMB server and bind using schannel (bind type 68). +- Fetch the session key ourselves using a temporary netlogon pipe. This version +- uses an ntlmssp bind to get the session key. +- ****************************************************************************/ +- +-NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, +- const struct ndr_interface_table *table, +- enum dcerpc_transport_t transport, +- enum dcerpc_AuthLevel auth_level, +- const char *domain, +- const char *username, +- const char *password, +- struct rpc_pipe_client **presult) +-{ +- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | +- NETLOGON_NEG_SUPPORTS_AES; +- struct rpc_pipe_client *netlogon_pipe = NULL; +- struct rpc_pipe_client *result = NULL; +- NTSTATUS status; +- +- status = get_schannel_session_key_auth_ntlmssp( +- cli, domain, username, password, &neg_flags, &netlogon_pipe); +- if (!NT_STATUS_IS_OK(status)) { +- DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session " +- "key from server %s for domain %s.\n", +- smbXcli_conn_remote_name(cli->conn), domain )); +- return status; +- } +- +- status = cli_rpc_pipe_open_schannel_with_key( +- cli, table, transport, auth_level, domain, &netlogon_pipe->dc, +- &result); +- +- /* Now we've bound using the session key we can close the netlog pipe. */ +- TALLOC_FREE(netlogon_pipe); +- +- if (NT_STATUS_IS_OK(status)) { +- *presult = result; +- } +- return status; +-} +- +-/**************************************************************************** +- Open a named pipe to an SMB server and bind using schannel (bind type 68). + Fetch the session key ourselves using a temporary netlogon pipe. + ****************************************************************************/ + +-- +1.9.3 + + +From 35d07a4d7ca15e4cf22f7cc96d6958c9856dc0a0 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sat, 3 Aug 2013 11:26:13 +0200 +Subject: [PATCH 064/249] auth/gensec: first check GENSEC_FEATURE_SESSION_KEY + before returning NOT_IMPLEMENTED + +Preferr NT_STATUS_NO_USER_SESSION_KEY as return value of gensec_session_key(). + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 45c74c8084d2db14fef6a79cd98068be2ab73f30) +--- + auth/gensec/gensec.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c +index ea62861..9a8f0ef 100644 +--- a/auth/gensec/gensec.c ++++ b/auth/gensec/gensec.c +@@ -155,13 +155,14 @@ _PUBLIC_ NTSTATUS gensec_session_key(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + DATA_BLOB *session_key) + { +- if (!gensec_security->ops->session_key) { +- return NT_STATUS_NOT_IMPLEMENTED; +- } + if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SESSION_KEY)) { + return NT_STATUS_NO_USER_SESSION_KEY; + } + ++ if (!gensec_security->ops->session_key) { ++ return NT_STATUS_NOT_IMPLEMENTED; ++ } ++ + return gensec_security->ops->session_key(gensec_security, mem_ctx, session_key); + } + +-- +1.9.3 + + +From 6eda030bd26347cef3fb670b0876956c97c00bfa Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sat, 3 Aug 2013 11:43:58 +0200 +Subject: [PATCH 065/249] auth/gensec: add gensec_security_by_auth_type() + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 59b09564a7edac8dc241269587146342244ce58b) +--- + auth/gensec/gensec.h | 3 +++ + auth/gensec/gensec_start.c | 26 ++++++++++++++++++++++++++ + 2 files changed, 29 insertions(+) + +diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h +index 396a16d..c080861 100644 +--- a/auth/gensec/gensec.h ++++ b/auth/gensec/gensec.h +@@ -268,6 +268,9 @@ const struct gensec_security_ops *gensec_security_by_oid(struct gensec_security + const char *oid_string); + const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_security *gensec_security, + const char *sasl_name); ++const struct gensec_security_ops *gensec_security_by_auth_type( ++ struct gensec_security *gensec_security, ++ uint32_t auth_type); + struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx); + const struct gensec_security_ops_wrapper *gensec_security_by_oid_list( +diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c +index e46f0ee..c2cfa1c 100644 +--- a/auth/gensec/gensec_start.c ++++ b/auth/gensec/gensec_start.c +@@ -246,6 +246,32 @@ _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name( + return NULL; + } + ++_PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type( ++ struct gensec_security *gensec_security, ++ uint32_t auth_type) ++{ ++ int i; ++ struct gensec_security_ops **backends; ++ const struct gensec_security_ops *backend; ++ TALLOC_CTX *mem_ctx = talloc_new(gensec_security); ++ if (!mem_ctx) { ++ return NULL; ++ } ++ backends = gensec_security_mechs(gensec_security, mem_ctx); ++ for (i=0; backends && backends[i]; i++) { ++ if (!gensec_security_ops_enabled(backends[i], gensec_security)) ++ continue; ++ if (backends[i]->auth_type == auth_type) { ++ backend = backends[i]; ++ talloc_free(mem_ctx); ++ return backend; ++ } ++ } ++ talloc_free(mem_ctx); ++ ++ return NULL; ++} ++ + static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security, + const char *name) + { +-- +1.9.3 + + +From f4e1506ed3a032d38605207f592cbc4ece93a414 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 24 Apr 2013 12:33:28 +0200 +Subject: [PATCH 066/249] libcli/auth: maintain the sequence number for the + NETLOGON SSP as 64bit + +See [MS-NPRC] 3.3.4.2 The Netlogon Signature Token. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 9f2e81ae02549369db49c05edf7071612a03a8b8) +--- + libcli/auth/schannel.h | 2 +- + libcli/auth/schannel_sign.c | 17 +++++++++++++---- + source3/librpc/rpc/dcerpc_helpers.c | 4 ++-- + 3 files changed, 16 insertions(+), 7 deletions(-) + +diff --git a/libcli/auth/schannel.h b/libcli/auth/schannel.h +index bfccd95..271b5bb 100644 +--- a/libcli/auth/schannel.h ++++ b/libcli/auth/schannel.h +@@ -30,7 +30,7 @@ enum schannel_position { + + struct schannel_state { + enum schannel_position state; +- uint32_t seq_num; ++ uint64_t seq_num; + bool initiator; + struct netlogon_creds_CredentialState *creds; + }; +diff --git a/libcli/auth/schannel_sign.c b/libcli/auth/schannel_sign.c +index 1871da2..6e5d454 100644 +--- a/libcli/auth/schannel_sign.c ++++ b/libcli/auth/schannel_sign.c +@@ -24,6 +24,17 @@ + #include "../libcli/auth/schannel.h" + #include "../lib/crypto/crypto.h" + ++#define SETUP_SEQNUM(state, buf, initiator) do { \ ++ uint8_t *_buf = buf; \ ++ uint32_t _seq_num_low = (state)->seq_num & UINT32_MAX; \ ++ uint32_t _seq_num_high = (state)->seq_num >> 32; \ ++ if (initiator) { \ ++ _seq_num_high |= 0x80000000; \ ++ } \ ++ RSIVAL(_buf, 0, _seq_num_low); \ ++ RSIVAL(_buf, 4, _seq_num_high); \ ++} while(0) ++ + static void netsec_offset_and_sizes(struct schannel_state *state, + bool do_seal, + uint32_t *_min_sig_size, +@@ -255,8 +266,7 @@ NTSTATUS netsec_incoming_packet(struct schannel_state *state, + confounder = NULL; + } + +- RSIVAL(seq_num, 0, state->seq_num); +- SIVAL(seq_num, 4, state->initiator?0:0x80); ++ SETUP_SEQNUM(state, seq_num, !state->initiator); + + if (do_unseal) { + netsec_do_seal(state, seq_num, +@@ -325,8 +335,7 @@ NTSTATUS netsec_outgoing_packet(struct schannel_state *state, + &checksum_length, + &confounder_ofs); + +- RSIVAL(seq_num, 0, state->seq_num); +- SIVAL(seq_num, 4, state->initiator?0x80:0); ++ SETUP_SEQNUM(state, seq_num, state->initiator); + + if (do_seal) { + confounder = _confounder; +diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c +index a55e419..0095990 100644 +--- a/source3/librpc/rpc/dcerpc_helpers.c ++++ b/source3/librpc/rpc/dcerpc_helpers.c +@@ -462,8 +462,8 @@ static NTSTATUS add_schannel_auth_footer(struct schannel_state *sas, + return NT_STATUS_INVALID_PARAMETER; + } + +- DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n", +- sas->seq_num)); ++ DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%llu\n", ++ (unsigned long long)sas->seq_num)); + + switch (auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: +-- +1.9.3 + + +From f99afc1924dbb267e696bbdf26db606a8c77f093 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 2 Aug 2013 12:53:42 +0200 +Subject: [PATCH 067/249] libcli/auth: add netsec_create_state() + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 33215398f32c76f4b8ada7b547c6d0741cb2ac16) +--- + libcli/auth/schannel_proto.h | 3 +++ + libcli/auth/schannel_sign.c | 23 +++++++++++++++++++++++ + 2 files changed, 26 insertions(+) + +diff --git a/libcli/auth/schannel_proto.h b/libcli/auth/schannel_proto.h +index 0414218..da76559 100644 +--- a/libcli/auth/schannel_proto.h ++++ b/libcli/auth/schannel_proto.h +@@ -28,6 +28,9 @@ struct schannel_state; + struct db_context *open_schannel_session_store(TALLOC_CTX *mem_ctx, + struct loadparm_context *lp_ctx); + ++struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_CredentialState *creds, ++ bool initiator); + NTSTATUS netsec_incoming_packet(struct schannel_state *state, + bool do_unseal, + uint8_t *data, size_t length, +diff --git a/libcli/auth/schannel_sign.c b/libcli/auth/schannel_sign.c +index 6e5d454..518a6a9 100644 +--- a/libcli/auth/schannel_sign.c ++++ b/libcli/auth/schannel_sign.c +@@ -35,6 +35,29 @@ + RSIVAL(_buf, 4, _seq_num_high); \ + } while(0) + ++struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_CredentialState *creds, ++ bool initiator) ++{ ++ struct schannel_state *state; ++ ++ state = talloc(mem_ctx, struct schannel_state); ++ if (state == NULL) { ++ return NULL; ++ } ++ ++ state->state = SCHANNEL_STATE_UPDATE_1; ++ state->initiator = initiator; ++ state->seq_num = 0; ++ state->creds = netlogon_creds_copy(state, creds); ++ if (state->creds == NULL) { ++ talloc_free(state); ++ return NULL; ++ } ++ ++ return state; ++} ++ + static void netsec_offset_and_sizes(struct schannel_state *state, + bool do_seal, + uint32_t *_min_sig_size, +-- +1.9.3 + + +From f13417a00173fcde96417773a1a551caced24c8b Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 2 Aug 2013 13:28:11 +0200 +Subject: [PATCH 068/249] s3:cli_pipe: make use of netsec_create_state() + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit e96142fc439efb7c90719f9c387778c4218ae637) +--- + source3/rpc_client/cli_pipe.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index cba055a..9e979b0 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -2271,18 +2271,11 @@ static NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, + goto fail; + } + +- schannel_auth = talloc_zero(result, struct schannel_state); ++ schannel_auth = netsec_create_state(result, creds, true /* initiator */); + if (schannel_auth == NULL) { + goto fail; + } + +- schannel_auth->state = SCHANNEL_STATE_START; +- schannel_auth->initiator = true; +- schannel_auth->creds = netlogon_creds_copy(schannel_auth, creds); +- if (schannel_auth->creds == NULL) { +- goto fail; +- } +- + result->auth_ctx = schannel_auth; + *presult = result; + return NT_STATUS_OK; +-- +1.9.3 + + +From becf68bc072fdfab4489326d148775ebdbe27fda Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 2 Aug 2013 13:28:59 +0200 +Subject: [PATCH 069/249] s3:cli_pipe: pass down creds->computer_name to + NL_AUTH_MESSAGE + +We need to use the same computer_name value as in the netr_Authenticate3() +request. + +We abuse cli->auth->user_name to pass the value down. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 838cb539621ef19cac6badb4b10678dcc3a6f68a) +--- + source3/rpc_client/cli_pipe.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 9e979b0..1de71fb 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -1027,13 +1027,12 @@ static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli, + NTSTATUS status; + struct NL_AUTH_MESSAGE r; + +- /* Use lp_workgroup() if domain not specified */ ++ if (!cli->auth->user_name || !cli->auth->user_name[0]) { ++ return NT_STATUS_INVALID_PARAMETER_MIX; ++ } + + if (!cli->auth->domain || !cli->auth->domain[0]) { +- cli->auth->domain = talloc_strdup(cli, lp_workgroup()); +- if (cli->auth->domain == NULL) { +- return NT_STATUS_NO_MEMORY; +- } ++ return NT_STATUS_INVALID_PARAMETER_MIX; + } + + /* +@@ -1044,7 +1043,7 @@ static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli, + r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | + NL_FLAG_OEM_NETBIOS_COMPUTER_NAME; + r.oem_netbios_domain.a = cli->auth->domain; +- r.oem_netbios_computer.a = lp_netbios_name(); ++ r.oem_netbios_computer.a = cli->auth->user_name; + + status = dcerpc_push_schannel_bind(cli, &r, auth_token); + if (!NT_STATUS_IS_OK(status)) { +@@ -2265,7 +2264,7 @@ static NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, + result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL; + result->auth_level = auth_level; + +- result->user_name = talloc_strdup(result, ""); ++ result->user_name = talloc_strdup(result, creds->computer_name); + result->domain = talloc_strdup(result, domain); + if ((result->user_name == NULL) || (result->domain == NULL)) { + goto fail; +-- +1.9.3 + + +From b447ab32047f33d306ee891d1d3fe2ae5a8c56f1 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sat, 3 Aug 2013 08:50:54 +0200 +Subject: [PATCH 070/249] s3:cli_pipe.c: return NO_USER_SESSION_KEY in + cli_get_session_key() for schannel + +SCHANNEL connections don't have a user session key, +they're like anonymous connections. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit af4dc306846a30a5a1201306cc2cbf4d494e16e7) +--- + source3/rpc_client/cli_pipe.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 1de71fb..470469f 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -3091,7 +3091,6 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, + { + NTSTATUS status; + struct pipe_auth_data *a; +- struct schannel_state *schannel_auth; + struct gensec_security *gensec_security; + DATA_BLOB sk = data_blob_null; + bool make_dup = false; +@@ -3107,12 +3106,6 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, + } + + switch (cli->auth->auth_type) { +- case DCERPC_AUTH_TYPE_SCHANNEL: +- schannel_auth = talloc_get_type_abort(a->auth_ctx, +- struct schannel_state); +- sk = data_blob_const(schannel_auth->creds->session_key, 16); +- make_dup = true; +- break; + case DCERPC_AUTH_TYPE_SPNEGO: + case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_KRB5: +-- +1.9.3 + + +From abebeb10c26f6fa7e61c56553ce1e52b5d45937a Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 2 Aug 2013 13:33:37 +0200 +Subject: [PATCH 071/249] s3:rpc_server: make use of netsec_create_state() + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit a964309bf7631f4f6953e0d6556f8ed8e5300dcc) +--- + source3/rpc_server/srv_pipe.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c +index 7daff04..9043a14 100644 +--- a/source3/rpc_server/srv_pipe.c ++++ b/source3/rpc_server/srv_pipe.c +@@ -462,8 +462,8 @@ static bool pipe_schannel_auth_bind(struct pipes_struct *p, + */ + + become_root(); +- status = schannel_get_creds_state(p, lp_ctx, +- neg.oem_netbios_computer.a, &creds); ++ status = schannel_get_creds_state(p->mem_ctx, lp_ctx, ++ neg.oem_netbios_computer.a, &creds); + unbecome_root(); + + talloc_unlink(p, lp_ctx); +@@ -472,16 +472,12 @@ static bool pipe_schannel_auth_bind(struct pipes_struct *p, + return False; + } + +- schannel_auth = talloc_zero(p, struct schannel_state); ++ schannel_auth = netsec_create_state(p, creds, false /* not initiator */); ++ TALLOC_FREE(creds); + if (!schannel_auth) { +- TALLOC_FREE(creds); + return False; + } + +- schannel_auth->state = SCHANNEL_STATE_START; +- schannel_auth->initiator = false; +- schannel_auth->creds = creds; +- + /* + * JRA. Should we also copy the schannel session key into the pipe session key p->session_key + * here ? We do that for NTLMSSP, but the session key is already set up from the vuser +-- +1.9.3 + + +From b567c4ef93de5c098d724c15b614f5f233903812 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 2 Aug 2013 13:36:30 +0200 +Subject: [PATCH 072/249] s3:dcerpc_helpers: remove unused DEBUG message of + schannel_state->seq_num. + +This is a layer violation and not needed anymore as we know +how the seqnum handling works now. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit a36ccdc83edb7437dd00601c459421286fd79db4) +--- + source3/librpc/rpc/dcerpc_helpers.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c +index 0095990..97999d7 100644 +--- a/source3/librpc/rpc/dcerpc_helpers.c ++++ b/source3/librpc/rpc/dcerpc_helpers.c +@@ -462,9 +462,6 @@ static NTSTATUS add_schannel_auth_footer(struct schannel_state *sas, + return NT_STATUS_INVALID_PARAMETER; + } + +- DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%llu\n", +- (unsigned long long)sas->seq_num)); +- + switch (auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + status = netsec_outgoing_packet(sas, +-- +1.9.3 + + +From e044773b51b76b3582669ee7e3a388d6471e2f2e Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 2 Aug 2013 10:08:54 +0200 +Subject: [PATCH 073/249] s4:libnet: avoid usage of dcerpc_schannel_creds() + +We use cli_credentials_get_netlogon_creds() which returns the same value. + +dcerpc_schannel_creds() is a layer violation. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit c0144273af8f0956a05d102113c40cec77069f7a) +--- + source4/libnet/libnet_samsync.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/source4/libnet/libnet_samsync.c b/source4/libnet/libnet_samsync.c +index 9629b9f..206d81e 100644 +--- a/source4/libnet/libnet_samsync.c ++++ b/source4/libnet/libnet_samsync.c +@@ -25,7 +25,6 @@ + #include "libcli/auth/libcli_auth.h" + #include "../libcli/samsync/samsync.h" + #include "auth/gensec/gensec.h" +-#include "auth/gensec/schannel.h" + #include "auth/credentials/credentials.h" + #include "libcli/auth/schannel.h" + #include "librpc/gen_ndr/ndr_netlogon.h" +@@ -183,9 +182,9 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx + + /* get NETLOGON credentials */ + +- nt_status = dcerpc_schannel_creds(p->conn->security_state.generic_state, samsync_ctx, &creds); +- if (!NT_STATUS_IS_OK(nt_status)) { +- r->out.error_string = talloc_strdup(mem_ctx, "Could not obtain NETLOGON credentials from DCERPC/GENSEC layer"); ++ creds = cli_credentials_get_netlogon_creds(machine_account); ++ if (creds == NULL) { ++ r->out.error_string = talloc_strdup(mem_ctx, "Could not obtain NETLOGON credentials from credentials"); + talloc_free(samsync_ctx); + return nt_status; + } +-- +1.9.3 + + +From 322dc86454fc4e60de641ef02da2c2744c347001 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 2 Aug 2013 10:08:54 +0200 +Subject: [PATCH 074/249] s4:torture: avoid usage of dcerpc_schannel_creds() + +We use cli_credentials_get_netlogon_creds() which returns the same value. + +dcerpc_schannel_creds() is a layer violation. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 2ea3a24dced0814100e352bbbca124011be73602) +--- + source4/torture/rpc/samlogon.c | 5 ++--- + source4/torture/rpc/samr.c | 6 +++--- + source4/torture/rpc/samsync.c | 11 ++++------- + source4/torture/rpc/schannel.c | 6 ++---- + 4 files changed, 11 insertions(+), 17 deletions(-) + +diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c +index 4861038..886ff39 100644 +--- a/source4/torture/rpc/samlogon.c ++++ b/source4/torture/rpc/samlogon.c +@@ -29,7 +29,6 @@ + #include "lib/cmdline/popt_common.h" + #include "torture/rpc/torture_rpc.h" + #include "auth/gensec/gensec.h" +-#include "auth/gensec/schannel.h" + #include "libcli/auth/libcli_auth.h" + #include "param/param.h" + +@@ -1764,8 +1763,8 @@ bool torture_rpc_samlogon(struct torture_context *torture) + torture_assert_ntstatus_ok_goto(torture, status, ret, failed, + talloc_asprintf(torture, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status))); + +- status = dcerpc_schannel_creds(p->conn->security_state.generic_state, mem_ctx, &creds); +- if (!NT_STATUS_IS_OK(status)) { ++ creds = cli_credentials_get_netlogon_creds(machine_credentials); ++ if (creds == NULL) { + ret = false; + goto failed; + } +diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c +index cdfa2b8..d4d64f9 100644 +--- a/source4/torture/rpc/samr.c ++++ b/source4/torture/rpc/samr.c +@@ -37,7 +37,6 @@ + #include "torture/rpc/torture_rpc.h" + #include "param/param.h" + #include "auth/gensec/gensec.h" +-#include "auth/gensec/schannel.h" + #include "auth/gensec/gensec_proto.h" + #include "../libcli/auth/schannel.h" + +@@ -2959,6 +2958,7 @@ static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b, + + static bool test_SamLogon(struct torture_context *tctx, + struct dcerpc_pipe *p, ++ struct cli_credentials *machine_credentials, + struct cli_credentials *test_credentials, + NTSTATUS expected_result, + bool interactive) +@@ -2978,7 +2978,7 @@ static bool test_SamLogon(struct torture_context *tctx, + struct netr_Authenticator a; + struct dcerpc_binding_handle *b = p->binding_handle; + +- torture_assert_ntstatus_ok(tctx, dcerpc_schannel_creds(p->conn->security_state.generic_state, tctx, &creds), ""); ++ torture_assert(tctx, (creds = cli_credentials_get_netlogon_creds(machine_credentials)), ""); + + if (lpcfg_client_lanman_auth(tctx->lp_ctx)) { + flags |= CLI_CRED_LANMAN_AUTH; +@@ -3105,7 +3105,7 @@ static bool test_SamLogon_with_creds(struct torture_context *tctx, + torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n", + interactive ? "interactive" : "network", acct_name, password); + +- if (!test_SamLogon(tctx, p, test_credentials, ++ if (!test_SamLogon(tctx, p, machine_creds, test_credentials, + expected_samlogon_result, interactive)) { + torture_warning(tctx, "new password did not work\n"); + ret = false; +diff --git a/source4/torture/rpc/samsync.c b/source4/torture/rpc/samsync.c +index 81027d0..15cab73 100644 +--- a/source4/torture/rpc/samsync.c ++++ b/source4/torture/rpc/samsync.c +@@ -27,7 +27,6 @@ + #include "system/time.h" + #include "torture/rpc/torture_rpc.h" + #include "auth/gensec/gensec.h" +-#include "auth/gensec/schannel.h" + #include "libcli/auth/libcli_auth.h" + #include "libcli/samsync/samsync.h" + #include "libcli/security/security.h" +@@ -1720,9 +1719,8 @@ bool torture_rpc_samsync(struct torture_context *torture) + } + samsync_state->b = samsync_state->p->binding_handle; + +- status = dcerpc_schannel_creds(samsync_state->p->conn->security_state.generic_state, +- samsync_state, &samsync_state->creds); +- if (!NT_STATUS_IS_OK(status)) { ++ samsync_state->creds = cli_credentials_get_netlogon_creds(credentials); ++ if (samsync_state->creds == NULL) { + ret = false; + } + +@@ -1758,9 +1756,8 @@ bool torture_rpc_samsync(struct torture_context *torture) + goto failed; + } + +- status = dcerpc_schannel_creds(samsync_state->p_netlogon_wksta->conn->security_state.generic_state, +- samsync_state, &samsync_state->creds_netlogon_wksta); +- if (!NT_STATUS_IS_OK(status)) { ++ samsync_state->creds_netlogon_wksta = cli_credentials_get_netlogon_creds(credentials_wksta); ++ if (samsync_state->creds_netlogon_wksta == NULL) { + torture_comment(torture, "Failed to obtail schanel creds!\n"); + ret = false; + } +diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c +index 8203749..0098dcf 100644 +--- a/source4/torture/rpc/schannel.c ++++ b/source4/torture/rpc/schannel.c +@@ -26,14 +26,12 @@ + #include "auth/credentials/credentials.h" + #include "torture/rpc/torture_rpc.h" + #include "lib/cmdline/popt_common.h" +-#include "auth/gensec/schannel.h" + #include "../libcli/auth/schannel.h" + #include "libcli/auth/libcli_auth.h" + #include "libcli/security/security.h" + #include "system/filesys.h" + #include "param/param.h" + #include "librpc/rpc/dcerpc_proto.h" +-#include "auth/gensec/gensec.h" + #include "libcli/composite/composite.h" + #include "lib/events/events.h" + +@@ -413,8 +411,8 @@ static bool test_schannel(struct torture_context *tctx, + + torture_assert_ntstatus_ok(tctx, status, "bind auth"); + +- status = dcerpc_schannel_creds(p_netlogon->conn->security_state.generic_state, tctx, &creds); +- torture_assert_ntstatus_ok(tctx, status, "schannel creds"); ++ creds = cli_credentials_get_netlogon_creds(credentials); ++ torture_assert(tctx, (creds != NULL), "schannel creds"); + + /* checks the capabilities */ + torture_assert(tctx, test_netlogon_capabilities(p_netlogon, tctx, credentials, creds), +-- +1.9.3 + + +From fa1c5bc2cdff9decd361c919567c502ef0c09385 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 2 Aug 2013 12:31:41 +0200 +Subject: [PATCH 075/249] s4:gensec/schannel: remove unused + dcerpc_schannel_creds() + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 4cad5dcb6d5e49cc9bb1aa4ca454f369e00e8c6f) +--- + source4/auth/gensec/schannel.c | 23 ----------------------- + source4/auth/gensec/schannel.h | 26 -------------------------- + 2 files changed, 49 deletions(-) + delete mode 100644 source4/auth/gensec/schannel.h + +diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c +index e7c545f..10d2565 100644 +--- a/source4/auth/gensec/schannel.c ++++ b/source4/auth/gensec/schannel.c +@@ -29,7 +29,6 @@ + #include "../libcli/auth/schannel.h" + #include "librpc/rpc/dcerpc.h" + #include "param/param.h" +-#include "auth/gensec/schannel.h" + #include "auth/gensec/gensec_toplevel_proto.h" + + _PUBLIC_ NTSTATUS gensec_schannel_init(void); +@@ -204,28 +203,6 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ + } + + /** +- * Return the struct netlogon_creds_CredentialState. +- * +- * Make sure not to call this unless gensec is using schannel... +- */ +- +-/* TODO: make this non-public */ +- +-_PUBLIC_ NTSTATUS dcerpc_schannel_creds(struct gensec_security *gensec_security, +- TALLOC_CTX *mem_ctx, +- struct netlogon_creds_CredentialState **creds) +-{ +- struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state); +- +- *creds = talloc_reference(mem_ctx, state->creds); +- if (!*creds) { +- return NT_STATUS_NO_MEMORY; +- } +- return NT_STATUS_OK; +-} +- +- +-/** + * Returns anonymous credentials for schannel, matching Win2k3. + * + */ +diff --git a/source4/auth/gensec/schannel.h b/source4/auth/gensec/schannel.h +deleted file mode 100644 +index 88a32a7..0000000 +--- a/source4/auth/gensec/schannel.h ++++ /dev/null +@@ -1,26 +0,0 @@ +-/* +- Unix SMB/CIFS implementation. +- +- dcerpc schannel operations +- +- Copyright (C) Andrew Tridgell 2004 +- Copyright (C) Andrew Bartlett 2004-2005 +- +- 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 . +-*/ +- +-struct netlogon_creds_CredentialState; +-NTSTATUS dcerpc_schannel_creds(struct gensec_security *gensec_security, +- TALLOC_CTX *mem_ctx, +- struct netlogon_creds_CredentialState **creds); +-- +1.9.3 + + +From eeb52af669e963ac856fc77be6a47f7ed33d8580 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 2 Aug 2013 13:04:07 +0200 +Subject: [PATCH 076/249] s4:gensec/schannel: simplify the code by using + netsec_create_state() + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 49f347eb11bd12a3f25b0fcb8ba36d4a36594868) +--- + source4/auth/gensec/schannel.c | 98 +++++++++++++----------------------------- + 1 file changed, 30 insertions(+), 68 deletions(-) + +diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c +index 10d2565..3896a41 100644 +--- a/source4/auth/gensec/schannel.c ++++ b/source4/auth/gensec/schannel.c +@@ -35,12 +35,11 @@ _PUBLIC_ NTSTATUS gensec_schannel_init(void); + + static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t data_size) + { +- struct schannel_state *state = (struct schannel_state *)gensec_security->private_data; +- uint32_t sig_size; +- +- sig_size = netsec_outgoing_sig_size(state); ++ struct schannel_state *state = ++ talloc_get_type_abort(gensec_security->private_data, ++ struct schannel_state); + +- return sig_size; ++ return netsec_outgoing_sig_size(state); + } + + static NTSTATUS schannel_session_key(struct gensec_security *gensec_security, +@@ -54,7 +53,9 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ + struct tevent_context *ev, + const DATA_BLOB in, DATA_BLOB *out) + { +- struct schannel_state *state = (struct schannel_state *)gensec_security->private_data; ++ struct schannel_state *state = ++ talloc_get_type(gensec_security->private_data, ++ struct schannel_state); + NTSTATUS status; + enum ndr_err_code ndr_err; + struct NL_AUTH_MESSAGE bind_schannel; +@@ -67,24 +68,22 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ + + switch (gensec_security->gensec_role) { + case GENSEC_CLIENT: +- if (state->state != SCHANNEL_STATE_START) { ++ if (state != NULL) { + /* we could parse the bind ack, but we don't know what it is yet */ + return NT_STATUS_OK; + } + +- state->creds = cli_credentials_get_netlogon_creds(gensec_security->credentials); +- if (state->creds == NULL) { ++ creds = cli_credentials_get_netlogon_creds(gensec_security->credentials); ++ if (creds == NULL) { + return NT_STATUS_INVALID_PARAMETER_MIX; + } +- /* +- * We need to create a reference here or we don't get +- * updates performed on the credentials if we create a +- * copy. +- */ +- state->creds = talloc_reference(state, state->creds); +- if (state->creds == NULL) { ++ ++ state = netsec_create_state(gensec_security, ++ creds, true /* initiator */); ++ if (state == NULL) { + return NT_STATUS_NO_MEMORY; + } ++ gensec_security->private_data = state; + + bind_schannel.MessageType = NL_NEGOTIATE_REQUEST; + #if 0 +@@ -117,12 +116,10 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ + return status; + } + +- state->state = SCHANNEL_STATE_UPDATE_1; +- + return NT_STATUS_MORE_PROCESSING_REQUIRED; + case GENSEC_SERVER: + +- if (state->state != SCHANNEL_STATE_START) { ++ if (state != NULL) { + /* no third leg on this protocol */ + return NT_STATUS_INVALID_PARAMETER; + } +@@ -177,7 +174,12 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ + return status; + } + +- state->creds = talloc_steal(state, creds); ++ state = netsec_create_state(gensec_security, ++ creds, false /* not initiator */); ++ if (state == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ gensec_security->private_data = state; + + bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE; + bind_schannel_ack.Flags = 0; +@@ -195,8 +197,6 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ + return status; + } + +- state->state = SCHANNEL_STATE_UPDATE_1; +- + return NT_STATUS_OK; + } + return NT_STATUS_INVALID_PARAMETER; +@@ -214,54 +214,16 @@ static NTSTATUS schannel_session_info(struct gensec_security *gensec_security, + return auth_anonymous_session_info(mem_ctx, gensec_security->settings->lp_ctx, _session_info); + } + +-static NTSTATUS schannel_start(struct gensec_security *gensec_security) +-{ +- struct schannel_state *state; +- +- state = talloc_zero(gensec_security, struct schannel_state); +- if (!state) { +- return NT_STATUS_NO_MEMORY; +- } +- +- state->state = SCHANNEL_STATE_START; +- gensec_security->private_data = state; +- +- return NT_STATUS_OK; +-} +- + static NTSTATUS schannel_server_start(struct gensec_security *gensec_security) + { +- NTSTATUS status; +- struct schannel_state *state; +- +- status = schannel_start(gensec_security); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- +- state = (struct schannel_state *)gensec_security->private_data; +- state->initiator = false; +- + return NT_STATUS_OK; + } + + static NTSTATUS schannel_client_start(struct gensec_security *gensec_security) + { +- NTSTATUS status; +- struct schannel_state *state; +- +- status = schannel_start(gensec_security); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- +- state = (struct schannel_state *)gensec_security->private_data; +- state->initiator = true; +- + return NT_STATUS_OK; + } + +- + static bool schannel_have_feature(struct gensec_security *gensec_security, + uint32_t feature) + { +@@ -287,8 +249,8 @@ static NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security, + const DATA_BLOB *sig) + { + struct schannel_state *state = +- talloc_get_type(gensec_security->private_data, +- struct schannel_state); ++ talloc_get_type_abort(gensec_security->private_data, ++ struct schannel_state); + + return netsec_incoming_packet(state, true, + discard_const_p(uint8_t, data), +@@ -304,8 +266,8 @@ static NTSTATUS schannel_check_packet(struct gensec_security *gensec_security, + const DATA_BLOB *sig) + { + struct schannel_state *state = +- talloc_get_type(gensec_security->private_data, +- struct schannel_state); ++ talloc_get_type_abort(gensec_security->private_data, ++ struct schannel_state); + + return netsec_incoming_packet(state, false, + discard_const_p(uint8_t, data), +@@ -321,8 +283,8 @@ static NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security, + DATA_BLOB *sig) + { + struct schannel_state *state = +- talloc_get_type(gensec_security->private_data, +- struct schannel_state); ++ talloc_get_type_abort(gensec_security->private_data, ++ struct schannel_state); + + return netsec_outgoing_packet(state, mem_ctx, true, + data, length, sig); +@@ -338,8 +300,8 @@ static NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security, + DATA_BLOB *sig) + { + struct schannel_state *state = +- talloc_get_type(gensec_security->private_data, +- struct schannel_state); ++ talloc_get_type_abort(gensec_security->private_data, ++ struct schannel_state); + + return netsec_outgoing_packet(state, mem_ctx, false, + discard_const_p(uint8_t, data), +-- +1.9.3 + + +From 685f00cfd7be11f4c62441e17d6416b9a668bb47 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 2 Aug 2013 13:25:20 +0200 +Subject: [PATCH 077/249] s4:gensec/schannel: use the correct computer_name + from netlogon_creds_CredentialState + +We need to use the same computer_name we used in the netr_Authenticate3 +request. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit b5104768225ae0308aa3f22f8d9bca389ef3cb3a) +--- + source4/auth/gensec/schannel.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c +index 3896a41..91f166b 100644 +--- a/source4/auth/gensec/schannel.c ++++ b/source4/auth/gensec/schannel.c +@@ -94,17 +94,17 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ + NL_FLAG_UTF8_DNS_DOMAIN_NAME | + NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME; + bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); +- bind_schannel.oem_netbios_computer.a = cli_credentials_get_workstation(gensec_security->credentials); ++ bind_schannel.oem_netbios_computer.a = creds->computer_name; + bind_schannel.utf8_dns_domain = cli_credentials_get_realm(gensec_security->credentials); + /* w2k3 refuses us if we use the full DNS workstation? + why? perhaps because we don't fill in the dNSHostName + attribute in the machine account? */ +- bind_schannel.utf8_netbios_computer = cli_credentials_get_workstation(gensec_security->credentials); ++ bind_schannel.utf8_netbios_computer = creds->computer_name; + #else + bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | + NL_FLAG_OEM_NETBIOS_COMPUTER_NAME; + bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); +- bind_schannel.oem_netbios_computer.a = cli_credentials_get_workstation(gensec_security->credentials); ++ bind_schannel.oem_netbios_computer.a = creds->computer_name; + #endif + + ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel, +-- +1.9.3 + + +From bd54e89fc5eb4d6afed3ef770dabf14a6ac6b060 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sat, 3 Aug 2013 11:21:32 +0200 +Subject: [PATCH 078/249] s4:gensec/schannel: GENSEC_FEATURE_ASYNC_REPLIES is + not supported + +There's a sequence number attached to the connection, +which needs to be incremented with each message... + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit a07049a839729e29ca888bae353cd37fd6238486) +--- + source4/auth/gensec/schannel.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c +index 91f166b..7fc0c7c 100644 +--- a/source4/auth/gensec/schannel.c ++++ b/source4/auth/gensec/schannel.c +@@ -234,9 +234,6 @@ static bool schannel_have_feature(struct gensec_security *gensec_security, + if (feature & GENSEC_FEATURE_DCE_STYLE) { + return true; + } +- if (feature & GENSEC_FEATURE_ASYNC_REPLIES) { +- return true; +- } + return false; + } + +-- +1.9.3 + + +From afcf626800e8aaf94878d62d1fd7318b2ffe21c1 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sat, 3 Aug 2013 11:27:55 +0200 +Subject: [PATCH 079/249] s4:gensec/schannel: there's no point in having + schannel_session_key() + +gensec_session_key() will return NT_STATUS_NO_USER_SESSION_KEY +before calling schannel_session_key(), as we don't provide +GENSEC_FEATURE_SESSION_KEY. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 9b9ab1ae6963b3819dc2b095cbe9e1432f3459b7) +--- + source4/auth/gensec/schannel.c | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c +index 7fc0c7c..ebf6469 100644 +--- a/source4/auth/gensec/schannel.c ++++ b/source4/auth/gensec/schannel.c +@@ -42,13 +42,6 @@ static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t + return netsec_outgoing_sig_size(state); + } + +-static NTSTATUS schannel_session_key(struct gensec_security *gensec_security, +- TALLOC_CTX *mem_ctx, +- DATA_BLOB *session_key) +-{ +- return NT_STATUS_NOT_IMPLEMENTED; +-} +- + static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, + struct tevent_context *ev, + const DATA_BLOB in, DATA_BLOB *out) +@@ -315,7 +308,6 @@ static const struct gensec_security_ops gensec_schannel_security_ops = { + .sign_packet = schannel_sign_packet, + .check_packet = schannel_check_packet, + .unseal_packet = schannel_unseal_packet, +- .session_key = schannel_session_key, + .session_info = schannel_session_info, + .sig_size = schannel_sig_size, + .have_feature = schannel_have_feature, +-- +1.9.3 + + +From 56599b7019eabe3656bdba676214c74191ad068f Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sat, 3 Aug 2013 11:32:31 +0200 +Subject: [PATCH 080/249] s4:gensec/schannel: only require + librpc/gen_ndr/dcerpc.h + +We just need DCERPC_AUTH_TYPE_SCHANNEL + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit e90e1b5c76db4cf589adf8856eb32e5f0d955734) +--- + source4/auth/gensec/schannel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c +index ebf6469..e67432c 100644 +--- a/source4/auth/gensec/schannel.c ++++ b/source4/auth/gensec/schannel.c +@@ -27,7 +27,7 @@ + #include "auth/gensec/gensec.h" + #include "auth/gensec/gensec_proto.h" + #include "../libcli/auth/schannel.h" +-#include "librpc/rpc/dcerpc.h" ++#include "librpc/gen_ndr/dcerpc.h" + #include "param/param.h" + #include "auth/gensec/gensec_toplevel_proto.h" + +-- +1.9.3 + + +From baa82a6ef22c1761c7206323e90781d008a7888b Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 2 Aug 2013 13:37:54 +0200 +Subject: [PATCH 081/249] libcli/auth/schannel: make struct schannel_state + private + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 4c978b68d9a87001f625c10421e7d4cc140b4554) +--- + libcli/auth/schannel.h | 13 ------------- + libcli/auth/schannel_sign.c | 12 ++++++++++++ + 2 files changed, 12 insertions(+), 13 deletions(-) + +diff --git a/libcli/auth/schannel.h b/libcli/auth/schannel.h +index 271b5bb..c53d68e 100644 +--- a/libcli/auth/schannel.h ++++ b/libcli/auth/schannel.h +@@ -22,17 +22,4 @@ + + #include "libcli/auth/libcli_auth.h" + #include "libcli/auth/schannel_state.h" +- +-enum schannel_position { +- SCHANNEL_STATE_START = 0, +- SCHANNEL_STATE_UPDATE_1 +-}; +- +-struct schannel_state { +- enum schannel_position state; +- uint64_t seq_num; +- bool initiator; +- struct netlogon_creds_CredentialState *creds; +-}; +- + #include "libcli/auth/schannel_proto.h" +diff --git a/libcli/auth/schannel_sign.c b/libcli/auth/schannel_sign.c +index 518a6a9..88a6e1e 100644 +--- a/libcli/auth/schannel_sign.c ++++ b/libcli/auth/schannel_sign.c +@@ -24,6 +24,18 @@ + #include "../libcli/auth/schannel.h" + #include "../lib/crypto/crypto.h" + ++enum schannel_position { ++ SCHANNEL_STATE_START = 0, ++ SCHANNEL_STATE_UPDATE_1 ++}; ++ ++struct schannel_state { ++ enum schannel_position state; ++ uint64_t seq_num; ++ bool initiator; ++ struct netlogon_creds_CredentialState *creds; ++}; ++ + #define SETUP_SEQNUM(state, buf, initiator) do { \ + uint8_t *_buf = buf; \ + uint32_t _seq_num_low = (state)->seq_num & UINT32_MAX; \ +-- +1.9.3 + + +From 29806ef23a9826688ace1dc52cd7af554cf83294 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 2 Aug 2013 15:42:21 +0200 +Subject: [PATCH 082/249] libcli/auth/schannel: remove unused schannel_position + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 57bcbb9c50f0a0252110a1e04a2883b511cd9165) +--- + libcli/auth/schannel_sign.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/libcli/auth/schannel_sign.c b/libcli/auth/schannel_sign.c +index 88a6e1e..9502cba 100644 +--- a/libcli/auth/schannel_sign.c ++++ b/libcli/auth/schannel_sign.c +@@ -24,13 +24,7 @@ + #include "../libcli/auth/schannel.h" + #include "../lib/crypto/crypto.h" + +-enum schannel_position { +- SCHANNEL_STATE_START = 0, +- SCHANNEL_STATE_UPDATE_1 +-}; +- + struct schannel_state { +- enum schannel_position state; + uint64_t seq_num; + bool initiator; + struct netlogon_creds_CredentialState *creds; +@@ -58,7 +52,6 @@ struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, + return NULL; + } + +- state->state = SCHANNEL_STATE_UPDATE_1; + state->initiator = initiator; + state->seq_num = 0; + state->creds = netlogon_creds_copy(state, creds); +-- +1.9.3 + + +From a6ad9118c250446ea9571f5ce9895b11ab8537ed Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 5 Aug 2013 07:12:01 +0200 +Subject: [PATCH 083/249] auth/gensec: introduce gensec_internal.h + +We should treat most gensec related structures private. + +It's a long way, but this is a start. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 71c63e85e7a09acb57f6b75284358f2b3b29eeed) +--- + auth/gensec/gensec.c | 1 + + auth/gensec/gensec.h | 100 ++------------------------- + auth/gensec/gensec_internal.h | 127 +++++++++++++++++++++++++++++++++++ + auth/gensec/gensec_start.c | 1 + + auth/gensec/gensec_util.c | 1 + + auth/gensec/spnego.c | 1 + + auth/ntlmssp/gensec_ntlmssp.c | 1 + + auth/ntlmssp/gensec_ntlmssp_server.c | 1 + + auth/ntlmssp/ntlmssp.c | 1 + + auth/ntlmssp/ntlmssp_client.c | 1 + + auth/ntlmssp/ntlmssp_server.c | 1 + + source3/libads/authdata.c | 1 + + source3/librpc/crypto/gse.c | 1 + + source3/libsmb/ntlmssp_wrap.c | 1 + + source3/utils/ntlm_auth.c | 1 + + source4/auth/gensec/cyrus_sasl.c | 1 + + source4/auth/gensec/gensec_gssapi.c | 1 + + source4/auth/gensec/gensec_krb5.c | 1 + + source4/auth/gensec/pygensec.c | 1 + + source4/auth/gensec/schannel.c | 1 + + source4/ldap_server/ldap_backend.c | 1 + + source4/libcli/ldap/ldap_bind.c | 1 + + source4/torture/auth/ntlmssp.c | 1 + + source4/utils/ntlm_auth.c | 1 + + 24 files changed, 153 insertions(+), 96 deletions(-) + create mode 100644 auth/gensec/gensec_internal.h + +diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c +index 9a8f0ef..d364a34 100644 +--- a/auth/gensec/gensec.c ++++ b/auth/gensec/gensec.c +@@ -26,6 +26,7 @@ + #include "lib/tsocket/tsocket.h" + #include "lib/util/tevent_ntstatus.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "librpc/rpc/dcerpc.h" + + /* +diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h +index c080861..5d39d81 100644 +--- a/auth/gensec/gensec.h ++++ b/auth/gensec/gensec.h +@@ -76,6 +76,7 @@ struct gensec_settings; + struct tevent_context; + struct tevent_req; + struct smb_krb5_context; ++struct tsocket_address; + + struct gensec_settings { + struct loadparm_context *lp_ctx; +@@ -93,106 +94,13 @@ struct gensec_settings { + const char *server_netbios_name; + }; + +-struct gensec_security_ops { +- const char *name; +- const char *sasl_name; +- uint8_t auth_type; /* 0 if not offered on DCE-RPC */ +- const char **oid; /* NULL if not offered by SPNEGO */ +- NTSTATUS (*client_start)(struct gensec_security *gensec_security); +- NTSTATUS (*server_start)(struct gensec_security *gensec_security); +- /** +- Determine if a packet has the right 'magic' for this mechanism +- */ +- NTSTATUS (*magic)(struct gensec_security *gensec_security, +- const DATA_BLOB *first_packet); +- NTSTATUS (*update)(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, +- struct tevent_context *ev, +- const DATA_BLOB in, DATA_BLOB *out); +- NTSTATUS (*seal_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx, +- uint8_t *data, size_t length, +- const uint8_t *whole_pdu, size_t pdu_length, +- DATA_BLOB *sig); +- NTSTATUS (*sign_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx, +- const uint8_t *data, size_t length, +- const uint8_t *whole_pdu, size_t pdu_length, +- DATA_BLOB *sig); +- size_t (*sig_size)(struct gensec_security *gensec_security, size_t data_size); +- size_t (*max_input_size)(struct gensec_security *gensec_security); +- size_t (*max_wrapped_size)(struct gensec_security *gensec_security); +- NTSTATUS (*check_packet)(struct gensec_security *gensec_security, +- const uint8_t *data, size_t length, +- const uint8_t *whole_pdu, size_t pdu_length, +- const DATA_BLOB *sig); +- NTSTATUS (*unseal_packet)(struct gensec_security *gensec_security, +- uint8_t *data, size_t length, +- const uint8_t *whole_pdu, size_t pdu_length, +- const DATA_BLOB *sig); +- NTSTATUS (*wrap)(struct gensec_security *gensec_security, +- TALLOC_CTX *mem_ctx, +- const DATA_BLOB *in, +- DATA_BLOB *out); +- NTSTATUS (*unwrap)(struct gensec_security *gensec_security, +- TALLOC_CTX *mem_ctx, +- const DATA_BLOB *in, +- DATA_BLOB *out); +- NTSTATUS (*wrap_packets)(struct gensec_security *gensec_security, +- TALLOC_CTX *mem_ctx, +- const DATA_BLOB *in, +- DATA_BLOB *out, +- size_t *len_processed); +- NTSTATUS (*unwrap_packets)(struct gensec_security *gensec_security, +- TALLOC_CTX *mem_ctx, +- const DATA_BLOB *in, +- DATA_BLOB *out, +- size_t *len_processed); +- NTSTATUS (*packet_full_request)(struct gensec_security *gensec_security, +- DATA_BLOB blob, size_t *size); +- NTSTATUS (*session_key)(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, +- DATA_BLOB *session_key); +- NTSTATUS (*session_info)(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, +- struct auth_session_info **session_info); +- void (*want_feature)(struct gensec_security *gensec_security, +- uint32_t feature); +- bool (*have_feature)(struct gensec_security *gensec_security, +- uint32_t feature); +- NTTIME (*expire_time)(struct gensec_security *gensec_security); +- bool enabled; +- bool kerberos; +- enum gensec_priority priority; +-}; +- +-struct gensec_security_ops_wrapper { +- const struct gensec_security_ops *op; +- const char *oid; +-}; ++struct gensec_security_ops; ++struct gensec_security_ops_wrapper; + + #define GENSEC_INTERFACE_VERSION 0 + +-struct gensec_security { +- const struct gensec_security_ops *ops; +- void *private_data; +- struct cli_credentials *credentials; +- struct gensec_target target; +- enum gensec_role gensec_role; +- bool subcontext; +- uint32_t want_features; +- uint32_t max_update_size; +- uint8_t dcerpc_auth_level; +- struct tsocket_address *local_addr, *remote_addr; +- struct gensec_settings *settings; +- +- /* When we are a server, this may be filled in to provide an +- * NTLM authentication backend, and user lookup (such as if no +- * PAC is found) */ +- struct auth4_context *auth_context; +-}; +- + /* this structure is used by backends to determine the size of some critical types */ +-struct gensec_critical_sizes { +- int interface_version; +- int sizeof_gensec_security_ops; +- int sizeof_gensec_security; +-}; ++struct gensec_critical_sizes; + const struct gensec_critical_sizes *gensec_interface_version(void); + + /* Socket wrapper */ +diff --git a/auth/gensec/gensec_internal.h b/auth/gensec/gensec_internal.h +new file mode 100644 +index 0000000..41b6f0d +--- /dev/null ++++ b/auth/gensec/gensec_internal.h +@@ -0,0 +1,127 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ Generic Authentication Interface ++ ++ Copyright (C) Andrew Tridgell 2003 ++ Copyright (C) Andrew Bartlett 2004-2005 ++ ++ 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 . ++*/ ++ ++#ifndef __GENSEC_INTERNAL_H__ ++#define __GENSEC_INTERNAL_H__ ++ ++struct gensec_security; ++ ++struct gensec_security_ops { ++ const char *name; ++ const char *sasl_name; ++ uint8_t auth_type; /* 0 if not offered on DCE-RPC */ ++ const char **oid; /* NULL if not offered by SPNEGO */ ++ NTSTATUS (*client_start)(struct gensec_security *gensec_security); ++ NTSTATUS (*server_start)(struct gensec_security *gensec_security); ++ /** ++ Determine if a packet has the right 'magic' for this mechanism ++ */ ++ NTSTATUS (*magic)(struct gensec_security *gensec_security, ++ const DATA_BLOB *first_packet); ++ NTSTATUS (*update)(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, ++ struct tevent_context *ev, ++ const DATA_BLOB in, DATA_BLOB *out); ++ NTSTATUS (*seal_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx, ++ uint8_t *data, size_t length, ++ const uint8_t *whole_pdu, size_t pdu_length, ++ DATA_BLOB *sig); ++ NTSTATUS (*sign_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx, ++ const uint8_t *data, size_t length, ++ const uint8_t *whole_pdu, size_t pdu_length, ++ DATA_BLOB *sig); ++ size_t (*sig_size)(struct gensec_security *gensec_security, size_t data_size); ++ size_t (*max_input_size)(struct gensec_security *gensec_security); ++ size_t (*max_wrapped_size)(struct gensec_security *gensec_security); ++ NTSTATUS (*check_packet)(struct gensec_security *gensec_security, ++ const uint8_t *data, size_t length, ++ const uint8_t *whole_pdu, size_t pdu_length, ++ const DATA_BLOB *sig); ++ NTSTATUS (*unseal_packet)(struct gensec_security *gensec_security, ++ uint8_t *data, size_t length, ++ const uint8_t *whole_pdu, size_t pdu_length, ++ const DATA_BLOB *sig); ++ NTSTATUS (*wrap)(struct gensec_security *gensec_security, ++ TALLOC_CTX *mem_ctx, ++ const DATA_BLOB *in, ++ DATA_BLOB *out); ++ NTSTATUS (*unwrap)(struct gensec_security *gensec_security, ++ TALLOC_CTX *mem_ctx, ++ const DATA_BLOB *in, ++ DATA_BLOB *out); ++ NTSTATUS (*wrap_packets)(struct gensec_security *gensec_security, ++ TALLOC_CTX *mem_ctx, ++ const DATA_BLOB *in, ++ DATA_BLOB *out, ++ size_t *len_processed); ++ NTSTATUS (*unwrap_packets)(struct gensec_security *gensec_security, ++ TALLOC_CTX *mem_ctx, ++ const DATA_BLOB *in, ++ DATA_BLOB *out, ++ size_t *len_processed); ++ NTSTATUS (*packet_full_request)(struct gensec_security *gensec_security, ++ DATA_BLOB blob, size_t *size); ++ NTSTATUS (*session_key)(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, ++ DATA_BLOB *session_key); ++ NTSTATUS (*session_info)(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, ++ struct auth_session_info **session_info); ++ void (*want_feature)(struct gensec_security *gensec_security, ++ uint32_t feature); ++ bool (*have_feature)(struct gensec_security *gensec_security, ++ uint32_t feature); ++ NTTIME (*expire_time)(struct gensec_security *gensec_security); ++ bool enabled; ++ bool kerberos; ++ enum gensec_priority priority; ++}; ++ ++struct gensec_security_ops_wrapper { ++ const struct gensec_security_ops *op; ++ const char *oid; ++}; ++ ++struct gensec_security { ++ const struct gensec_security_ops *ops; ++ void *private_data; ++ struct cli_credentials *credentials; ++ struct gensec_target target; ++ enum gensec_role gensec_role; ++ bool subcontext; ++ uint32_t want_features; ++ uint32_t max_update_size; ++ uint8_t dcerpc_auth_level; ++ struct tsocket_address *local_addr, *remote_addr; ++ struct gensec_settings *settings; ++ ++ /* When we are a server, this may be filled in to provide an ++ * NTLM authentication backend, and user lookup (such as if no ++ * PAC is found) */ ++ struct auth4_context *auth_context; ++}; ++ ++/* this structure is used by backends to determine the size of some critical types */ ++struct gensec_critical_sizes { ++ int interface_version; ++ int sizeof_gensec_security_ops; ++ int sizeof_gensec_security; ++}; ++ ++#endif /* __GENSEC_H__ */ +diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c +index c2cfa1c..34029f5 100644 +--- a/auth/gensec/gensec_start.c ++++ b/auth/gensec/gensec_start.c +@@ -27,6 +27,7 @@ + #include "librpc/rpc/dcerpc.h" + #include "auth/credentials/credentials.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "lib/param/param.h" + #include "lib/util/tsort.h" + #include "lib/util/samba_modules.h" +diff --git a/auth/gensec/gensec_util.c b/auth/gensec/gensec_util.c +index 64952b1..568128a 100644 +--- a/auth/gensec/gensec_util.c ++++ b/auth/gensec/gensec_util.c +@@ -22,6 +22,7 @@ + + #include "includes.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "auth/common_auth.h" + #include "../lib/util/asn1.h" + +diff --git a/auth/gensec/spnego.c b/auth/gensec/spnego.c +index da1fc0e..38a45f8 100644 +--- a/auth/gensec/spnego.c ++++ b/auth/gensec/spnego.c +@@ -27,6 +27,7 @@ + #include "librpc/gen_ndr/ndr_dcerpc.h" + #include "auth/credentials/credentials.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "param/param.h" + #include "lib/util/asn1.h" + +diff --git a/auth/ntlmssp/gensec_ntlmssp.c b/auth/ntlmssp/gensec_ntlmssp.c +index 9e1d8a8..654c0e3 100644 +--- a/auth/ntlmssp/gensec_ntlmssp.c ++++ b/auth/ntlmssp/gensec_ntlmssp.c +@@ -22,6 +22,7 @@ + #include "includes.h" + #include "auth/ntlmssp/ntlmssp.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "auth/ntlmssp/ntlmssp_private.h" + + NTSTATUS gensec_ntlmssp_magic(struct gensec_security *gensec_security, +diff --git a/auth/ntlmssp/gensec_ntlmssp_server.c b/auth/ntlmssp/gensec_ntlmssp_server.c +index f4dfab3..69c56fb 100644 +--- a/auth/ntlmssp/gensec_ntlmssp_server.c ++++ b/auth/ntlmssp/gensec_ntlmssp_server.c +@@ -31,6 +31,7 @@ + #include "../libcli/auth/libcli_auth.h" + #include "../lib/crypto/crypto.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "auth/common_auth.h" + #include "param/param.h" + +diff --git a/auth/ntlmssp/ntlmssp.c b/auth/ntlmssp/ntlmssp.c +index 1a2d662..916b376 100644 +--- a/auth/ntlmssp/ntlmssp.c ++++ b/auth/ntlmssp/ntlmssp.c +@@ -29,6 +29,7 @@ struct auth_session_info; + #include "../libcli/auth/libcli_auth.h" + #include "librpc/gen_ndr/ndr_dcerpc.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + + /** + * Callbacks for NTLMSSP - for both client and server operating modes +diff --git a/auth/ntlmssp/ntlmssp_client.c b/auth/ntlmssp/ntlmssp_client.c +index fc66a8d..f99257d 100644 +--- a/auth/ntlmssp/ntlmssp_client.c ++++ b/auth/ntlmssp/ntlmssp_client.c +@@ -29,6 +29,7 @@ struct auth_session_info; + #include "../libcli/auth/libcli_auth.h" + #include "auth/credentials/credentials.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "param/param.h" + #include "auth/ntlmssp/ntlmssp_private.h" + #include "../librpc/gen_ndr/ndr_ntlmssp.h" +diff --git a/auth/ntlmssp/ntlmssp_server.c b/auth/ntlmssp/ntlmssp_server.c +index 57179e1..2f3f0bb 100644 +--- a/auth/ntlmssp/ntlmssp_server.c ++++ b/auth/ntlmssp/ntlmssp_server.c +@@ -28,6 +28,7 @@ + #include "../libcli/auth/libcli_auth.h" + #include "../lib/crypto/crypto.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "auth/common_auth.h" + + /** +diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c +index 2c667a6..582917d 100644 +--- a/source3/libads/authdata.c ++++ b/source3/libads/authdata.c +@@ -30,6 +30,7 @@ + #include "lib/param/param.h" + #include "librpc/crypto/gse.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" /* TODO: remove this */ + #include "../libcli/auth/spnego.h" + + #ifdef HAVE_KRB5 +diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c +index 11a5457..8db3cdd 100644 +--- a/source3/librpc/crypto/gse.c ++++ b/source3/librpc/crypto/gse.c +@@ -26,6 +26,7 @@ + #include "libads/kerberos_proto.h" + #include "auth/common_auth.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "auth/credentials/credentials.h" + #include "../librpc/gen_ndr/dcerpc.h" + +diff --git a/source3/libsmb/ntlmssp_wrap.c b/source3/libsmb/ntlmssp_wrap.c +index 9ce4b12..46f68ae 100644 +--- a/source3/libsmb/ntlmssp_wrap.c ++++ b/source3/libsmb/ntlmssp_wrap.c +@@ -23,6 +23,7 @@ + #include "auth/ntlmssp/ntlmssp_private.h" + #include "auth_generic.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "auth/credentials/credentials.h" + #include "librpc/rpc/dcerpc.h" + #include "lib/param/param.h" +diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c +index a5e0cd2..5fcb60e 100644 +--- a/source3/utils/ntlm_auth.c ++++ b/source3/utils/ntlm_auth.c +@@ -32,6 +32,7 @@ + #include "../libcli/auth/spnego.h" + #include "auth/ntlmssp/ntlmssp.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "auth/credentials/credentials.h" + #include "librpc/crypto/gse.h" + #include "smb_krb5.h" +diff --git a/source4/auth/gensec/cyrus_sasl.c b/source4/auth/gensec/cyrus_sasl.c +index 2e733bf..08dccd6 100644 +--- a/source4/auth/gensec/cyrus_sasl.c ++++ b/source4/auth/gensec/cyrus_sasl.c +@@ -23,6 +23,7 @@ + #include "lib/tsocket/tsocket.h" + #include "auth/credentials/credentials.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "auth/gensec/gensec_proto.h" + #include "auth/gensec/gensec_toplevel_proto.h" + #include +diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c +index 4fc544f..63a53bf 100644 +--- a/source4/auth/gensec/gensec_gssapi.c ++++ b/source4/auth/gensec/gensec_gssapi.c +@@ -34,6 +34,7 @@ + #include "auth/credentials/credentials.h" + #include "auth/credentials/credentials_krb5.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "auth/gensec/gensec_proto.h" + #include "auth/gensec/gensec_toplevel_proto.h" + #include "param/param.h" +diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c +index fbec64c..ecc3331 100644 +--- a/source4/auth/gensec/gensec_krb5.c ++++ b/source4/auth/gensec/gensec_krb5.c +@@ -34,6 +34,7 @@ + #include "auth/credentials/credentials_krb5.h" + #include "auth/kerberos/kerberos_credentials.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "auth/gensec/gensec_proto.h" + #include "auth/gensec/gensec_toplevel_proto.h" + #include "param/param.h" +diff --git a/source4/auth/gensec/pygensec.c b/source4/auth/gensec/pygensec.c +index 02e5ae2..fd6daff 100644 +--- a/source4/auth/gensec/pygensec.c ++++ b/source4/auth/gensec/pygensec.c +@@ -20,6 +20,7 @@ + #include "includes.h" + #include "param/pyparam.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" /* TODO: remove this */ + #include "auth/credentials/pycredentials.h" + #include "libcli/util/pyerrors.h" + #include "python/modules.h" +diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c +index e67432c..eb2e100 100644 +--- a/source4/auth/gensec/schannel.c ++++ b/source4/auth/gensec/schannel.c +@@ -25,6 +25,7 @@ + #include "auth/auth.h" + #include "auth/credentials/credentials.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "auth/gensec/gensec_proto.h" + #include "../libcli/auth/schannel.h" + #include "librpc/gen_ndr/dcerpc.h" +diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c +index 4a195e5..f0da82c 100644 +--- a/source4/ldap_server/ldap_backend.c ++++ b/source4/ldap_server/ldap_backend.c +@@ -23,6 +23,7 @@ + #include "../lib/util/dlinklist.h" + #include "auth/credentials/credentials.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" /* TODO: remove this */ + #include "param/param.h" + #include "smbd/service_stream.h" + #include "dsdb/samdb/samdb.h" +diff --git a/source4/libcli/ldap/ldap_bind.c b/source4/libcli/ldap/ldap_bind.c +index b355e18..f0a498b 100644 +--- a/source4/libcli/ldap/ldap_bind.c ++++ b/source4/libcli/ldap/ldap_bind.c +@@ -27,6 +27,7 @@ + #include "libcli/ldap/ldap_client.h" + #include "lib/tls/tls.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" /* TODO: remove this */ + #include "auth/gensec/gensec_socket.h" + #include "auth/credentials/credentials.h" + #include "lib/stream/packet.h" +diff --git a/source4/torture/auth/ntlmssp.c b/source4/torture/auth/ntlmssp.c +index bdaa65b..45e5889 100644 +--- a/source4/torture/auth/ntlmssp.c ++++ b/source4/torture/auth/ntlmssp.c +@@ -19,6 +19,7 @@ + + #include "includes.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" + #include "auth/ntlmssp/ntlmssp.h" + #include "auth/ntlmssp/ntlmssp_private.h" + #include "lib/cmdline/popt_common.h" +diff --git a/source4/utils/ntlm_auth.c b/source4/utils/ntlm_auth.c +index 136e238..1e2feb0 100644 +--- a/source4/utils/ntlm_auth.c ++++ b/source4/utils/ntlm_auth.c +@@ -27,6 +27,7 @@ + #include + #include "auth/credentials/credentials.h" + #include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" /* TODO: remove this */ + #include "auth/auth.h" + #include "librpc/gen_ndr/ndr_netlogon.h" + #include "auth/auth_sam.h" +-- +1.9.3 + + +From fabdf9f539385d97bc4bf2550e7fd4de2d1b5d01 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 5 Aug 2013 10:37:26 +0200 +Subject: [PATCH 084/249] auth/gensec: avoid talloc_reference in + gensec_use_kerberos_mechs() + +We now always copy. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 3e3534f882651880093381f5a7846c0938df6501) +--- + auth/gensec/gensec_start.c | 38 ++++++++++++++++++++------------------ + 1 file changed, 20 insertions(+), 18 deletions(-) + +diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c +index 34029f5..096ad36 100644 +--- a/auth/gensec/gensec_start.c ++++ b/auth/gensec/gensec_start.c +@@ -80,13 +80,6 @@ _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ + use_kerberos = cli_credentials_get_kerberos_state(creds); + } + +- if (use_kerberos == CRED_AUTO_USE_KERBEROS) { +- if (!talloc_reference(mem_ctx, old_gensec_list)) { +- return NULL; +- } +- return old_gensec_list; +- } +- + for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) { + /* noop */ + } +@@ -99,35 +92,44 @@ _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ + j = 0; + for (i=0; old_gensec_list && old_gensec_list[i]; i++) { + int oid_idx; +- bool found_spnego = false; ++ bool keep = false; ++ + for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) { + if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) { +- new_gensec_list[j] = old_gensec_list[i]; +- j++; +- found_spnego = true; ++ keep = true; + break; + } + } +- if (found_spnego) { +- continue; +- } ++ + switch (use_kerberos) { ++ case CRED_AUTO_USE_KERBEROS: ++ keep = true; ++ break; ++ + case CRED_DONT_USE_KERBEROS: + if (old_gensec_list[i]->kerberos == false) { +- new_gensec_list[j] = old_gensec_list[i]; +- j++; ++ keep = true; + } ++ + break; ++ + case CRED_MUST_USE_KERBEROS: + if (old_gensec_list[i]->kerberos == true) { +- new_gensec_list[j] = old_gensec_list[i]; +- j++; ++ keep = true; + } ++ + break; + default: + /* Can't happen or invalid parameter */ + return NULL; + } ++ ++ if (!keep) { ++ continue; ++ } ++ ++ new_gensec_list[j] = old_gensec_list[i]; ++ j++; + } + new_gensec_list[j] = NULL; + +-- +1.9.3 + + +From b71ed3dd183d64beda108d0881c03978ef4b3892 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 5 Aug 2013 10:39:16 +0200 +Subject: [PATCH 085/249] auth/gensec: avoid talloc_reference in + gensec_security_mechs() + +We now always copy. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 6a7a44db5999af7262478eb1c186d784d6075beb) +--- + auth/gensec/gensec_start.c | 27 +++++++++------------------ + 1 file changed, 9 insertions(+), 18 deletions(-) + +diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c +index 096ad36..00e2759 100644 +--- a/auth/gensec/gensec_start.c ++++ b/auth/gensec/gensec_start.c +@@ -140,28 +140,19 @@ _PUBLIC_ struct gensec_security_ops **gensec_security_mechs( + struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx) + { +- struct gensec_security_ops **backends; +- if (!gensec_security) { +- backends = gensec_security_all(); +- if (!talloc_reference(mem_ctx, backends)) { +- return NULL; +- } +- return backends; +- } else { +- struct cli_credentials *creds = gensec_get_credentials(gensec_security); ++ struct cli_credentials *creds = NULL; ++ struct gensec_security_ops **backends = gensec_security_all(); ++ ++ if (gensec_security != NULL) { ++ creds = gensec_get_credentials(gensec_security); ++ + if (gensec_security->settings->backends) { + backends = gensec_security->settings->backends; +- } else { +- backends = gensec_security_all(); + } +- if (!creds) { +- if (!talloc_reference(mem_ctx, backends)) { +- return NULL; +- } +- return backends; +- } +- return gensec_use_kerberos_mechs(mem_ctx, backends, creds); + } ++ ++ return gensec_use_kerberos_mechs(mem_ctx, backends, creds); ++ + } + + static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security, +-- +1.9.3 + + +From fe6a14d48b0eb3dfcfc6d7f0b68e8f28b7ad9796 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 5 Aug 2013 16:12:13 +0200 +Subject: [PATCH 086/249] auth/gensec: make it possible to implement async + backends + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit e81550c8117166d0fbf69ba1d3957cb950c42961) +--- + auth/gensec/gensec.c | 202 ++++++++++++++++++++++++++++++++---------- + auth/gensec/gensec_internal.h | 7 ++ + 2 files changed, 160 insertions(+), 49 deletions(-) + +diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c +index d364a34..abcbcb9 100644 +--- a/auth/gensec/gensec.c ++++ b/auth/gensec/gensec.c +@@ -218,61 +218,92 @@ _PUBLIC_ NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_ + const DATA_BLOB in, DATA_BLOB *out) + { + NTSTATUS status; ++ const struct gensec_security_ops *ops = gensec_security->ops; ++ TALLOC_CTX *frame = NULL; ++ struct tevent_req *subreq = NULL; ++ bool ok; + +- status = gensec_security->ops->update(gensec_security, out_mem_ctx, +- ev, in, out); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } ++ if (ops->update_send == NULL) { + +- /* +- * Because callers using the +- * gensec_start_mech_by_auth_type() never call +- * gensec_want_feature(), it isn't sensible for them +- * to have to call gensec_have_feature() manually, and +- * these are not points of negotiation, but are +- * asserted by the client +- */ +- switch (gensec_security->dcerpc_auth_level) { +- case DCERPC_AUTH_LEVEL_INTEGRITY: +- if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) { +- DEBUG(0,("Did not manage to negotiate mandetory feature " +- "SIGN for dcerpc auth_level %u\n", +- gensec_security->dcerpc_auth_level)); +- return NT_STATUS_ACCESS_DENIED; +- } +- break; +- case DCERPC_AUTH_LEVEL_PRIVACY: +- if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) { +- DEBUG(0,("Did not manage to negotiate mandetory feature " +- "SIGN for dcerpc auth_level %u\n", +- gensec_security->dcerpc_auth_level)); +- return NT_STATUS_ACCESS_DENIED; ++ status = ops->update(gensec_security, out_mem_ctx, ++ ev, in, out); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; + } +- if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) { +- DEBUG(0,("Did not manage to negotiate mandetory feature " +- "SEAL for dcerpc auth_level %u\n", +- gensec_security->dcerpc_auth_level)); +- return NT_STATUS_ACCESS_DENIED; ++ ++ /* ++ * Because callers using the ++ * gensec_start_mech_by_auth_type() never call ++ * gensec_want_feature(), it isn't sensible for them ++ * to have to call gensec_have_feature() manually, and ++ * these are not points of negotiation, but are ++ * asserted by the client ++ */ ++ switch (gensec_security->dcerpc_auth_level) { ++ case DCERPC_AUTH_LEVEL_INTEGRITY: ++ if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) { ++ DEBUG(0,("Did not manage to negotiate mandetory feature " ++ "SIGN for dcerpc auth_level %u\n", ++ gensec_security->dcerpc_auth_level)); ++ return NT_STATUS_ACCESS_DENIED; ++ } ++ break; ++ case DCERPC_AUTH_LEVEL_PRIVACY: ++ if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) { ++ DEBUG(0,("Did not manage to negotiate mandetory feature " ++ "SIGN for dcerpc auth_level %u\n", ++ gensec_security->dcerpc_auth_level)); ++ return NT_STATUS_ACCESS_DENIED; ++ } ++ if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) { ++ DEBUG(0,("Did not manage to negotiate mandetory feature " ++ "SEAL for dcerpc auth_level %u\n", ++ gensec_security->dcerpc_auth_level)); ++ return NT_STATUS_ACCESS_DENIED; ++ } ++ break; ++ default: ++ break; + } +- break; +- default: +- break; ++ ++ return NT_STATUS_OK; + } + +- return NT_STATUS_OK; ++ frame = talloc_stackframe(); ++ ++ subreq = ops->update_send(frame, ev, gensec_security, in); ++ if (subreq == NULL) { ++ goto fail; ++ } ++ ok = tevent_req_poll_ntstatus(subreq, ev, &status); ++ if (!ok) { ++ goto fail; ++ } ++ status = ops->update_recv(subreq, out_mem_ctx, out); ++ fail: ++ TALLOC_FREE(frame); ++ return status; + } + + struct gensec_update_state { +- struct tevent_immediate *im; ++ const struct gensec_security_ops *ops; ++ struct tevent_req *subreq; + struct gensec_security *gensec_security; +- DATA_BLOB in; + DATA_BLOB out; ++ ++ /* ++ * only for sync backends, we should remove this ++ * once all backends are async. ++ */ ++ struct tevent_immediate *im; ++ DATA_BLOB in; + }; + + static void gensec_update_async_trigger(struct tevent_context *ctx, + struct tevent_immediate *im, + void *private_data); ++static void gensec_update_subreq_done(struct tevent_req *subreq); ++ + /** + * Next state function for the GENSEC state machine async version + * +@@ -298,17 +329,31 @@ _PUBLIC_ struct tevent_req *gensec_update_send(TALLOC_CTX *mem_ctx, + return NULL; + } + +- state->gensec_security = gensec_security; +- state->in = in; +- state->out = data_blob(NULL, 0); +- state->im = tevent_create_immediate(state); +- if (tevent_req_nomem(state->im, req)) { ++ state->ops = gensec_security->ops; ++ state->gensec_security = gensec_security; ++ ++ if (state->ops->update_send == NULL) { ++ state->in = in; ++ state->im = tevent_create_immediate(state); ++ if (tevent_req_nomem(state->im, req)) { ++ return tevent_req_post(req, ev); ++ } ++ ++ tevent_schedule_immediate(state->im, ev, ++ gensec_update_async_trigger, ++ req); ++ ++ return req; ++ } ++ ++ state->subreq = state->ops->update_send(state, ev, gensec_security, in); ++ if (tevent_req_nomem(state->subreq, req)) { + return tevent_req_post(req, ev); + } + +- tevent_schedule_immediate(state->im, ev, +- gensec_update_async_trigger, +- req); ++ tevent_req_set_callback(state->subreq, ++ gensec_update_subreq_done, ++ req); + + return req; + } +@@ -323,12 +368,71 @@ static void gensec_update_async_trigger(struct tevent_context *ctx, + tevent_req_data(req, struct gensec_update_state); + NTSTATUS status; + +- status = gensec_update(state->gensec_security, state, ctx, +- state->in, &state->out); ++ status = state->ops->update(state->gensec_security, state, ctx, ++ state->in, &state->out); ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ ++ tevent_req_done(req); ++} ++ ++static void gensec_update_subreq_done(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = ++ tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct gensec_update_state *state = ++ tevent_req_data(req, ++ struct gensec_update_state); ++ NTSTATUS status; ++ ++ state->subreq = NULL; ++ ++ status = state->ops->update_recv(subreq, state, &state->out); ++ TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + ++ /* ++ * Because callers using the ++ * gensec_start_mech_by_authtype() never call ++ * gensec_want_feature(), it isn't sensible for them ++ * to have to call gensec_have_feature() manually, and ++ * these are not points of negotiation, but are ++ * asserted by the client ++ */ ++ switch (state->gensec_security->dcerpc_auth_level) { ++ case DCERPC_AUTH_LEVEL_INTEGRITY: ++ if (!gensec_have_feature(state->gensec_security, GENSEC_FEATURE_SIGN)) { ++ DEBUG(0,("Did not manage to negotiate mandetory feature " ++ "SIGN for dcerpc auth_level %u\n", ++ state->gensec_security->dcerpc_auth_level)); ++ tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); ++ return; ++ } ++ break; ++ case DCERPC_AUTH_LEVEL_PRIVACY: ++ if (!gensec_have_feature(state->gensec_security, GENSEC_FEATURE_SIGN)) { ++ DEBUG(0,("Did not manage to negotiate mandetory feature " ++ "SIGN for dcerpc auth_level %u\n", ++ state->gensec_security->dcerpc_auth_level)); ++ tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); ++ return; ++ } ++ if (!gensec_have_feature(state->gensec_security, GENSEC_FEATURE_SEAL)) { ++ DEBUG(0,("Did not manage to negotiate mandetory feature " ++ "SEAL for dcerpc auth_level %u\n", ++ state->gensec_security->dcerpc_auth_level)); ++ tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); ++ return; ++ } ++ break; ++ default: ++ break; ++ } ++ + tevent_req_done(req); + } + +diff --git a/auth/gensec/gensec_internal.h b/auth/gensec/gensec_internal.h +index 41b6f0d..c04164a 100644 +--- a/auth/gensec/gensec_internal.h ++++ b/auth/gensec/gensec_internal.h +@@ -40,6 +40,13 @@ struct gensec_security_ops { + NTSTATUS (*update)(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, + struct tevent_context *ev, + const DATA_BLOB in, DATA_BLOB *out); ++ struct tevent_req *(*update_send)(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct gensec_security *gensec_security, ++ const DATA_BLOB in); ++ NTSTATUS (*update_recv)(struct tevent_req *req, ++ TALLOC_CTX *out_mem_ctx, ++ DATA_BLOB *out); + NTSTATUS (*seal_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx, + uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, +-- +1.9.3 + + +From aa559f2fc6f228fba268adafa92392dff8152747 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 5 Aug 2013 11:10:55 +0200 +Subject: [PATCH 087/249] auth/gensec: use 'const char * const *' for function + parameters + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit c81b6f7448d7f945635784de645bea4f7f2e230f) +--- + auth/gensec/gensec.h | 2 +- + auth/gensec/gensec_start.c | 2 +- + auth/gensec/spnego.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h +index 5d39d81..d0bc451 100644 +--- a/auth/gensec/gensec.h ++++ b/auth/gensec/gensec.h +@@ -184,7 +184,7 @@ struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gense + const struct gensec_security_ops_wrapper *gensec_security_by_oid_list( + struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, +- const char **oid_strings, ++ const char * const *oid_strings, + const char *skip); + const char **gensec_security_oids(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, +diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c +index 00e2759..2874c13 100644 +--- a/auth/gensec/gensec_start.c ++++ b/auth/gensec/gensec_start.c +@@ -373,7 +373,7 @@ static const struct gensec_security_ops **gensec_security_by_sasl_list( + _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list( + struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, +- const char **oid_strings, ++ const char * const *oid_strings, + const char *skip) + { + struct gensec_security_ops_wrapper *backends_out; +diff --git a/auth/gensec/spnego.c b/auth/gensec/spnego.c +index 38a45f8..0eb6da1 100644 +--- a/auth/gensec/spnego.c ++++ b/auth/gensec/spnego.c +@@ -417,7 +417,7 @@ static NTSTATUS gensec_spnego_parse_negTokenInit(struct gensec_security *gensec_ + struct spnego_state *spnego_state, + TALLOC_CTX *out_mem_ctx, + struct tevent_context *ev, +- const char **mechType, ++ const char * const *mechType, + const DATA_BLOB unwrapped_in, DATA_BLOB *unwrapped_out) + { + int i; +-- +1.9.3 + + +From a2e14962e1eeebaac2fb4539794a454b0f486869 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 5 Aug 2013 11:20:21 +0200 +Subject: [PATCH 088/249] auth/gensec: treat struct gensec_security_ops as + const if possible. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit 966faef9c61d2ec02d75fc3ccc82a61524fb77e4) +--- + auth/gensec/gensec.h | 14 +++++----- + auth/gensec/gensec_start.c | 52 ++++++++++++++++++++------------------ + auth/gensec/spnego.c | 8 +++--- + source3/auth/auth_generic.c | 15 ++++++----- + source3/libads/authdata.c | 11 ++++---- + source3/libsmb/auth_generic.c | 15 ++++++----- + source3/utils/ntlm_auth.c | 22 ++++++++-------- + source4/ldap_server/ldap_backend.c | 4 +-- + 8 files changed, 75 insertions(+), 66 deletions(-) + +diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h +index d0bc451..ac1fadf 100644 +--- a/auth/gensec/gensec.h ++++ b/auth/gensec/gensec.h +@@ -85,7 +85,7 @@ struct gensec_settings { + /* this allows callers to specify a specific set of ops that + * should be used, rather than those loaded by the plugin + * mechanism */ +- struct gensec_security_ops **backends; ++ const struct gensec_security_ops * const *backends; + + /* To fill in our own name in the NTLMSSP server */ + const char *server_dns_domain; +@@ -179,7 +179,7 @@ const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_sec + const struct gensec_security_ops *gensec_security_by_auth_type( + struct gensec_security *gensec_security, + uint32_t auth_type); +-struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security, ++const struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx); + const struct gensec_security_ops_wrapper *gensec_security_by_oid_list( + struct gensec_security *gensec_security, +@@ -243,11 +243,11 @@ NTSTATUS gensec_wrap(struct gensec_security *gensec_security, + const DATA_BLOB *in, + DATA_BLOB *out); + +-struct gensec_security_ops **gensec_security_all(void); +-bool gensec_security_ops_enabled(struct gensec_security_ops *ops, struct gensec_security *security); +-struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx, +- struct gensec_security_ops **old_gensec_list, +- struct cli_credentials *creds); ++const struct gensec_security_ops * const *gensec_security_all(void); ++bool gensec_security_ops_enabled(const struct gensec_security_ops *ops, struct gensec_security *security); ++const struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx, ++ const struct gensec_security_ops * const *old_gensec_list, ++ struct cli_credentials *creds); + + NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security, + const char *sasl_name); +diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c +index 2874c13..3ae64d5 100644 +--- a/auth/gensec/gensec_start.c ++++ b/auth/gensec/gensec_start.c +@@ -33,17 +33,17 @@ + #include "lib/util/samba_modules.h" + + /* the list of currently registered GENSEC backends */ +-static struct gensec_security_ops **generic_security_ops; ++static const struct gensec_security_ops **generic_security_ops; + static int gensec_num_backends; + + /* Return all the registered mechs. Don't modify the return pointer, +- * but you may talloc_reference it if convient */ +-_PUBLIC_ struct gensec_security_ops **gensec_security_all(void) ++ * but you may talloc_referen it if convient */ ++_PUBLIC_ const struct gensec_security_ops * const *gensec_security_all(void) + { + return generic_security_ops; + } + +-bool gensec_security_ops_enabled(struct gensec_security_ops *ops, struct gensec_security *security) ++bool gensec_security_ops_enabled(const struct gensec_security_ops *ops, struct gensec_security *security) + { + return lpcfg_parm_bool(security->settings->lp_ctx, NULL, "gensec", ops->name, ops->enabled); + } +@@ -68,11 +68,11 @@ bool gensec_security_ops_enabled(struct gensec_security_ops *ops, struct gensec_ + * more compplex. + */ + +-_PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx, +- struct gensec_security_ops **old_gensec_list, +- struct cli_credentials *creds) ++_PUBLIC_ const struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx, ++ const struct gensec_security_ops * const *old_gensec_list, ++ struct cli_credentials *creds) + { +- struct gensec_security_ops **new_gensec_list; ++ const struct gensec_security_ops **new_gensec_list; + int i, j, num_mechs_in; + enum credentials_use_kerberos use_kerberos = CRED_AUTO_USE_KERBEROS; + +@@ -84,7 +84,9 @@ _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ + /* noop */ + } + +- new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1); ++ new_gensec_list = talloc_array(mem_ctx, ++ const struct gensec_security_ops *, ++ num_mechs_in + 1); + if (!new_gensec_list) { + return NULL; + } +@@ -136,12 +138,12 @@ _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ + return new_gensec_list; + } + +-_PUBLIC_ struct gensec_security_ops **gensec_security_mechs( ++_PUBLIC_ const struct gensec_security_ops **gensec_security_mechs( + struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx) + { + struct cli_credentials *creds = NULL; +- struct gensec_security_ops **backends = gensec_security_all(); ++ const struct gensec_security_ops * const *backends = gensec_security_all(); + + if (gensec_security != NULL) { + creds = gensec_get_credentials(gensec_security); +@@ -159,7 +161,7 @@ static const struct gensec_security_ops *gensec_security_by_authtype(struct gens + uint8_t auth_type) + { + int i; +- struct gensec_security_ops **backends; ++ const struct gensec_security_ops **backends; + const struct gensec_security_ops *backend; + TALLOC_CTX *mem_ctx = talloc_new(gensec_security); + if (!mem_ctx) { +@@ -185,7 +187,7 @@ _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid( + const char *oid_string) + { + int i, j; +- struct gensec_security_ops **backends; ++ const struct gensec_security_ops **backends; + const struct gensec_security_ops *backend; + TALLOC_CTX *mem_ctx = talloc_new(gensec_security); + if (!mem_ctx) { +@@ -218,7 +220,7 @@ _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name( + const char *sasl_name) + { + int i; +- struct gensec_security_ops **backends; ++ const struct gensec_security_ops **backends; + const struct gensec_security_ops *backend; + TALLOC_CTX *mem_ctx = talloc_new(gensec_security); + if (!mem_ctx) { +@@ -245,7 +247,7 @@ _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type( + uint32_t auth_type) + { + int i; +- struct gensec_security_ops **backends; ++ const struct gensec_security_ops **backends; + const struct gensec_security_ops *backend; + TALLOC_CTX *mem_ctx = talloc_new(gensec_security); + if (!mem_ctx) { +@@ -270,7 +272,7 @@ static const struct gensec_security_ops *gensec_security_by_name(struct gensec_s + const char *name) + { + int i; +- struct gensec_security_ops **backends; ++ const struct gensec_security_ops **backends; + const struct gensec_security_ops *backend; + TALLOC_CTX *mem_ctx = talloc_new(gensec_security); + if (!mem_ctx) { +@@ -306,7 +308,7 @@ static const struct gensec_security_ops **gensec_security_by_sasl_list( + const char **sasl_names) + { + const struct gensec_security_ops **backends_out; +- struct gensec_security_ops **backends; ++ const struct gensec_security_ops **backends; + int i, k, sasl_idx; + int num_backends_out = 0; + +@@ -377,7 +379,7 @@ _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list( + const char *skip) + { + struct gensec_security_ops_wrapper *backends_out; +- struct gensec_security_ops **backends; ++ const struct gensec_security_ops **backends; + int i, j, k, oid_idx; + int num_backends_out = 0; + +@@ -451,7 +453,7 @@ _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list( + static const char **gensec_security_oids_from_ops( + struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, +- struct gensec_security_ops **ops, ++ const struct gensec_security_ops * const *ops, + const char *skip) + { + int i; +@@ -542,8 +544,10 @@ _PUBLIC_ const char **gensec_security_oids(struct gensec_security *gensec_securi + TALLOC_CTX *mem_ctx, + const char *skip) + { +- struct gensec_security_ops **ops +- = gensec_security_mechs(gensec_security, mem_ctx); ++ const struct gensec_security_ops **ops; ++ ++ ops = gensec_security_mechs(gensec_security, mem_ctx); ++ + return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip); + } + +@@ -876,13 +880,13 @@ _PUBLIC_ NTSTATUS gensec_register(const struct gensec_security_ops *ops) + + generic_security_ops = talloc_realloc(talloc_autofree_context(), + generic_security_ops, +- struct gensec_security_ops *, ++ const struct gensec_security_ops *, + gensec_num_backends+2); + if (!generic_security_ops) { + return NT_STATUS_NO_MEMORY; + } + +- generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops); ++ generic_security_ops[gensec_num_backends] = ops; + gensec_num_backends++; + generic_security_ops[gensec_num_backends] = NULL; + +@@ -908,7 +912,7 @@ _PUBLIC_ const struct gensec_critical_sizes *gensec_interface_version(void) + return &critical_sizes; + } + +-static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) { ++static int sort_gensec(const struct gensec_security_ops **gs1, const struct gensec_security_ops **gs2) { + return (*gs2)->priority - (*gs1)->priority; + } + +diff --git a/auth/gensec/spnego.c b/auth/gensec/spnego.c +index 0eb6da1..d90a50c 100644 +--- a/auth/gensec/spnego.c ++++ b/auth/gensec/spnego.c +@@ -352,9 +352,11 @@ static NTSTATUS gensec_spnego_server_try_fallback(struct gensec_security *gensec + const DATA_BLOB in, DATA_BLOB *out) + { + int i,j; +- struct gensec_security_ops **all_ops +- = gensec_security_mechs(gensec_security, out_mem_ctx); +- for (i=0; all_ops[i]; i++) { ++ const struct gensec_security_ops **all_ops; ++ ++ all_ops = gensec_security_mechs(gensec_security, out_mem_ctx); ++ ++ for (i=0; all_ops && all_ops[i]; i++) { + bool is_spnego; + NTSTATUS nt_status; + +diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c +index a2ba4e3..e15c87e 100644 +--- a/source3/auth/auth_generic.c ++++ b/source3/auth/auth_generic.c +@@ -203,6 +203,7 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx, + return nt_status; + } + } else { ++ const struct gensec_security_ops **backends = NULL; + struct gensec_settings *gensec_settings; + struct loadparm_context *lp_ctx; + size_t idx = 0; +@@ -259,24 +260,24 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx, + return NT_STATUS_NO_MEMORY; + } + +- gensec_settings->backends = talloc_zero_array(gensec_settings, +- struct gensec_security_ops *, 4); +- if (gensec_settings->backends == NULL) { ++ backends = talloc_zero_array(gensec_settings, ++ const struct gensec_security_ops *, 4); ++ if (backends == NULL) { + TALLOC_FREE(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } ++ gensec_settings->backends = backends; + + gensec_init(); + + /* These need to be in priority order, krb5 before NTLMSSP */ + #if defined(HAVE_KRB5) +- gensec_settings->backends[idx++] = &gensec_gse_krb5_security_ops; ++ backends[idx++] = &gensec_gse_krb5_security_ops; + #endif + +- gensec_settings->backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_NTLMSSP); ++ backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_NTLMSSP); + +- gensec_settings->backends[idx++] = gensec_security_by_oid(NULL, +- GENSEC_OID_SPNEGO); ++ backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO); + + /* + * This is anonymous for now, because we just use it +diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c +index 582917d..801e551 100644 +--- a/source3/libads/authdata.c ++++ b/source3/libads/authdata.c +@@ -111,7 +111,7 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, + const char *cc = "MEMORY:kerberos_return_pac"; + struct auth_session_info *session_info; + struct gensec_security *gensec_server_context; +- ++ const struct gensec_security_ops **backends; + struct gensec_settings *gensec_settings; + size_t idx = 0; + struct auth4_context *auth_context; +@@ -230,16 +230,17 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, + goto out; + } + +- gensec_settings->backends = talloc_zero_array(gensec_settings, +- struct gensec_security_ops *, 2); +- if (gensec_settings->backends == NULL) { ++ backends = talloc_zero_array(gensec_settings, ++ const struct gensec_security_ops *, 2); ++ if (backends == NULL) { + status = NT_STATUS_NO_MEMORY; + goto out; + } ++ gensec_settings->backends = backends; + + gensec_init(); + +- gensec_settings->backends[idx++] = &gensec_gse_krb5_security_ops; ++ backends[idx++] = &gensec_gse_krb5_security_ops; + + status = gensec_server_start(tmp_ctx, gensec_settings, + auth_context, &gensec_server_context); +diff --git a/source3/libsmb/auth_generic.c b/source3/libsmb/auth_generic.c +index ba0a0ce..e30c1b7 100644 +--- a/source3/libsmb/auth_generic.c ++++ b/source3/libsmb/auth_generic.c +@@ -54,6 +54,7 @@ NTSTATUS auth_generic_client_prepare(TALLOC_CTX *mem_ctx, struct auth_generic_st + NTSTATUS nt_status; + size_t idx = 0; + struct gensec_settings *gensec_settings; ++ const struct gensec_security_ops **backends = NULL; + struct loadparm_context *lp_ctx; + + ans = talloc_zero(mem_ctx, struct auth_generic_state); +@@ -76,24 +77,24 @@ NTSTATUS auth_generic_client_prepare(TALLOC_CTX *mem_ctx, struct auth_generic_st + return NT_STATUS_NO_MEMORY; + } + +- gensec_settings->backends = talloc_zero_array(gensec_settings, +- struct gensec_security_ops *, 4); +- if (gensec_settings->backends == NULL) { ++ backends = talloc_zero_array(gensec_settings, ++ const struct gensec_security_ops *, 4); ++ if (backends == NULL) { + TALLOC_FREE(ans); + return NT_STATUS_NO_MEMORY; + } ++ gensec_settings->backends = backends; + + gensec_init(); + + /* These need to be in priority order, krb5 before NTLMSSP */ + #if defined(HAVE_KRB5) +- gensec_settings->backends[idx++] = &gensec_gse_krb5_security_ops; ++ backends[idx++] = &gensec_gse_krb5_security_ops; + #endif + +- gensec_settings->backends[idx++] = &gensec_ntlmssp3_client_ops; ++ backends[idx++] = &gensec_ntlmssp3_client_ops; + +- gensec_settings->backends[idx++] = gensec_security_by_oid(NULL, +- GENSEC_OID_SPNEGO); ++ backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO); + + nt_status = gensec_client_start(ans, &ans->gensec_security, gensec_settings); + +diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c +index 5fcb60e..25e717c 100644 +--- a/source3/utils/ntlm_auth.c ++++ b/source3/utils/ntlm_auth.c +@@ -1035,7 +1035,7 @@ static NTSTATUS ntlm_auth_start_ntlmssp_server(TALLOC_CTX *mem_ctx, + NTSTATUS nt_status; + + TALLOC_CTX *tmp_ctx; +- ++ const struct gensec_security_ops **backends; + struct gensec_settings *gensec_settings; + size_t idx = 0; + struct cli_credentials *server_credentials; +@@ -1079,26 +1079,26 @@ static NTSTATUS ntlm_auth_start_ntlmssp_server(TALLOC_CTX *mem_ctx, + gensec_settings->server_dns_name = strlower_talloc(gensec_settings, + get_mydnsfullname()); + +- gensec_settings->backends = talloc_zero_array(gensec_settings, +- struct gensec_security_ops *, 4); ++ backends = talloc_zero_array(gensec_settings, ++ const struct gensec_security_ops *, 4); + +- if (gensec_settings->backends == NULL) { ++ if (backends == NULL) { + TALLOC_FREE(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } +- ++ gensec_settings->backends = backends; ++ + gensec_init(); + + /* These need to be in priority order, krb5 before NTLMSSP */ + #if defined(HAVE_KRB5) +- gensec_settings->backends[idx++] = &gensec_gse_krb5_security_ops; ++ backends[idx++] = &gensec_gse_krb5_security_ops; + #endif +- +- gensec_settings->backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_NTLMSSP); + +- gensec_settings->backends[idx++] = gensec_security_by_oid(NULL, +- GENSEC_OID_SPNEGO); +- ++ backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_NTLMSSP); ++ ++ backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO); ++ + /* + * This is anonymous for now, because we just use it + * to set the kerberos state at the moment +diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c +index f0da82c..3432594 100644 +--- a/source4/ldap_server/ldap_backend.c ++++ b/source4/ldap_server/ldap_backend.c +@@ -192,8 +192,8 @@ NTSTATUS ldapsrv_backend_Init(struct ldapsrv_connection *conn) + + if (conn->server_credentials) { + char **sasl_mechs = NULL; +- struct gensec_security_ops **backends = gensec_security_all(); +- struct gensec_security_ops **ops ++ const struct gensec_security_ops * const *backends = gensec_security_all(); ++ const struct gensec_security_ops **ops + = gensec_use_kerberos_mechs(conn, backends, conn->server_credentials); + unsigned int i, j = 0; + for (i = 0; ops && ops[i]; i++) { +-- +1.9.3 + + +From 6a58d4f4cb60bf25c1493ef0aedd5978abc06969 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 5 Aug 2013 10:43:38 +0200 +Subject: [PATCH 089/249] libcli/auth: avoid possible mem leak in + read_negTokenInit() + +Also add error checks. + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett +(cherry picked from commit f1e60142e12deb560e3c62441fd9ff2acd086b60) +--- + libcli/auth/spnego_parse.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/libcli/auth/spnego_parse.c b/libcli/auth/spnego_parse.c +index 3bf7aea..2c73613 100644 +--- a/libcli/auth/spnego_parse.c ++++ b/libcli/auth/spnego_parse.c +@@ -46,13 +46,24 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx, + asn1_start_tag(asn1, ASN1_CONTEXT(0)); + asn1_start_tag(asn1, ASN1_SEQUENCE(0)); + +- token->mechTypes = talloc(NULL, const char *); ++ token->mechTypes = talloc(mem_ctx, const char *); ++ if (token->mechTypes == NULL) { ++ asn1->has_error = true; ++ return false; ++ } + for (i = 0; !asn1->has_error && + 0 < asn1_tag_remaining(asn1); i++) { + char *oid; +- token->mechTypes = talloc_realloc(NULL, +- token->mechTypes, +- const char *, i+2); ++ const char **p; ++ p = talloc_realloc(mem_ctx, ++ token->mechTypes, ++ const char *, i+2); ++ if (p == NULL) { ++ TALLOC_FREE(token->mechTypes); ++ asn1->has_error = true; ++ return false; ++ } ++ token->mechTypes = p; + asn1_read_OID(asn1, token->mechTypes, &oid); + token->mechTypes[i] = oid; + } +-- +1.9.3 + + +From 8835471a993521e49aa48ef55f324874e1933108 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 5 Aug 2013 10:46:47 +0200 +Subject: [PATCH 090/249] libcli/auth: add more const to + spnego_negTokenInit->mechTypes + +Signed-off-by: Stefan Metzmacher + +Reviewed-by: Andrew Bartlett + +Autobuild-User(master): Stefan Metzmacher +Autobuild-Date(master): Sat Aug 10 11:11:54 CEST 2013 on sn-devel-104 +(cherry picked from commit 9177a0d1c1c92c45ef92fbda55fc6dd8aeb76b6c) +--- + libcli/auth/spnego.h | 2 +- + libcli/auth/spnego_parse.c | 27 ++++++++++++++++----------- + libcli/auth/spnego_proto.h | 2 +- + source3/utils/ntlm_auth.c | 2 +- + 4 files changed, 19 insertions(+), 14 deletions(-) + +diff --git a/libcli/auth/spnego.h b/libcli/auth/spnego.h +index 9a93f2e..539b903 100644 +--- a/libcli/auth/spnego.h ++++ b/libcli/auth/spnego.h +@@ -49,7 +49,7 @@ enum spnego_negResult { + }; + + struct spnego_negTokenInit { +- const char **mechTypes; ++ const char * const *mechTypes; + DATA_BLOB reqFlags; + uint8_t reqFlagsPadding; + DATA_BLOB mechToken; +diff --git a/libcli/auth/spnego_parse.c b/libcli/auth/spnego_parse.c +index 2c73613..b1ca07d 100644 +--- a/libcli/auth/spnego_parse.c ++++ b/libcli/auth/spnego_parse.c +@@ -42,12 +42,14 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx, + + switch (context) { + /* Read mechTypes */ +- case ASN1_CONTEXT(0): ++ case ASN1_CONTEXT(0): { ++ const char **mechTypes; ++ + asn1_start_tag(asn1, ASN1_CONTEXT(0)); + asn1_start_tag(asn1, ASN1_SEQUENCE(0)); + +- token->mechTypes = talloc(mem_ctx, const char *); +- if (token->mechTypes == NULL) { ++ mechTypes = talloc(mem_ctx, const char *); ++ if (mechTypes == NULL) { + asn1->has_error = true; + return false; + } +@@ -56,22 +58,25 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx, + char *oid; + const char **p; + p = talloc_realloc(mem_ctx, +- token->mechTypes, ++ mechTypes, + const char *, i+2); + if (p == NULL) { +- TALLOC_FREE(token->mechTypes); ++ talloc_free(mechTypes); + asn1->has_error = true; + return false; + } +- token->mechTypes = p; +- asn1_read_OID(asn1, token->mechTypes, &oid); +- token->mechTypes[i] = oid; ++ mechTypes = p; ++ ++ asn1_read_OID(asn1, mechTypes, &oid); ++ mechTypes[i] = oid; + } +- token->mechTypes[i] = NULL; ++ mechTypes[i] = NULL; ++ token->mechTypes = mechTypes; + + asn1_end_tag(asn1); + asn1_end_tag(asn1); + break; ++ } + /* Read reqFlags */ + case ASN1_CONTEXT(1): + asn1_start_tag(asn1, ASN1_CONTEXT(1)); +@@ -366,7 +371,7 @@ bool spnego_free_data(struct spnego_data *spnego) + switch(spnego->type) { + case SPNEGO_NEG_TOKEN_INIT: + if (spnego->negTokenInit.mechTypes) { +- talloc_free(spnego->negTokenInit.mechTypes); ++ talloc_free(discard_const(spnego->negTokenInit.mechTypes)); + } + data_blob_free(&spnego->negTokenInit.reqFlags); + data_blob_free(&spnego->negTokenInit.mechToken); +@@ -390,7 +395,7 @@ out: + } + + bool spnego_write_mech_types(TALLOC_CTX *mem_ctx, +- const char **mech_types, ++ const char * const *mech_types, + DATA_BLOB *blob) + { + struct asn1_data *asn1 = asn1_init(mem_ctx); +diff --git a/libcli/auth/spnego_proto.h b/libcli/auth/spnego_proto.h +index 5fd5e59..c0fa934 100644 +--- a/libcli/auth/spnego_proto.h ++++ b/libcli/auth/spnego_proto.h +@@ -24,5 +24,5 @@ ssize_t spnego_read_data(TALLOC_CTX *mem_ctx, DATA_BLOB data, struct spnego_data + ssize_t spnego_write_data(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct spnego_data *spnego); + bool spnego_free_data(struct spnego_data *spnego); + bool spnego_write_mech_types(TALLOC_CTX *mem_ctx, +- const char **mech_types, ++ const char * const *mech_types, + DATA_BLOB *blob); +diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c +index 25e717c..1df615c 100644 +--- a/source3/utils/ntlm_auth.c ++++ b/source3/utils/ntlm_auth.c +@@ -2058,7 +2058,7 @@ static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper + + /* The server offers a list of mechanisms */ + +- const char **mechType = (const char **)spnego.negTokenInit.mechTypes; ++ const char *const *mechType = spnego.negTokenInit.mechTypes; + + while (*mechType != NULL) { + +-- +1.9.3 + + +From c06bb0c3d2c032f8b4848c75baa1fd900650866a Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 9 Aug 2013 10:15:05 +0200 +Subject: [PATCH 091/249] auth/credentials: make sure + cli_credentials_get_nt_hash() always returns a talloc object + +Signed-off-by: Stefan Metzmacher +--- + auth/credentials/credentials.c | 19 ++++++++++++++----- + auth/credentials/credentials.h | 4 ++-- + 2 files changed, 16 insertions(+), 7 deletions(-) + +diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c +index be497bc..57a7c0b 100644 +--- a/auth/credentials/credentials.c ++++ b/auth/credentials/credentials.c +@@ -471,8 +471,8 @@ _PUBLIC_ bool cli_credentials_set_old_password(struct cli_credentials *cred, + * @param cred credentials context + * @retval If set, the cleartext password, otherwise NULL + */ +-_PUBLIC_ const struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred, +- TALLOC_CTX *mem_ctx) ++_PUBLIC_ struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred, ++ TALLOC_CTX *mem_ctx) + { + const char *password = cli_credentials_get_password(cred); + +@@ -481,13 +481,22 @@ _PUBLIC_ const struct samr_Password *cli_credentials_get_nt_hash(struct cli_cred + if (!nt_hash) { + return NULL; + } +- ++ + E_md4hash(password, nt_hash->hash); + + return nt_hash; +- } else { +- return cred->nt_hash; ++ } else if (cred->nt_hash != NULL) { ++ struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password); ++ if (!nt_hash) { ++ return NULL; ++ } ++ ++ *nt_hash = *cred->nt_hash; ++ ++ return nt_hash; + } ++ ++ return NULL; + } + + /** +diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h +index cb09dc3..766a513 100644 +--- a/auth/credentials/credentials.h ++++ b/auth/credentials/credentials.h +@@ -141,8 +141,8 @@ bool cli_credentials_set_password(struct cli_credentials *cred, + enum credentials_obtained obtained); + struct cli_credentials *cli_credentials_init_anon(TALLOC_CTX *mem_ctx); + void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained); +-const struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred, +- TALLOC_CTX *mem_ctx); ++struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred, ++ TALLOC_CTX *mem_ctx); + bool cli_credentials_set_realm(struct cli_credentials *cred, + const char *val, + enum credentials_obtained obtained); +-- +1.9.3 + + +From 8a3ed9f72ef9f9de32da4d454b866d64eb24ee17 Mon Sep 17 00:00:00 2001 +From: Howard Chu +Date: Tue, 17 Sep 2013 13:09:50 -0700 +Subject: [PATCH 092/249] Add SASL/EXTERNAL gensec module + +Signed-off-by: Howard Chu +Reviewed-by: Andrew Bartlett +Reviewed-by: Nadezhda Ivanova +(cherry picked from commit 6bf59b03d72b94b71e53fc2404c11e0d237e41b2) +--- + auth/gensec/external.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++ + auth/gensec/gensec.h | 3 +- + auth/gensec/wscript_build | 7 ++++ + 3 files changed, 91 insertions(+), 1 deletion(-) + create mode 100644 auth/gensec/external.c + +diff --git a/auth/gensec/external.c b/auth/gensec/external.c +new file mode 100644 +index 0000000..a26e435 +--- /dev/null ++++ b/auth/gensec/external.c +@@ -0,0 +1,82 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ SASL/EXTERNAL authentication. ++ ++ Copyright (C) Howard Chu 2013 ++ ++ 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 . ++*/ ++ ++#include "includes.h" ++#include "auth/credentials/credentials.h" ++#include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" ++#include "auth/gensec/gensec_proto.h" ++#include "auth/gensec/gensec_toplevel_proto.h" ++ ++/* SASL/EXTERNAL is essentially a no-op; it is only usable when the transport ++ * layer is already mutually authenticated. ++ */ ++ ++NTSTATUS gensec_external_init(void); ++ ++static NTSTATUS gensec_external_start(struct gensec_security *gensec_security) ++{ ++ if (gensec_security->want_features & GENSEC_FEATURE_SIGN) ++ return NT_STATUS_INVALID_PARAMETER; ++ if (gensec_security->want_features & GENSEC_FEATURE_SEAL) ++ return NT_STATUS_INVALID_PARAMETER; ++ ++ return NT_STATUS_OK; ++} ++ ++static NTSTATUS gensec_external_update(struct gensec_security *gensec_security, ++ TALLOC_CTX *out_mem_ctx, ++ struct tevent_context *ev, ++ const DATA_BLOB in, DATA_BLOB *out) ++{ ++ *out = data_blob_talloc(out_mem_ctx, "", 0); ++ return NT_STATUS_OK; ++} ++ ++/* We have no features */ ++static bool gensec_external_have_feature(struct gensec_security *gensec_security, ++ uint32_t feature) ++{ ++ return false; ++} ++ ++static const struct gensec_security_ops gensec_external_ops = { ++ .name = "sasl-EXTERNAL", ++ .sasl_name = "EXTERNAL", ++ .client_start = gensec_external_start, ++ .update = gensec_external_update, ++ .have_feature = gensec_external_have_feature, ++ .enabled = true, ++ .priority = GENSEC_EXTERNAL ++}; ++ ++ ++NTSTATUS gensec_external_init(void) ++{ ++ NTSTATUS ret; ++ ++ ret = gensec_register(&gensec_external_ops); ++ if (!NT_STATUS_IS_OK(ret)) { ++ DEBUG(0,("Failed to register '%s' gensec backend!\n", ++ gensec_external_ops.name)); ++ } ++ return ret; ++} +diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h +index ac1fadf..6974f87 100644 +--- a/auth/gensec/gensec.h ++++ b/auth/gensec/gensec.h +@@ -41,7 +41,8 @@ enum gensec_priority { + GENSEC_SCHANNEL = 60, + GENSEC_NTLMSSP = 50, + GENSEC_SASL = 20, +- GENSEC_OTHER = 0 ++ GENSEC_OTHER = 10, ++ GENSEC_EXTERNAL = 0 + }; + + struct gensec_security; +diff --git a/auth/gensec/wscript_build b/auth/gensec/wscript_build +index fcd74a3..71222f7 100755 +--- a/auth/gensec/wscript_build ++++ b/auth/gensec/wscript_build +@@ -16,3 +16,10 @@ bld.SAMBA_MODULE('gensec_spnego', + init_function='gensec_spnego_init', + deps='asn1util samba-credentials SPNEGO_PARSE' + ) ++ ++bld.SAMBA_MODULE('gensec_external', ++ source='external.c', ++ autoproto='external_proto.h', ++ subsystem='gensec', ++ init_function='gensec_external_init' ++ ) +-- +1.9.3 + + +From 75d9566940069ebeb367191ec6a6641bf7d45a83 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 18 Sep 2013 17:24:10 +0200 +Subject: [PATCH 093/249] gensec: move schannel module to toplevel. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Pair-Programmed-With: Andreas Schneider +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 4d2ec9e37ee9dcf7b521806a1c0aabdffe524d47) +--- + auth/gensec/schannel.c | 330 ++++++++++++++++++++++++++++++++++++++ + auth/gensec/wscript_build | 8 + + source4/auth/gensec/schannel.c | 330 -------------------------------------- + source4/auth/gensec/wscript_build | 10 -- + 4 files changed, 338 insertions(+), 340 deletions(-) + create mode 100644 auth/gensec/schannel.c + delete mode 100644 source4/auth/gensec/schannel.c + +diff --git a/auth/gensec/schannel.c b/auth/gensec/schannel.c +new file mode 100644 +index 0000000..eb2e100 +--- /dev/null ++++ b/auth/gensec/schannel.c +@@ -0,0 +1,330 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ dcerpc schannel operations ++ ++ Copyright (C) Andrew Tridgell 2004 ++ Copyright (C) Andrew Bartlett 2004-2005 ++ ++ 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 . ++*/ ++ ++#include "includes.h" ++#include "librpc/gen_ndr/ndr_schannel.h" ++#include "auth/auth.h" ++#include "auth/credentials/credentials.h" ++#include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" ++#include "auth/gensec/gensec_proto.h" ++#include "../libcli/auth/schannel.h" ++#include "librpc/gen_ndr/dcerpc.h" ++#include "param/param.h" ++#include "auth/gensec/gensec_toplevel_proto.h" ++ ++_PUBLIC_ NTSTATUS gensec_schannel_init(void); ++ ++static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t data_size) ++{ ++ struct schannel_state *state = ++ talloc_get_type_abort(gensec_security->private_data, ++ struct schannel_state); ++ ++ return netsec_outgoing_sig_size(state); ++} ++ ++static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, ++ struct tevent_context *ev, ++ const DATA_BLOB in, DATA_BLOB *out) ++{ ++ struct schannel_state *state = ++ talloc_get_type(gensec_security->private_data, ++ struct schannel_state); ++ NTSTATUS status; ++ enum ndr_err_code ndr_err; ++ struct NL_AUTH_MESSAGE bind_schannel; ++ struct NL_AUTH_MESSAGE bind_schannel_ack; ++ struct netlogon_creds_CredentialState *creds; ++ const char *workstation; ++ const char *domain; ++ ++ *out = data_blob(NULL, 0); ++ ++ switch (gensec_security->gensec_role) { ++ case GENSEC_CLIENT: ++ if (state != NULL) { ++ /* we could parse the bind ack, but we don't know what it is yet */ ++ return NT_STATUS_OK; ++ } ++ ++ creds = cli_credentials_get_netlogon_creds(gensec_security->credentials); ++ if (creds == NULL) { ++ return NT_STATUS_INVALID_PARAMETER_MIX; ++ } ++ ++ state = netsec_create_state(gensec_security, ++ creds, true /* initiator */); ++ if (state == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ gensec_security->private_data = state; ++ ++ bind_schannel.MessageType = NL_NEGOTIATE_REQUEST; ++#if 0 ++ /* to support this we'd need to have access to the full domain name */ ++ /* 0x17, 23 */ ++ bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | ++ NL_FLAG_OEM_NETBIOS_COMPUTER_NAME | ++ NL_FLAG_UTF8_DNS_DOMAIN_NAME | ++ NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME; ++ bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); ++ bind_schannel.oem_netbios_computer.a = creds->computer_name; ++ bind_schannel.utf8_dns_domain = cli_credentials_get_realm(gensec_security->credentials); ++ /* w2k3 refuses us if we use the full DNS workstation? ++ why? perhaps because we don't fill in the dNSHostName ++ attribute in the machine account? */ ++ bind_schannel.utf8_netbios_computer = creds->computer_name; ++#else ++ bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | ++ NL_FLAG_OEM_NETBIOS_COMPUTER_NAME; ++ bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); ++ bind_schannel.oem_netbios_computer.a = creds->computer_name; ++#endif ++ ++ ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel, ++ (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); ++ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ++ status = ndr_map_error2ntstatus(ndr_err); ++ DEBUG(3, ("Could not create schannel bind: %s\n", ++ nt_errstr(status))); ++ return status; ++ } ++ ++ return NT_STATUS_MORE_PROCESSING_REQUIRED; ++ case GENSEC_SERVER: ++ ++ if (state != NULL) { ++ /* no third leg on this protocol */ ++ return NT_STATUS_INVALID_PARAMETER; ++ } ++ ++ /* parse the schannel startup blob */ ++ ndr_err = ndr_pull_struct_blob(&in, out_mem_ctx, &bind_schannel, ++ (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE); ++ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ++ status = ndr_map_error2ntstatus(ndr_err); ++ DEBUG(3, ("Could not parse incoming schannel bind: %s\n", ++ nt_errstr(status))); ++ return status; ++ } ++ ++ if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_DOMAIN_NAME) { ++ domain = bind_schannel.oem_netbios_domain.a; ++ if (strcasecmp_m(domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)) != 0) { ++ DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n", ++ domain, lpcfg_workgroup(gensec_security->settings->lp_ctx))); ++ return NT_STATUS_LOGON_FAILURE; ++ } ++ } else if (bind_schannel.Flags & NL_FLAG_UTF8_DNS_DOMAIN_NAME) { ++ domain = bind_schannel.utf8_dns_domain.u; ++ if (strcasecmp_m(domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)) != 0) { ++ DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n", ++ domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx))); ++ return NT_STATUS_LOGON_FAILURE; ++ } ++ } else { ++ DEBUG(3, ("Request for schannel to without domain\n")); ++ return NT_STATUS_LOGON_FAILURE; ++ } ++ ++ if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME) { ++ workstation = bind_schannel.oem_netbios_computer.a; ++ } else if (bind_schannel.Flags & NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME) { ++ workstation = bind_schannel.utf8_netbios_computer.u; ++ } else { ++ DEBUG(3, ("Request for schannel to without netbios workstation\n")); ++ return NT_STATUS_LOGON_FAILURE; ++ } ++ ++ status = schannel_get_creds_state(out_mem_ctx, ++ gensec_security->settings->lp_ctx, ++ workstation, &creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ DEBUG(3, ("Could not find session key for attempted schannel connection from %s: %s\n", ++ workstation, nt_errstr(status))); ++ if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) { ++ return NT_STATUS_LOGON_FAILURE; ++ } ++ return status; ++ } ++ ++ state = netsec_create_state(gensec_security, ++ creds, false /* not initiator */); ++ if (state == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ gensec_security->private_data = state; ++ ++ bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE; ++ bind_schannel_ack.Flags = 0; ++ bind_schannel_ack.Buffer.dummy = 0x6c0000; /* actually I think ++ * this does not have ++ * any meaning here ++ * - gd */ ++ ++ ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel_ack, ++ (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); ++ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ++ status = ndr_map_error2ntstatus(ndr_err); ++ DEBUG(3, ("Could not return schannel bind ack for client %s: %s\n", ++ workstation, nt_errstr(status))); ++ return status; ++ } ++ ++ return NT_STATUS_OK; ++ } ++ return NT_STATUS_INVALID_PARAMETER; ++} ++ ++/** ++ * Returns anonymous credentials for schannel, matching Win2k3. ++ * ++ */ ++ ++static NTSTATUS schannel_session_info(struct gensec_security *gensec_security, ++ TALLOC_CTX *mem_ctx, ++ struct auth_session_info **_session_info) ++{ ++ return auth_anonymous_session_info(mem_ctx, gensec_security->settings->lp_ctx, _session_info); ++} ++ ++static NTSTATUS schannel_server_start(struct gensec_security *gensec_security) ++{ ++ return NT_STATUS_OK; ++} ++ ++static NTSTATUS schannel_client_start(struct gensec_security *gensec_security) ++{ ++ return NT_STATUS_OK; ++} ++ ++static bool schannel_have_feature(struct gensec_security *gensec_security, ++ uint32_t feature) ++{ ++ if (feature & (GENSEC_FEATURE_SIGN | ++ GENSEC_FEATURE_SEAL)) { ++ return true; ++ } ++ if (feature & GENSEC_FEATURE_DCE_STYLE) { ++ return true; ++ } ++ return false; ++} ++ ++/* ++ unseal a packet ++*/ ++static NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security, ++ uint8_t *data, size_t length, ++ const uint8_t *whole_pdu, size_t pdu_length, ++ const DATA_BLOB *sig) ++{ ++ struct schannel_state *state = ++ talloc_get_type_abort(gensec_security->private_data, ++ struct schannel_state); ++ ++ return netsec_incoming_packet(state, true, ++ discard_const_p(uint8_t, data), ++ length, sig); ++} ++ ++/* ++ check the signature on a packet ++*/ ++static NTSTATUS schannel_check_packet(struct gensec_security *gensec_security, ++ const uint8_t *data, size_t length, ++ const uint8_t *whole_pdu, size_t pdu_length, ++ const DATA_BLOB *sig) ++{ ++ struct schannel_state *state = ++ talloc_get_type_abort(gensec_security->private_data, ++ struct schannel_state); ++ ++ return netsec_incoming_packet(state, false, ++ discard_const_p(uint8_t, data), ++ length, sig); ++} ++/* ++ seal a packet ++*/ ++static NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security, ++ TALLOC_CTX *mem_ctx, ++ uint8_t *data, size_t length, ++ const uint8_t *whole_pdu, size_t pdu_length, ++ DATA_BLOB *sig) ++{ ++ struct schannel_state *state = ++ talloc_get_type_abort(gensec_security->private_data, ++ struct schannel_state); ++ ++ return netsec_outgoing_packet(state, mem_ctx, true, ++ data, length, sig); ++} ++ ++/* ++ sign a packet ++*/ ++static NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security, ++ TALLOC_CTX *mem_ctx, ++ const uint8_t *data, size_t length, ++ const uint8_t *whole_pdu, size_t pdu_length, ++ DATA_BLOB *sig) ++{ ++ struct schannel_state *state = ++ talloc_get_type_abort(gensec_security->private_data, ++ struct schannel_state); ++ ++ return netsec_outgoing_packet(state, mem_ctx, false, ++ discard_const_p(uint8_t, data), ++ length, sig); ++} ++ ++static const struct gensec_security_ops gensec_schannel_security_ops = { ++ .name = "schannel", ++ .auth_type = DCERPC_AUTH_TYPE_SCHANNEL, ++ .client_start = schannel_client_start, ++ .server_start = schannel_server_start, ++ .update = schannel_update, ++ .seal_packet = schannel_seal_packet, ++ .sign_packet = schannel_sign_packet, ++ .check_packet = schannel_check_packet, ++ .unseal_packet = schannel_unseal_packet, ++ .session_info = schannel_session_info, ++ .sig_size = schannel_sig_size, ++ .have_feature = schannel_have_feature, ++ .enabled = true, ++ .priority = GENSEC_SCHANNEL ++}; ++ ++_PUBLIC_ NTSTATUS gensec_schannel_init(void) ++{ ++ NTSTATUS ret; ++ ret = gensec_register(&gensec_schannel_security_ops); ++ if (!NT_STATUS_IS_OK(ret)) { ++ DEBUG(0,("Failed to register '%s' gensec backend!\n", ++ gensec_schannel_security_ops.name)); ++ return ret; ++ } ++ ++ return ret; ++} +diff --git a/auth/gensec/wscript_build b/auth/gensec/wscript_build +index 71222f7..7329eec 100755 +--- a/auth/gensec/wscript_build ++++ b/auth/gensec/wscript_build +@@ -17,6 +17,14 @@ bld.SAMBA_MODULE('gensec_spnego', + deps='asn1util samba-credentials SPNEGO_PARSE' + ) + ++bld.SAMBA_MODULE('gensec_schannel', ++ source='schannel.c', ++ autoproto='schannel_proto.h', ++ subsystem='gensec', ++ init_function='gensec_schannel_init', ++ deps='COMMON_SCHANNEL NDR_SCHANNEL samba-credentials auth_session' ++ ) ++ + bld.SAMBA_MODULE('gensec_external', + source='external.c', + autoproto='external_proto.h', +diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c +deleted file mode 100644 +index eb2e100..0000000 +--- a/source4/auth/gensec/schannel.c ++++ /dev/null +@@ -1,330 +0,0 @@ +-/* +- Unix SMB/CIFS implementation. +- +- dcerpc schannel operations +- +- Copyright (C) Andrew Tridgell 2004 +- Copyright (C) Andrew Bartlett 2004-2005 +- +- 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 . +-*/ +- +-#include "includes.h" +-#include "librpc/gen_ndr/ndr_schannel.h" +-#include "auth/auth.h" +-#include "auth/credentials/credentials.h" +-#include "auth/gensec/gensec.h" +-#include "auth/gensec/gensec_internal.h" +-#include "auth/gensec/gensec_proto.h" +-#include "../libcli/auth/schannel.h" +-#include "librpc/gen_ndr/dcerpc.h" +-#include "param/param.h" +-#include "auth/gensec/gensec_toplevel_proto.h" +- +-_PUBLIC_ NTSTATUS gensec_schannel_init(void); +- +-static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t data_size) +-{ +- struct schannel_state *state = +- talloc_get_type_abort(gensec_security->private_data, +- struct schannel_state); +- +- return netsec_outgoing_sig_size(state); +-} +- +-static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, +- struct tevent_context *ev, +- const DATA_BLOB in, DATA_BLOB *out) +-{ +- struct schannel_state *state = +- talloc_get_type(gensec_security->private_data, +- struct schannel_state); +- NTSTATUS status; +- enum ndr_err_code ndr_err; +- struct NL_AUTH_MESSAGE bind_schannel; +- struct NL_AUTH_MESSAGE bind_schannel_ack; +- struct netlogon_creds_CredentialState *creds; +- const char *workstation; +- const char *domain; +- +- *out = data_blob(NULL, 0); +- +- switch (gensec_security->gensec_role) { +- case GENSEC_CLIENT: +- if (state != NULL) { +- /* we could parse the bind ack, but we don't know what it is yet */ +- return NT_STATUS_OK; +- } +- +- creds = cli_credentials_get_netlogon_creds(gensec_security->credentials); +- if (creds == NULL) { +- return NT_STATUS_INVALID_PARAMETER_MIX; +- } +- +- state = netsec_create_state(gensec_security, +- creds, true /* initiator */); +- if (state == NULL) { +- return NT_STATUS_NO_MEMORY; +- } +- gensec_security->private_data = state; +- +- bind_schannel.MessageType = NL_NEGOTIATE_REQUEST; +-#if 0 +- /* to support this we'd need to have access to the full domain name */ +- /* 0x17, 23 */ +- bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | +- NL_FLAG_OEM_NETBIOS_COMPUTER_NAME | +- NL_FLAG_UTF8_DNS_DOMAIN_NAME | +- NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME; +- bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); +- bind_schannel.oem_netbios_computer.a = creds->computer_name; +- bind_schannel.utf8_dns_domain = cli_credentials_get_realm(gensec_security->credentials); +- /* w2k3 refuses us if we use the full DNS workstation? +- why? perhaps because we don't fill in the dNSHostName +- attribute in the machine account? */ +- bind_schannel.utf8_netbios_computer = creds->computer_name; +-#else +- bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | +- NL_FLAG_OEM_NETBIOS_COMPUTER_NAME; +- bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); +- bind_schannel.oem_netbios_computer.a = creds->computer_name; +-#endif +- +- ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel, +- (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); +- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { +- status = ndr_map_error2ntstatus(ndr_err); +- DEBUG(3, ("Could not create schannel bind: %s\n", +- nt_errstr(status))); +- return status; +- } +- +- return NT_STATUS_MORE_PROCESSING_REQUIRED; +- case GENSEC_SERVER: +- +- if (state != NULL) { +- /* no third leg on this protocol */ +- return NT_STATUS_INVALID_PARAMETER; +- } +- +- /* parse the schannel startup blob */ +- ndr_err = ndr_pull_struct_blob(&in, out_mem_ctx, &bind_schannel, +- (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE); +- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { +- status = ndr_map_error2ntstatus(ndr_err); +- DEBUG(3, ("Could not parse incoming schannel bind: %s\n", +- nt_errstr(status))); +- return status; +- } +- +- if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_DOMAIN_NAME) { +- domain = bind_schannel.oem_netbios_domain.a; +- if (strcasecmp_m(domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)) != 0) { +- DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n", +- domain, lpcfg_workgroup(gensec_security->settings->lp_ctx))); +- return NT_STATUS_LOGON_FAILURE; +- } +- } else if (bind_schannel.Flags & NL_FLAG_UTF8_DNS_DOMAIN_NAME) { +- domain = bind_schannel.utf8_dns_domain.u; +- if (strcasecmp_m(domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)) != 0) { +- DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n", +- domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx))); +- return NT_STATUS_LOGON_FAILURE; +- } +- } else { +- DEBUG(3, ("Request for schannel to without domain\n")); +- return NT_STATUS_LOGON_FAILURE; +- } +- +- if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME) { +- workstation = bind_schannel.oem_netbios_computer.a; +- } else if (bind_schannel.Flags & NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME) { +- workstation = bind_schannel.utf8_netbios_computer.u; +- } else { +- DEBUG(3, ("Request for schannel to without netbios workstation\n")); +- return NT_STATUS_LOGON_FAILURE; +- } +- +- status = schannel_get_creds_state(out_mem_ctx, +- gensec_security->settings->lp_ctx, +- workstation, &creds); +- if (!NT_STATUS_IS_OK(status)) { +- DEBUG(3, ("Could not find session key for attempted schannel connection from %s: %s\n", +- workstation, nt_errstr(status))); +- if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) { +- return NT_STATUS_LOGON_FAILURE; +- } +- return status; +- } +- +- state = netsec_create_state(gensec_security, +- creds, false /* not initiator */); +- if (state == NULL) { +- return NT_STATUS_NO_MEMORY; +- } +- gensec_security->private_data = state; +- +- bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE; +- bind_schannel_ack.Flags = 0; +- bind_schannel_ack.Buffer.dummy = 0x6c0000; /* actually I think +- * this does not have +- * any meaning here +- * - gd */ +- +- ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel_ack, +- (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); +- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { +- status = ndr_map_error2ntstatus(ndr_err); +- DEBUG(3, ("Could not return schannel bind ack for client %s: %s\n", +- workstation, nt_errstr(status))); +- return status; +- } +- +- return NT_STATUS_OK; +- } +- return NT_STATUS_INVALID_PARAMETER; +-} +- +-/** +- * Returns anonymous credentials for schannel, matching Win2k3. +- * +- */ +- +-static NTSTATUS schannel_session_info(struct gensec_security *gensec_security, +- TALLOC_CTX *mem_ctx, +- struct auth_session_info **_session_info) +-{ +- return auth_anonymous_session_info(mem_ctx, gensec_security->settings->lp_ctx, _session_info); +-} +- +-static NTSTATUS schannel_server_start(struct gensec_security *gensec_security) +-{ +- return NT_STATUS_OK; +-} +- +-static NTSTATUS schannel_client_start(struct gensec_security *gensec_security) +-{ +- return NT_STATUS_OK; +-} +- +-static bool schannel_have_feature(struct gensec_security *gensec_security, +- uint32_t feature) +-{ +- if (feature & (GENSEC_FEATURE_SIGN | +- GENSEC_FEATURE_SEAL)) { +- return true; +- } +- if (feature & GENSEC_FEATURE_DCE_STYLE) { +- return true; +- } +- return false; +-} +- +-/* +- unseal a packet +-*/ +-static NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security, +- uint8_t *data, size_t length, +- const uint8_t *whole_pdu, size_t pdu_length, +- const DATA_BLOB *sig) +-{ +- struct schannel_state *state = +- talloc_get_type_abort(gensec_security->private_data, +- struct schannel_state); +- +- return netsec_incoming_packet(state, true, +- discard_const_p(uint8_t, data), +- length, sig); +-} +- +-/* +- check the signature on a packet +-*/ +-static NTSTATUS schannel_check_packet(struct gensec_security *gensec_security, +- const uint8_t *data, size_t length, +- const uint8_t *whole_pdu, size_t pdu_length, +- const DATA_BLOB *sig) +-{ +- struct schannel_state *state = +- talloc_get_type_abort(gensec_security->private_data, +- struct schannel_state); +- +- return netsec_incoming_packet(state, false, +- discard_const_p(uint8_t, data), +- length, sig); +-} +-/* +- seal a packet +-*/ +-static NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security, +- TALLOC_CTX *mem_ctx, +- uint8_t *data, size_t length, +- const uint8_t *whole_pdu, size_t pdu_length, +- DATA_BLOB *sig) +-{ +- struct schannel_state *state = +- talloc_get_type_abort(gensec_security->private_data, +- struct schannel_state); +- +- return netsec_outgoing_packet(state, mem_ctx, true, +- data, length, sig); +-} +- +-/* +- sign a packet +-*/ +-static NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security, +- TALLOC_CTX *mem_ctx, +- const uint8_t *data, size_t length, +- const uint8_t *whole_pdu, size_t pdu_length, +- DATA_BLOB *sig) +-{ +- struct schannel_state *state = +- talloc_get_type_abort(gensec_security->private_data, +- struct schannel_state); +- +- return netsec_outgoing_packet(state, mem_ctx, false, +- discard_const_p(uint8_t, data), +- length, sig); +-} +- +-static const struct gensec_security_ops gensec_schannel_security_ops = { +- .name = "schannel", +- .auth_type = DCERPC_AUTH_TYPE_SCHANNEL, +- .client_start = schannel_client_start, +- .server_start = schannel_server_start, +- .update = schannel_update, +- .seal_packet = schannel_seal_packet, +- .sign_packet = schannel_sign_packet, +- .check_packet = schannel_check_packet, +- .unseal_packet = schannel_unseal_packet, +- .session_info = schannel_session_info, +- .sig_size = schannel_sig_size, +- .have_feature = schannel_have_feature, +- .enabled = true, +- .priority = GENSEC_SCHANNEL +-}; +- +-_PUBLIC_ NTSTATUS gensec_schannel_init(void) +-{ +- NTSTATUS ret; +- ret = gensec_register(&gensec_schannel_security_ops); +- if (!NT_STATUS_IS_OK(ret)) { +- DEBUG(0,("Failed to register '%s' gensec backend!\n", +- gensec_schannel_security_ops.name)); +- return ret; +- } +- +- return ret; +-} +diff --git a/source4/auth/gensec/wscript_build b/source4/auth/gensec/wscript_build +index 04fccc5..a3eff97 100755 +--- a/source4/auth/gensec/wscript_build ++++ b/source4/auth/gensec/wscript_build +@@ -32,16 +32,6 @@ bld.SAMBA_MODULE('cyrus_sasl', + ) + + +-bld.SAMBA_MODULE('gensec_schannel', +- source='schannel.c', +- subsystem='gensec', +- deps='COMMON_SCHANNEL NDR_SCHANNEL samba-credentials ndr auth_session', +- internal_module=True, +- autoproto='schannel_proto.h', +- init_function='gensec_schannel_init' +- ) +- +- + bld.SAMBA_PYTHON('pygensec', + source='pygensec.c', + deps='gensec pytalloc-util pyparam_util', +-- +1.9.3 + + +From c4829848f45db27d6c145b35a20bea2f33bcb4d7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 18 Sep 2013 17:24:49 +0200 +Subject: [PATCH 094/249] gensec: remove duplicate + gensec_security_by_authtype() call. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We should use the equivalent gensec_security_by_auth_type() call which is +exposed in the public header. + +Guenther + +Signed-off-by: Günther Deschner +Pair-Programmed-With: Andreas Schneider +Reviewed-by: Stefan Metzmacher +(cherry picked from commit d433ad077f354de4fc1d5a155d991f417ae9967c) +--- + auth/gensec/gensec_start.c | 29 ++--------------------------- + 1 file changed, 2 insertions(+), 27 deletions(-) + +diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c +index 3ae64d5..906ef67 100644 +--- a/auth/gensec/gensec_start.c ++++ b/auth/gensec/gensec_start.c +@@ -157,31 +157,6 @@ _PUBLIC_ const struct gensec_security_ops **gensec_security_mechs( + + } + +-static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security, +- uint8_t auth_type) +-{ +- int i; +- const struct gensec_security_ops **backends; +- const struct gensec_security_ops *backend; +- TALLOC_CTX *mem_ctx = talloc_new(gensec_security); +- if (!mem_ctx) { +- return NULL; +- } +- backends = gensec_security_mechs(gensec_security, mem_ctx); +- for (i=0; backends && backends[i]; i++) { +- if (!gensec_security_ops_enabled(backends[i], gensec_security)) +- continue; +- if (backends[i]->auth_type == auth_type) { +- backend = backends[i]; +- talloc_free(mem_ctx); +- return backend; +- } +- } +- talloc_free(mem_ctx); +- +- return NULL; +-} +- + _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid( + struct gensec_security *gensec_security, + const char *oid_string) +@@ -719,7 +694,7 @@ NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security, + _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security, + uint8_t auth_type, uint8_t auth_level) + { +- gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type); ++ gensec_security->ops = gensec_security_by_auth_type(gensec_security, auth_type); + if (!gensec_security->ops) { + DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type)); + return NT_STATUS_INVALID_PARAMETER; +@@ -746,7 +721,7 @@ _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_s + _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype) + { + const struct gensec_security_ops *ops; +- ops = gensec_security_by_authtype(gensec_security, authtype); ++ ops = gensec_security_by_auth_type(gensec_security, authtype); + if (ops) { + return ops->name; + } +-- +1.9.3 + + +From 8c54d2ee4861a35def7cce29b900a68112356f6b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 18 Sep 2013 17:25:55 +0200 +Subject: [PATCH 095/249] gensec: check for NULL gensec_security in + gensec_security_by_auth_type(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We have equivalent checks in other gensec_security_by_X calls already. + +Guenther + +Signed-off-by: Günther Deschner +Pair-Programmed-With: Andreas Schneider +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 4f979525e4137c536118a9c2b2b4ef798c270e27) +--- + auth/gensec/gensec_start.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c +index 906ef67..476134a 100644 +--- a/auth/gensec/gensec_start.c ++++ b/auth/gensec/gensec_start.c +@@ -230,8 +230,10 @@ _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type( + } + backends = gensec_security_mechs(gensec_security, mem_ctx); + for (i=0; backends && backends[i]; i++) { +- if (!gensec_security_ops_enabled(backends[i], gensec_security)) +- continue; ++ if (gensec_security != NULL && ++ !gensec_security_ops_enabled(backends[i], gensec_security)) { ++ continue; ++ } + if (backends[i]->auth_type == auth_type) { + backend = backends[i]; + talloc_free(mem_ctx); +-- +1.9.3 + + +From 5b941811c7ebd51bf2c8d421517fd92b3065ba47 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 18 Sep 2013 17:27:28 +0200 +Subject: [PATCH 096/249] s3-auth: also load schannel module from + auth_generic_client_prepare(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Pair-Programmed-With: Andreas Schneider +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 8fce75aa58ec70547ad218bde154e141f2d17303) +--- + source3/libsmb/auth_generic.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/source3/libsmb/auth_generic.c b/source3/libsmb/auth_generic.c +index e30c1b7..3130dec 100644 +--- a/source3/libsmb/auth_generic.c ++++ b/source3/libsmb/auth_generic.c +@@ -78,7 +78,7 @@ NTSTATUS auth_generic_client_prepare(TALLOC_CTX *mem_ctx, struct auth_generic_st + } + + backends = talloc_zero_array(gensec_settings, +- const struct gensec_security_ops *, 4); ++ const struct gensec_security_ops *, 5); + if (backends == NULL) { + TALLOC_FREE(ans); + return NT_STATUS_NO_MEMORY; +@@ -95,6 +95,7 @@ NTSTATUS auth_generic_client_prepare(TALLOC_CTX *mem_ctx, struct auth_generic_st + backends[idx++] = &gensec_ntlmssp3_client_ops; + + backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO); ++ backends[idx++] = gensec_security_by_auth_type(NULL, DCERPC_AUTH_TYPE_SCHANNEL); + + nt_status = gensec_client_start(ans, &ans->gensec_security, gensec_settings); + +-- +1.9.3 + + +From 28b5f156bcc03b88f8c0f3e52cd051a0b069334e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 18 Sep 2013 17:44:10 +0200 +Subject: [PATCH 097/249] s3-rpc_cli: allow to pass down a netlogon + CredentialState struct to gensec. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Pair-Programmed-With: Andreas Schneider +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 7b570b4128f9af212048ce56abd841a1f6fdc259) +--- + source3/rpc_client/cli_pipe.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 470469f..2acbad6 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -2178,6 +2178,7 @@ static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx, + const char *username, + const char *password, + enum credentials_use_kerberos use_kerberos, ++ struct netlogon_creds_CredentialState *creds, + struct pipe_auth_data **presult) + { + struct auth_generic_state *auth_generic_ctx; +@@ -2231,6 +2232,7 @@ static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx, + } + + cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos); ++ cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds); + + status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level); + if (!NT_STATUS_IS_OK(status)) { +@@ -2830,6 +2832,7 @@ NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli, + server, target_service, + domain, username, password, + CRED_AUTO_USE_KERBEROS, ++ NULL, + &auth); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("rpccli_generic_bind_data returned %s\n", +@@ -3057,7 +3060,7 @@ NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli, + DCERPC_AUTH_TYPE_SPNEGO, auth_level, + server, target_service, + domain, username, password, +- use_kerberos, ++ use_kerberos, NULL, + &auth); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("rpccli_generic_bind_data returned %s\n", +-- +1.9.3 + + +From 4775b3fd2905e54b2c824d901fd8a99fb8caae04 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 18 Sep 2013 18:23:40 +0200 +Subject: [PATCH 098/249] s3-auth: register schannel gensec module in + auth_generic_prepare() as well. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Pair-Programmed-With: Andreas Schneider +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 090671aca5234f47f390054de771198e3c177060) +--- + source3/auth/auth_generic.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c +index e15c87e..e07d3b7 100644 +--- a/source3/auth/auth_generic.c ++++ b/source3/auth/auth_generic.c +@@ -32,6 +32,7 @@ + #include "librpc/crypto/gse.h" + #include "auth/credentials/credentials.h" + #include "lib/param/loadparm.h" ++#include "librpc/gen_ndr/dcerpc.h" + + static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + TALLOC_CTX *mem_ctx, +@@ -261,7 +262,7 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx, + } + + backends = talloc_zero_array(gensec_settings, +- const struct gensec_security_ops *, 4); ++ const struct gensec_security_ops *, 5); + if (backends == NULL) { + TALLOC_FREE(tmp_ctx); + return NT_STATUS_NO_MEMORY; +@@ -279,6 +280,8 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx, + + backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO); + ++ backends[idx++] = gensec_security_by_auth_type(NULL, DCERPC_AUTH_TYPE_SCHANNEL); ++ + /* + * This is anonymous for now, because we just use it + * to set the kerberos state at the moment +-- +1.9.3 + + +From 080c2ac3cbd28318bc6c682dff0aea17fad07a2c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 18 Sep 2013 18:33:14 +0200 +Subject: [PATCH 099/249] s3-rpc_cli: use gensec for schannel bind. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Pair-Programmed-With: Andreas Schneider +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 89d0b89b5d58ceef13bc10036d396b10f8a102ae) +--- + source3/rpc_client/cli_pipe.c | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 2acbad6..8a642e2 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -1120,12 +1120,6 @@ static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx, + + switch (auth->auth_type) { + case DCERPC_AUTH_TYPE_SCHANNEL: +- ret = create_schannel_auth_rpc_bind_req(cli, &auth_token); +- if (!NT_STATUS_IS_OK(ret)) { +- return ret; +- } +- break; +- + case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_KRB5: + case DCERPC_AUTH_TYPE_SPNEGO: +@@ -2884,16 +2878,26 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + struct netr_Authenticator auth; + struct netr_Authenticator return_auth; + union netr_Capabilities capabilities; ++ const char *target_service = table->authservices->names[0]; + + status = cli_rpc_pipe_open(cli, transport, table, &rpccli); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + +- status = rpccli_schannel_bind_data(rpccli, domain, auth_level, +- *pdc, &rpcauth); ++ status = rpccli_generic_bind_data(rpccli, ++ DCERPC_AUTH_TYPE_SCHANNEL, ++ auth_level, ++ NULL, ++ target_service, ++ domain, ++ (*pdc)->computer_name, ++ NULL, ++ CRED_AUTO_USE_KERBEROS, ++ *pdc, ++ &rpcauth); + if (!NT_STATUS_IS_OK(status)) { +- DEBUG(0, ("rpccli_schannel_bind_data returned %s\n", ++ DEBUG(0, ("rpccli_generic_bind_data returned %s\n", + nt_errstr(status))); + TALLOC_FREE(rpccli); + return status; +-- +1.9.3 + + +From 40ffd89f975e06821379fbd240187f5e268da5fe Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 18 Sep 2013 18:34:58 +0200 +Subject: [PATCH 100/249] s3-rpc_srv: use gensec for schannel bind. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Pair-Programmed-With: Andreas Schneider +Reviewed-by: Stefan Metzmacher +(cherry picked from commit a32a83ba9d6c7b5bbe9077973e5402ba65c068e7) +--- + source3/rpc_server/srv_pipe.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c +index 9043a14..fd7a90a 100644 +--- a/source3/rpc_server/srv_pipe.c ++++ b/source3/rpc_server/srv_pipe.c +@@ -808,10 +808,15 @@ static bool api_pipe_bind_req(struct pipes_struct *p, + break; + + case DCERPC_AUTH_TYPE_SCHANNEL: +- if (!pipe_schannel_auth_bind(p, pkt, +- &auth_info, &auth_resp)) { ++ if (!pipe_auth_generic_bind(p, pkt, ++ &auth_info, &auth_resp)) { ++ goto err_exit; ++ } ++ if (!session_info_set_session_key(p->session_info, generic_session_key())) { ++ DEBUG(0, ("session_info_set_session_key failed\n")); + goto err_exit; + } ++ p->pipe_bound = true; + break; + + case DCERPC_AUTH_TYPE_SPNEGO: +-- +1.9.3 + + +From 285de020b6e284ad5074492d62740ba8a370826a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 18 Sep 2013 18:36:19 +0200 +Subject: [PATCH 101/249] s3-rpc: use gensec for schannel footer processing. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Pair-Programmed-With: Andreas Schneider +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 5a628490e46f428432cd9b32c2b4b3a34a3736ae) +--- + source3/librpc/rpc/dcerpc_helpers.c | 35 +++-------------------------------- + 1 file changed, 3 insertions(+), 32 deletions(-) + +diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c +index 97999d7..b9e05cb 100644 +--- a/source3/librpc/rpc/dcerpc_helpers.c ++++ b/source3/librpc/rpc/dcerpc_helpers.c +@@ -273,7 +273,6 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, + size_t max_len; + size_t mod_len; + struct gensec_security *gensec_security; +- struct schannel_state *schannel_auth; + + /* no auth token cases first */ + switch (auth->auth_level) { +@@ -307,16 +306,11 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, + case DCERPC_AUTH_TYPE_SPNEGO: + case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_KRB5: ++ case DCERPC_AUTH_TYPE_SCHANNEL: + gensec_security = talloc_get_type_abort(auth->auth_ctx, + struct gensec_security); + *auth_len = gensec_sig_size(gensec_security, max_len); + break; +- +- case DCERPC_AUTH_TYPE_SCHANNEL: +- schannel_auth = talloc_get_type_abort(auth->auth_ctx, +- struct schannel_state); +- *auth_len = netsec_outgoing_sig_size(schannel_auth); +- break; + default: + return NT_STATUS_INVALID_PARAMETER; + } +@@ -548,7 +542,6 @@ static NTSTATUS get_schannel_auth_footer(TALLOC_CTX *mem_ctx, + NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth, + size_t pad_len, DATA_BLOB *rpc_out) + { +- struct schannel_state *schannel_auth; + struct gensec_security *gensec_security; + char pad[CLIENT_NDR_PADDING_SIZE] = { 0, }; + DATA_BLOB auth_info; +@@ -600,19 +593,13 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth, + case DCERPC_AUTH_TYPE_SPNEGO: + case DCERPC_AUTH_TYPE_KRB5: + case DCERPC_AUTH_TYPE_NTLMSSP: ++ case DCERPC_AUTH_TYPE_SCHANNEL: + gensec_security = talloc_get_type_abort(auth->auth_ctx, + struct gensec_security); + status = add_generic_auth_footer(gensec_security, + auth->auth_level, + rpc_out); + break; +- case DCERPC_AUTH_TYPE_SCHANNEL: +- schannel_auth = talloc_get_type_abort(auth->auth_ctx, +- struct schannel_state); +- status = add_schannel_auth_footer(schannel_auth, +- auth->auth_level, +- rpc_out); +- break; + default: + status = NT_STATUS_INVALID_PARAMETER; + break; +@@ -640,7 +627,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, + DATA_BLOB *raw_pkt, + size_t *pad_len) + { +- struct schannel_state *schannel_auth; + struct gensec_security *gensec_security; + NTSTATUS status; + struct dcerpc_auth auth_info; +@@ -710,6 +696,7 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, + case DCERPC_AUTH_TYPE_SPNEGO: + case DCERPC_AUTH_TYPE_KRB5: + case DCERPC_AUTH_TYPE_NTLMSSP: ++ case DCERPC_AUTH_TYPE_SCHANNEL: + + DEBUG(10, ("GENSEC auth\n")); + +@@ -723,22 +710,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, + return status; + } + break; +- +- case DCERPC_AUTH_TYPE_SCHANNEL: +- +- DEBUG(10, ("SCHANNEL auth\n")); +- +- schannel_auth = talloc_get_type_abort(auth->auth_ctx, +- struct schannel_state); +- status = get_schannel_auth_footer(pkt, schannel_auth, +- auth->auth_level, +- &data, &full_pkt, +- &auth_info.credentials); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- break; +- + default: + DEBUG(0, ("process_request_pdu: " + "unknown auth type %u set.\n", +-- +1.9.3 + + +From cfa396d153cedb9b10356540a479ff299c480cae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Thu, 19 Sep 2013 11:03:31 +0200 +Subject: [PATCH 102/249] s3-rpc_cli: remove unused schannel calls from + dcerpc_helpers.c +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 639f60b1513a8c877d307ed86b7748250821fb3f) +--- + source3/librpc/rpc/dcerpc.h | 3 - + source3/librpc/rpc/dcerpc_helpers.c | 124 ------------------------------------ + 2 files changed, 127 deletions(-) + +diff --git a/source3/librpc/rpc/dcerpc.h b/source3/librpc/rpc/dcerpc.h +index b3ae3b4..38d59cd 100644 +--- a/source3/librpc/rpc/dcerpc.h ++++ b/source3/librpc/rpc/dcerpc.h +@@ -60,9 +60,6 @@ NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx, + const DATA_BLOB *blob, + struct ncacn_packet *r, + bool bigendian); +-NTSTATUS dcerpc_push_schannel_bind(TALLOC_CTX *mem_ctx, +- struct NL_AUTH_MESSAGE *r, +- DATA_BLOB *blob); + NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, +diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c +index b9e05cb..2400bfd 100644 +--- a/source3/librpc/rpc/dcerpc_helpers.c ++++ b/source3/librpc/rpc/dcerpc_helpers.c +@@ -21,9 +21,6 @@ + #include "includes.h" + #include "librpc/rpc/dcerpc.h" + #include "librpc/gen_ndr/ndr_dcerpc.h" +-#include "librpc/gen_ndr/ndr_schannel.h" +-#include "../libcli/auth/schannel.h" +-#include "../libcli/auth/spnego.h" + #include "librpc/crypto/gse.h" + #include "auth/gensec/gensec.h" + +@@ -135,34 +132,6 @@ NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx, + } + + /** +-* @brief NDR Encodes a NL_AUTH_MESSAGE +-* +-* @param mem_ctx The memory context the blob will be allocated on +-* @param r The NL_AUTH_MESSAGE to encode +-* @param blob [out] The encoded blob if successful +-* +-* @return a NTSTATUS error code +-*/ +-NTSTATUS dcerpc_push_schannel_bind(TALLOC_CTX *mem_ctx, +- struct NL_AUTH_MESSAGE *r, +- DATA_BLOB *blob) +-{ +- enum ndr_err_code ndr_err; +- +- ndr_err = ndr_push_struct_blob(blob, mem_ctx, r, +- (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); +- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { +- return ndr_map_error2ntstatus(ndr_err); +- } +- +- if (DEBUGLEVEL >= 10) { +- NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, r); +- } +- +- return NT_STATUS_OK; +-} +- +-/** + * @brief NDR Encodes a dcerpc_auth structure + * + * @param mem_ctx The memory context the blob will be allocated on +@@ -437,99 +406,6 @@ static NTSTATUS get_generic_auth_footer(struct gensec_security *gensec_security, + } + } + +-/******************************************************************* +- Create and add the schannel sign/seal auth data. +- ********************************************************************/ +- +-static NTSTATUS add_schannel_auth_footer(struct schannel_state *sas, +- enum dcerpc_AuthLevel auth_level, +- DATA_BLOB *rpc_out) +-{ +- uint8_t *data_p = rpc_out->data + DCERPC_RESPONSE_LENGTH; +- size_t data_and_pad_len = rpc_out->length +- - DCERPC_RESPONSE_LENGTH +- - DCERPC_AUTH_TRAILER_LENGTH; +- DATA_BLOB auth_blob; +- NTSTATUS status; +- +- if (!sas) { +- return NT_STATUS_INVALID_PARAMETER; +- } +- +- switch (auth_level) { +- case DCERPC_AUTH_LEVEL_PRIVACY: +- status = netsec_outgoing_packet(sas, +- rpc_out->data, +- true, +- data_p, +- data_and_pad_len, +- &auth_blob); +- break; +- case DCERPC_AUTH_LEVEL_INTEGRITY: +- status = netsec_outgoing_packet(sas, +- rpc_out->data, +- false, +- data_p, +- data_and_pad_len, +- &auth_blob); +- break; +- default: +- status = NT_STATUS_INTERNAL_ERROR; +- break; +- } +- +- if (!NT_STATUS_IS_OK(status)) { +- DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n", +- nt_errstr(status))); +- return status; +- } +- +- if (DEBUGLEVEL >= 10) { +- dump_NL_AUTH_SIGNATURE(talloc_tos(), &auth_blob); +- } +- +- /* Finally attach the blob. */ +- if (!data_blob_append(NULL, rpc_out, +- auth_blob.data, auth_blob.length)) { +- return NT_STATUS_NO_MEMORY; +- } +- data_blob_free(&auth_blob); +- +- return NT_STATUS_OK; +-} +- +-/******************************************************************* +- Check/unseal the Schannel auth data. (Unseal in place). +- ********************************************************************/ +- +-static NTSTATUS get_schannel_auth_footer(TALLOC_CTX *mem_ctx, +- struct schannel_state *auth_state, +- enum dcerpc_AuthLevel auth_level, +- DATA_BLOB *data, DATA_BLOB *full_pkt, +- DATA_BLOB *auth_token) +-{ +- switch (auth_level) { +- case DCERPC_AUTH_LEVEL_PRIVACY: +- /* Data portion is encrypted. */ +- return netsec_incoming_packet(auth_state, +- true, +- data->data, +- data->length, +- auth_token); +- +- case DCERPC_AUTH_LEVEL_INTEGRITY: +- /* Data is signed. */ +- return netsec_incoming_packet(auth_state, +- false, +- data->data, +- data->length, +- auth_token); +- +- default: +- return NT_STATUS_INVALID_PARAMETER; +- } +-} +- + /** + * @brief Append an auth footer according to what is the current mechanism + * +-- +1.9.3 + + +From 3c10a3501c04e1f5f9bd2bb1418b95b4b17248a8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Thu, 19 Sep 2013 11:04:19 +0200 +Subject: [PATCH 103/249] s3-rpc_cli: remove unused schannel calls from + cli_pipe.c +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 45949d721892a0e8a6b1a76e221c6b3bfd6a872f) +--- + source3/rpc_client/cli_pipe.c | 76 ------------------------------------------- + 1 file changed, 76 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 8a642e2..b73f2f2 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -22,11 +22,8 @@ + #include "includes.h" + #include "../lib/util/tevent_ntstatus.h" + #include "librpc/gen_ndr/ndr_epmapper_c.h" +-#include "../librpc/gen_ndr/ndr_schannel.h" + #include "../librpc/gen_ndr/ndr_dssetup.h" + #include "../libcli/auth/schannel.h" +-#include "../libcli/auth/spnego.h" +-#include "../auth/ntlmssp/ntlmssp.h" + #include "auth_generic.h" + #include "librpc/gen_ndr/ndr_dcerpc.h" + #include "librpc/gen_ndr/ndr_netlogon_c.h" +@@ -1018,42 +1015,6 @@ static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli, + } + + /******************************************************************* +- Creates schannel auth bind. +- ********************************************************************/ +- +-static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli, +- DATA_BLOB *auth_token) +-{ +- NTSTATUS status; +- struct NL_AUTH_MESSAGE r; +- +- if (!cli->auth->user_name || !cli->auth->user_name[0]) { +- return NT_STATUS_INVALID_PARAMETER_MIX; +- } +- +- if (!cli->auth->domain || !cli->auth->domain[0]) { +- return NT_STATUS_INVALID_PARAMETER_MIX; +- } +- +- /* +- * Now marshall the data into the auth parse_struct. +- */ +- +- r.MessageType = NL_NEGOTIATE_REQUEST; +- r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | +- NL_FLAG_OEM_NETBIOS_COMPUTER_NAME; +- r.oem_netbios_domain.a = cli->auth->domain; +- r.oem_netbios_computer.a = cli->auth->user_name; +- +- status = dcerpc_push_schannel_bind(cli, &r, auth_token); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- +- return NT_STATUS_OK; +-} +- +-/******************************************************************* + Creates the internals of a DCE/RPC bind request or alter context PDU. + ********************************************************************/ + +@@ -2243,43 +2204,6 @@ static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx, + return status; + } + +-static NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, +- const char *domain, +- enum dcerpc_AuthLevel auth_level, +- struct netlogon_creds_CredentialState *creds, +- struct pipe_auth_data **presult) +-{ +- struct schannel_state *schannel_auth; +- struct pipe_auth_data *result; +- +- result = talloc(mem_ctx, struct pipe_auth_data); +- if (result == NULL) { +- return NT_STATUS_NO_MEMORY; +- } +- +- result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL; +- result->auth_level = auth_level; +- +- result->user_name = talloc_strdup(result, creds->computer_name); +- result->domain = talloc_strdup(result, domain); +- if ((result->user_name == NULL) || (result->domain == NULL)) { +- goto fail; +- } +- +- schannel_auth = netsec_create_state(result, creds, true /* initiator */); +- if (schannel_auth == NULL) { +- goto fail; +- } +- +- result->auth_ctx = schannel_auth; +- *presult = result; +- return NT_STATUS_OK; +- +- fail: +- TALLOC_FREE(result); +- return NT_STATUS_NO_MEMORY; +-} +- + /** + * Create an rpc pipe client struct, connecting to a tcp port. + */ +-- +1.9.3 + + +From e4b33d6311e051501815199bd6c6dbba33f1bc55 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Thu, 19 Sep 2013 11:05:21 +0200 +Subject: [PATCH 104/249] s3-rpc_srv: remove unused schannel calls from + srv_pipe.c +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher + +Autobuild-User(master): Günther Deschner +Autobuild-Date(master): Thu Sep 19 12:59:04 CEST 2013 on sn-devel-104 +(cherry picked from commit 6965f918c04328535c55a0ef9b7fe6392fba193a) +--- + source3/rpc_server/srv_pipe.c | 116 ------------------------------------------ + 1 file changed, 116 deletions(-) + +diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c +index fd7a90a..06752a8 100644 +--- a/source3/rpc_server/srv_pipe.c ++++ b/source3/rpc_server/srv_pipe.c +@@ -30,11 +30,8 @@ + #include "includes.h" + #include "system/filesys.h" + #include "srv_pipe_internal.h" +-#include "../librpc/gen_ndr/ndr_schannel.h" + #include "../librpc/gen_ndr/dcerpc.h" + #include "../librpc/rpc/rpc_common.h" +-#include "../libcli/auth/schannel.h" +-#include "../libcli/auth/spnego.h" + #include "dcesrv_auth_generic.h" + #include "rpc_server.h" + #include "rpc_dce.h" +@@ -415,119 +412,6 @@ bool is_known_pipename(const char *pipename, struct ndr_syntax_id *syntax) + } + + /******************************************************************* +- Handle an schannel bind auth. +-*******************************************************************/ +- +-static bool pipe_schannel_auth_bind(struct pipes_struct *p, +- TALLOC_CTX *mem_ctx, +- struct dcerpc_auth *auth_info, +- DATA_BLOB *response) +-{ +- struct NL_AUTH_MESSAGE neg; +- struct NL_AUTH_MESSAGE reply; +- bool ret; +- NTSTATUS status; +- struct netlogon_creds_CredentialState *creds; +- enum ndr_err_code ndr_err; +- struct schannel_state *schannel_auth; +- struct loadparm_context *lp_ctx; +- +- ndr_err = ndr_pull_struct_blob( +- &auth_info->credentials, mem_ctx, &neg, +- (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE); +- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { +- DEBUG(0,("pipe_schannel_auth_bind: Could not unmarshal SCHANNEL auth neg\n")); +- return false; +- } +- +- if (DEBUGLEVEL >= 10) { +- NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, &neg); +- } +- +- if (!(neg.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME)) { +- DEBUG(0,("pipe_schannel_auth_bind: Did not receive netbios computer name\n")); +- return false; +- } +- +- lp_ctx = loadparm_init_s3(p, loadparm_s3_helpers()); +- if (!lp_ctx) { +- DEBUG(0,("pipe_schannel_auth_bind: loadparm_init_s3() failed!\n")); +- return false; +- } +- +- /* +- * The neg.oem_netbios_computer.a key here must match the remote computer name +- * given in the DOM_CLNT_SRV.uni_comp_name used on all netlogon pipe +- * operations that use credentials. +- */ +- +- become_root(); +- status = schannel_get_creds_state(p->mem_ctx, lp_ctx, +- neg.oem_netbios_computer.a, &creds); +- unbecome_root(); +- +- talloc_unlink(p, lp_ctx); +- if (!NT_STATUS_IS_OK(status)) { +- DEBUG(0, ("pipe_schannel_auth_bind: Attempt to bind using schannel without successful serverauth2\n")); +- return False; +- } +- +- schannel_auth = netsec_create_state(p, creds, false /* not initiator */); +- TALLOC_FREE(creds); +- if (!schannel_auth) { +- return False; +- } +- +- /* +- * JRA. Should we also copy the schannel session key into the pipe session key p->session_key +- * here ? We do that for NTLMSSP, but the session key is already set up from the vuser +- * struct of the person who opened the pipe. I need to test this further. JRA. +- * +- * VL. As we are mapping this to guest set the generic key +- * "SystemLibraryDTC" key here. It's a bit difficult to test against +- * W2k3, as it does not allow schannel binds against SAMR and LSA +- * anymore. +- */ +- +- ret = session_info_set_session_key(p->session_info, generic_session_key()); +- +- if (!ret) { +- DEBUG(0, ("session_info_set_session_key failed\n")); +- return false; +- } +- +- /*** SCHANNEL verifier ***/ +- +- reply.MessageType = NL_NEGOTIATE_RESPONSE; +- reply.Flags = 0; +- reply.Buffer.dummy = 5; /* ??? actually I don't think +- * this has any meaning +- * here - gd */ +- +- ndr_err = ndr_push_struct_blob(response, mem_ctx, &reply, +- (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); +- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { +- DEBUG(0,("Failed to marshall NL_AUTH_MESSAGE.\n")); +- return false; +- } +- +- if (DEBUGLEVEL >= 10) { +- NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, &reply); +- } +- +- DEBUG(10,("pipe_schannel_auth_bind: schannel auth: domain [%s] myname [%s]\n", +- neg.oem_netbios_domain.a, neg.oem_netbios_computer.a)); +- +- /* We're finished with this bind - no more packets. */ +- p->auth.auth_ctx = schannel_auth; +- p->auth.auth_type = DCERPC_AUTH_TYPE_SCHANNEL; +- +- p->pipe_bound = True; +- +- return True; +-} +- +-/******************************************************************* + Handle an NTLMSSP bind auth. + *******************************************************************/ + +-- +1.9.3 + + +From 68fbdf567cb7d0bc3550b826204c0708a771a4dc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Mon, 12 Aug 2013 17:22:15 +0200 +Subject: [PATCH 105/249] librpc/ndr: call ndr_table_list() from all ndr_X + functions. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 88c1dbf722889a2d7379cdcbac1ce9b140a42356) +--- + librpc/ndr/ndr_table.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/librpc/ndr/ndr_table.c b/librpc/ndr/ndr_table.c +index 7ca0417..01d9094 100644 +--- a/librpc/ndr/ndr_table.c ++++ b/librpc/ndr/ndr_table.c +@@ -73,7 +73,7 @@ const char *ndr_interface_name(const struct GUID *uuid, uint32_t if_version) + int ndr_interface_num_calls(const struct GUID *uuid, uint32_t if_version) + { + const struct ndr_interface_list *l; +- for (l=ndr_interfaces;l;l=l->next){ ++ for (l=ndr_table_list();l;l=l->next){ + if (GUID_equal(&l->table->syntax_id.uuid, uuid) && + l->table->syntax_id.if_version == if_version) { + return l->table->num_calls; +@@ -89,7 +89,7 @@ int ndr_interface_num_calls(const struct GUID *uuid, uint32_t if_version) + const struct ndr_interface_table *ndr_table_by_name(const char *name) + { + const struct ndr_interface_list *l; +- for (l=ndr_interfaces;l;l=l->next) { ++ for (l=ndr_table_list();l;l=l->next) { + if (strcasecmp(l->table->name, name) == 0) { + return l->table; + } +@@ -103,7 +103,7 @@ const struct ndr_interface_table *ndr_table_by_name(const char *name) + const struct ndr_interface_table *ndr_table_by_uuid(const struct GUID *uuid) + { + const struct ndr_interface_list *l; +- for (l=ndr_interfaces;l;l=l->next) { ++ for (l=ndr_table_list();l;l=l->next) { + if (GUID_equal(&l->table->syntax_id.uuid, uuid)) { + return l->table; + } +-- +1.9.3 + + +From c936c80f7e567bab6fc749fb35e60176fca020af Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Thu, 8 Aug 2013 17:34:56 +0200 +Subject: [PATCH 106/249] librpc/ndr: make sure ndr_table_list() always calls + ndr_init_table() first. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 21200b12dc14673f9a610c5798635b6052370dbe) +--- + librpc/ndr/ndr_table.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/librpc/ndr/ndr_table.c b/librpc/ndr/ndr_table.c +index 01d9094..f73b9fc 100644 +--- a/librpc/ndr/ndr_table.c ++++ b/librpc/ndr/ndr_table.c +@@ -116,6 +116,7 @@ const struct ndr_interface_table *ndr_table_by_uuid(const struct GUID *uuid) + */ + const struct ndr_interface_list *ndr_table_list(void) + { ++ ndr_table_init(); + return ndr_interfaces; + } + +-- +1.9.3 + + +From 2ced3243b3589b673967452a6401d665dd514525 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Thu, 8 Aug 2013 17:40:22 +0200 +Subject: [PATCH 107/249] s3-rpc: use table->name directly in DEBUG contexts. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +(cherry picked from commit a94e278883c58b35d383753e86135ff6a1d14ec7) +--- + source3/lib/netapi/cm.c | 2 +- + source3/rpc_client/cli_pipe.c | 7 +++---- + 2 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c +index 1cfdccf..bb5d6b2 100644 +--- a/source3/lib/netapi/cm.c ++++ b/source3/lib/netapi/cm.c +@@ -254,7 +254,7 @@ WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, + status = pipe_cm_open(ctx, ipc, table, &result); + if (!NT_STATUS_IS_OK(status)) { + libnetapi_set_error_string(ctx, "failed to open PIPE %s: %s", +- get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), ++ table->name, + get_friendly_nt_error_msg(status)); + return WERR_DEST_NOT_FOUND; + } +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index b73f2f2..64e7f1c 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -2692,8 +2692,7 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, + } + DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe " + "%s failed with error %s\n", +- get_pipe_name_from_syntax(talloc_tos(), +- &table->syntax_id), ++ table->name, + nt_errstr(status) )); + TALLOC_FREE(result); + return status; +@@ -2701,7 +2700,7 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, + + DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine " + "%s and bound anonymously.\n", +- get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), ++ table->name, + result->desthost)); + + *presult = result; +@@ -2946,7 +2945,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + done: + DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s " + "for domain %s and bound using schannel.\n", +- get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), ++ table->name, + rpccli->desthost, domain)); + + *_rpccli = rpccli; +-- +1.9.3 + + +From cd864f1a3748c219df78600fc826a6e1d81fa07d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 18 Sep 2013 10:58:16 +0200 +Subject: [PATCH 108/249] s3-rpc: use ndr_interface_name() instead of + get_pipe_name_from_syntax() in DEBUG. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 3135533710b2a1b64aaf6b10d30b86f3c004657d) +--- + source3/rpc_server/rpc_handles.c | 15 +++++++++------ + source3/rpc_server/srv_pipe.c | 22 ++++++++++++++-------- + source3/rpc_server/srv_pipe_hnd.c | 16 +++++++++++----- + source3/wscript_build | 3 ++- + 4 files changed, 36 insertions(+), 20 deletions(-) + +diff --git a/source3/rpc_server/rpc_handles.c b/source3/rpc_server/rpc_handles.c +index 70c3919..409299a 100644 +--- a/source3/rpc_server/rpc_handles.c ++++ b/source3/rpc_server/rpc_handles.c +@@ -27,6 +27,7 @@ + #include "rpc_server/rpc_pipes.h" + #include "../libcli/security/security.h" + #include "lib/tsocket/tsocket.h" ++#include "librpc/ndr/ndr_table.h" + + #undef DBGC_CLASS + #define DBGC_CLASS DBGC_RPC_SRV +@@ -218,7 +219,8 @@ bool init_pipe_handles(struct pipes_struct *p, const struct ndr_syntax_id *synta + + DEBUG(10,("init_pipe_handle_list: created handle list for " + "pipe %s\n", +- get_pipe_name_from_syntax(talloc_tos(), syntax))); ++ ndr_interface_name(&syntax->uuid, ++ syntax->if_version))); + } + + /* +@@ -235,7 +237,7 @@ bool init_pipe_handles(struct pipes_struct *p, const struct ndr_syntax_id *synta + + DEBUG(10,("init_pipe_handle_list: pipe_handles ref count = %lu for " + "pipe %s\n", (unsigned long)p->pipe_handles->pipe_ref_count, +- get_pipe_name_from_syntax(talloc_tos(), syntax))); ++ ndr_interface_name(&syntax->uuid, syntax->if_version))); + + return True; + } +@@ -412,8 +414,8 @@ void close_policy_by_pipe(struct pipes_struct *p) + TALLOC_FREE(p->pipe_handles); + + DEBUG(10,("Deleted handle list for RPC connection %s\n", +- get_pipe_name_from_syntax(talloc_tos(), +- &p->contexts->syntax))); ++ ndr_interface_name(&p->contexts->syntax.uuid, ++ p->contexts->syntax.if_version))); + } + } + +@@ -456,8 +458,9 @@ void *_policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd, + if (p->pipe_handles->count > MAX_OPEN_POLS) { + DEBUG(0, ("ERROR: Too many handles (%d) for RPC connection %s\n", + (int) p->pipe_handles->count, +- get_pipe_name_from_syntax(talloc_tos(), +- &p->contexts->syntax))); ++ ndr_interface_name(&p->contexts->syntax.uuid, ++ p->contexts->syntax.if_version))); ++ + *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; + return NULL; + } +diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c +index 06752a8..19dbc37 100644 +--- a/source3/rpc_server/srv_pipe.c ++++ b/source3/rpc_server/srv_pipe.c +@@ -41,6 +41,7 @@ + #include "rpc_server/srv_pipe.h" + #include "rpc_server/rpc_contexts.h" + #include "lib/param/param.h" ++#include "librpc/ndr/ndr_table.h" + + #undef DBGC_CLASS + #define DBGC_CLASS DBGC_RPC_SRV +@@ -336,7 +337,8 @@ static bool check_bind_req(struct pipes_struct *p, + bool ok; + + DEBUG(3,("check_bind_req for %s\n", +- get_pipe_name_from_syntax(talloc_tos(), abstract))); ++ ndr_interface_name(&abstract->uuid, ++ abstract->if_version))); + + /* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */ + if (rpc_srv_pipe_exists_by_id(abstract) && +@@ -580,7 +582,8 @@ static bool api_pipe_bind_req(struct pipes_struct *p, + if (NT_STATUS_IS_ERR(status)) { + DEBUG(3,("api_pipe_bind_req: Unknown rpc service name " + "%s in bind request.\n", +- get_pipe_name_from_syntax(talloc_tos(), &id))); ++ ndr_interface_name(&id.uuid, ++ id.if_version))); + + return setup_bind_nak(p, pkt); + } +@@ -595,8 +598,10 @@ static bool api_pipe_bind_req(struct pipes_struct *p, + } else { + DEBUG(0, ("module %s doesn't provide functions for " + "pipe %s!\n", +- get_pipe_name_from_syntax(talloc_tos(), &id), +- get_pipe_name_from_syntax(talloc_tos(), &id))); ++ ndr_interface_name(&id.uuid, ++ id.if_version), ++ ndr_interface_name(&id.uuid, ++ id.if_version))); + return setup_bind_nak(p, pkt); + } + } +@@ -1206,7 +1211,8 @@ static bool api_pipe_request(struct pipes_struct *p, + TALLOC_CTX *frame = talloc_stackframe(); + + DEBUG(5, ("Requested %s rpc service\n", +- get_pipe_name_from_syntax(talloc_tos(), &pipe_fns->syntax))); ++ ndr_interface_name(&pipe_fns->syntax.uuid, ++ pipe_fns->syntax.if_version))); + + ret = api_rpcTNP(p, pkt, pipe_fns->cmds, pipe_fns->n_cmds, + &pipe_fns->syntax); +@@ -1237,7 +1243,7 @@ static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt, + + /* interpret the command */ + DEBUG(4,("api_rpcTNP: %s op 0x%x - ", +- get_pipe_name_from_syntax(talloc_tos(), syntax), ++ ndr_interface_name(&syntax->uuid, syntax->if_version), + pkt->u.request.opnum)); + + if (DEBUGLEVEL >= 50) { +@@ -1276,7 +1282,7 @@ static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt, + /* do the actual command */ + if(!api_rpc_cmds[fn_num].fn(p)) { + DEBUG(0,("api_rpcTNP: %s: %s failed.\n", +- get_pipe_name_from_syntax(talloc_tos(), syntax), ++ ndr_interface_name(&syntax->uuid, syntax->if_version), + api_rpc_cmds[fn_num].name)); + data_blob_free(&p->out_data.rdata); + return False; +@@ -1299,7 +1305,7 @@ static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt, + } + + DEBUG(5,("api_rpcTNP: called %s successfully\n", +- get_pipe_name_from_syntax(talloc_tos(), syntax))); ++ ndr_interface_name(&syntax->uuid, syntax->if_version))); + + /* Check for buffer underflow in rpc parsing */ + if ((DEBUGLEVEL >= 10) && +diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c +index 3f8ff44..fcbfa77 100644 +--- a/source3/rpc_server/srv_pipe_hnd.c ++++ b/source3/rpc_server/srv_pipe_hnd.c +@@ -30,6 +30,7 @@ + #include "rpc_server/rpc_config.h" + #include "../lib/tsocket/tsocket.h" + #include "../lib/util/tevent_ntstatus.h" ++#include "librpc/ndr/ndr_table.h" + + #undef DBGC_CLASS + #define DBGC_CLASS DBGC_RPC_SRV +@@ -281,7 +282,8 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, + } + + DEBUG(6,(" name: %s len: %u\n", +- get_pipe_name_from_syntax(talloc_tos(), &p->contexts->syntax), ++ ndr_interface_name(&p->contexts->syntax.uuid, ++ p->contexts->syntax.if_version), + (unsigned int)n)); + + /* +@@ -299,7 +301,8 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, + DEBUG(5,("read_from_pipe: too large read (%u) requested on " + "pipe %s. We can only service %d sized reads.\n", + (unsigned int)n, +- get_pipe_name_from_syntax(talloc_tos(), &p->contexts->syntax), ++ ndr_interface_name(&p->contexts->syntax.uuid, ++ p->contexts->syntax.if_version), + RPC_MAX_PDU_FRAG_LEN )); + n = RPC_MAX_PDU_FRAG_LEN; + } +@@ -320,7 +323,8 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, + + DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, " + "current_pdu_sent = %u returning %d bytes.\n", +- get_pipe_name_from_syntax(talloc_tos(), &p->contexts->syntax), ++ ndr_interface_name(&p->contexts->syntax.uuid, ++ p->contexts->syntax.if_version), + (unsigned int)p->out_data.frag.length, + (unsigned int)p->out_data.current_pdu_sent, + (int)data_returned)); +@@ -341,7 +345,8 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, + + DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length " + "= %u, p->out_data.rdata.length = %u.\n", +- get_pipe_name_from_syntax(talloc_tos(), &p->contexts->syntax), ++ ndr_interface_name(&p->contexts->syntax.uuid, ++ p->contexts->syntax.if_version), + (int)p->fault_state, + (unsigned int)p->out_data.data_sent_length, + (unsigned int)p->out_data.rdata.length)); +@@ -363,7 +368,8 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, + + if(!create_next_pdu(p)) { + DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n", +- get_pipe_name_from_syntax(talloc_tos(), &p->contexts->syntax))); ++ ndr_interface_name(&p->contexts->syntax.uuid, ++ p->contexts->syntax.if_version))); + return -1; + } + +diff --git a/source3/wscript_build b/source3/wscript_build +index 0bf84e2..bb2e928 100755 +--- a/source3/wscript_build ++++ b/source3/wscript_build +@@ -672,7 +672,8 @@ bld.SAMBA3_LIBRARY('msrpc3', + deps='''ndr ndr-standard + RPC_NDR_EPMAPPER NTLMSSP_COMMON COMMON_SCHANNEL LIBCLI_AUTH + LIBTSOCKET gse dcerpc-binding +- libsmb''', ++ libsmb ++ ndr-table''', + vars=locals(), + private_library=True) + +-- +1.9.3 + + +From 6e6ba9bb34ac4e1d55056ef82e4bad8ab2d65b0d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Thu, 8 Aug 2013 17:33:29 +0200 +Subject: [PATCH 109/249] librpc: add dcerpc_default_transport_endpoint() + function. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 40ee3d8a5f7439b90f1ebf5e40535fad51038fe6) +--- + librpc/rpc/dcerpc_util.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ + librpc/rpc/rpc_common.h | 3 +++ + 2 files changed, 58 insertions(+) + +diff --git a/librpc/rpc/dcerpc_util.c b/librpc/rpc/dcerpc_util.c +index 0b9cca3..4046f32 100644 +--- a/librpc/rpc/dcerpc_util.c ++++ b/librpc/rpc/dcerpc_util.c +@@ -332,3 +332,58 @@ NTSTATUS dcerpc_read_ncacn_packet_recv(struct tevent_req *req, + tevent_req_received(req); + return NT_STATUS_OK; + } ++ ++const char *dcerpc_default_transport_endpoint(TALLOC_CTX *mem_ctx, ++ enum dcerpc_transport_t transport, ++ const struct ndr_interface_table *table) ++{ ++ NTSTATUS status; ++ const char *p = NULL; ++ const char *endpoint = NULL; ++ int i; ++ struct dcerpc_binding *default_binding = NULL; ++ TALLOC_CTX *frame = talloc_stackframe(); ++ ++ /* Find one of the default pipes for this interface */ ++ ++ for (i = 0; i < table->endpoints->count; i++) { ++ ++ status = dcerpc_parse_binding(frame, table->endpoints->names[i], ++ &default_binding); ++ if (NT_STATUS_IS_OK(status)) { ++ if (transport == NCA_UNKNOWN && ++ default_binding->endpoint != NULL) { ++ p = default_binding->endpoint; ++ break; ++ } ++ if (default_binding->transport == transport && ++ default_binding->endpoint != NULL) { ++ p = default_binding->endpoint; ++ break; ++ } ++ } ++ } ++ ++ if (i == table->endpoints->count || p == NULL) { ++ goto done; ++ } ++ ++ /* ++ * extract the pipe name without \\pipe from for example ++ * ncacn_np:[\\pipe\\epmapper] ++ */ ++ if (default_binding->transport == NCACN_NP) { ++ if (strncasecmp(p, "\\pipe\\", 6) == 0) { ++ p += 6; ++ } ++ if (strncmp(p, "\\", 1) == 0) { ++ p += 1; ++ } ++ } ++ ++ endpoint = talloc_strdup(mem_ctx, p); ++ ++ done: ++ talloc_free(frame); ++ return endpoint; ++} +diff --git a/librpc/rpc/rpc_common.h b/librpc/rpc/rpc_common.h +index e2b3755..d2816f5 100644 +--- a/librpc/rpc/rpc_common.h ++++ b/librpc/rpc/rpc_common.h +@@ -143,6 +143,9 @@ void dcerpc_set_frag_length(DATA_BLOB *blob, uint16_t v); + uint16_t dcerpc_get_frag_length(const DATA_BLOB *blob); + void dcerpc_set_auth_length(DATA_BLOB *blob, uint16_t v); + uint8_t dcerpc_get_endian_flag(DATA_BLOB *blob); ++const char *dcerpc_default_transport_endpoint(TALLOC_CTX *mem_ctx, ++ enum dcerpc_transport_t transport, ++ const struct ndr_interface_table *table); + + /** + * @brief Pull a dcerpc_auth structure, taking account of any auth +-- +1.9.3 + + +From a71f6912117ef5054cba4346f8bfd555d70d7837 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 18 Sep 2013 10:59:14 +0200 +Subject: [PATCH 110/249] s3-rpc: use dcerpc_default_transport_endpoint + function. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher +(cherry picked from commit b73e2d927b2221cb3fde8776789c8ca085cf2b8f) +--- + source3/rpc_client/rpc_transport_np.c | 4 +++- + source3/rpc_server/rpc_ncacn_np.c | 12 ++++++++++-- + source3/rpc_server/srv_pipe.c | 28 +++++++++++++++++++++------- + 3 files changed, 34 insertions(+), 10 deletions(-) + +diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c +index c0f313e..91943f4 100644 +--- a/source3/rpc_client/rpc_transport_np.c ++++ b/source3/rpc_client/rpc_transport_np.c +@@ -22,6 +22,7 @@ + #include "rpc_client/rpc_transport.h" + #include "libsmb/cli_np_tstream.h" + #include "client.h" ++#include "librpc/ndr/ndr_table.h" + + #undef DBGC_CLASS + #define DBGC_CLASS DBGC_RPC_CLI +@@ -55,7 +56,8 @@ struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, + state->ev = ev; + state->cli = cli; + state->abs_timeout = timeval_current_ofs_msec(cli->timeout); +- state->pipe_name = get_pipe_name_from_syntax(state, &table->syntax_id); ++ state->pipe_name = dcerpc_default_transport_endpoint(state, NCACN_NP, ++ table); + if (tevent_req_nomem(state->pipe_name, req)) { + return tevent_req_post(req, ev); + } +diff --git a/source3/rpc_server/rpc_ncacn_np.c b/source3/rpc_server/rpc_ncacn_np.c +index 7389b3e..46b77fd 100644 +--- a/source3/rpc_server/rpc_ncacn_np.c ++++ b/source3/rpc_server/rpc_ncacn_np.c +@@ -36,6 +36,7 @@ + #include "../lib/util/tevent_ntstatus.h" + #include "rpc_contexts.h" + #include "rpc_server/rpc_config.h" ++#include "librpc/ndr/ndr_table.h" + + #undef DBGC_CLASS + #define DBGC_CLASS DBGC_RPC_SRV +@@ -54,8 +55,15 @@ struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, + struct pipe_rpc_fns *context_fns; + const char *pipe_name; + int ret; ++ const struct ndr_interface_table *table; + +- pipe_name = get_pipe_name_from_syntax(talloc_tos(), syntax); ++ table = ndr_table_by_uuid(&syntax->uuid); ++ if (table == NULL) { ++ DEBUG(0,("unknown interface\n")); ++ return NULL; ++ } ++ ++ pipe_name = dcerpc_default_transport_endpoint(mem_ctx, NCACN_NP, table); + + DEBUG(4,("Create pipe requested %s\n", pipe_name)); + +@@ -783,7 +791,7 @@ NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx, + return NT_STATUS_NO_MEMORY; + } + +- pipe_name = get_pipe_name_from_syntax(tmp_ctx, &table->syntax_id); ++ pipe_name = dcerpc_default_transport_endpoint(mem_ctx, NCACN_NP, table); + if (pipe_name == NULL) { + status = NT_STATUS_INVALID_PARAMETER; + goto done; +diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c +index 19dbc37..5f834fb 100644 +--- a/source3/rpc_server/srv_pipe.c ++++ b/source3/rpc_server/srv_pipe.c +@@ -552,6 +552,7 @@ static bool api_pipe_bind_req(struct pipes_struct *p, + struct dcerpc_ack_ctx bind_ack_ctx; + DATA_BLOB auth_resp = data_blob_null; + DATA_BLOB auth_blob = data_blob_null; ++ const struct ndr_interface_table *table; + + /* No rebinds on a bound pipe - use alter context. */ + if (p->pipe_bound) { +@@ -569,15 +570,21 @@ static bool api_pipe_bind_req(struct pipes_struct *p, + * that this is a pipe name we support. + */ + id = pkt->u.bind.ctx_list[0].abstract_syntax; ++ ++ table = ndr_table_by_uuid(&id.uuid); ++ if (table == NULL) { ++ DEBUG(0,("unknown interface\n")); ++ return false; ++ } ++ + if (rpc_srv_pipe_exists_by_id(&id)) { + DEBUG(3, ("api_pipe_bind_req: %s -> %s rpc service\n", + rpc_srv_get_pipe_cli_name(&id), + rpc_srv_get_pipe_srv_name(&id))); + } else { + status = smb_probe_module( +- "rpc", get_pipe_name_from_syntax( +- talloc_tos(), +- &id)); ++ "rpc", dcerpc_default_transport_endpoint(pkt, ++ NCACN_NP, table)); + + if (NT_STATUS_IS_ERR(status)) { + DEBUG(3,("api_pipe_bind_req: Unknown rpc service name " +@@ -589,8 +596,8 @@ static bool api_pipe_bind_req(struct pipes_struct *p, + } + + if (rpc_srv_get_pipe_interface_by_cli_name( +- get_pipe_name_from_syntax(talloc_tos(), +- &id), ++ dcerpc_default_transport_endpoint(pkt, ++ NCACN_NP, table), + &id)) { + DEBUG(3, ("api_pipe_bind_req: %s -> %s rpc service\n", + rpc_srv_get_pipe_cli_name(&id), +@@ -1240,16 +1247,23 @@ static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt, + { + int fn_num; + uint32_t offset1; ++ const struct ndr_interface_table *table; + + /* interpret the command */ + DEBUG(4,("api_rpcTNP: %s op 0x%x - ", + ndr_interface_name(&syntax->uuid, syntax->if_version), + pkt->u.request.opnum)); + ++ table = ndr_table_by_uuid(&syntax->uuid); ++ if (table == NULL) { ++ DEBUG(0,("unknown interface\n")); ++ return false; ++ } ++ + if (DEBUGLEVEL >= 50) { + fstring name; + slprintf(name, sizeof(name)-1, "in_%s", +- get_pipe_name_from_syntax(talloc_tos(), syntax)); ++ dcerpc_default_transport_endpoint(pkt, NCACN_NP, table)); + dump_pdu_region(name, pkt->u.request.opnum, + &p->in_data.data, 0, + p->in_data.data.length); +@@ -1298,7 +1312,7 @@ static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt, + if (DEBUGLEVEL >= 50) { + fstring name; + slprintf(name, sizeof(name)-1, "out_%s", +- get_pipe_name_from_syntax(talloc_tos(), syntax)); ++ dcerpc_default_transport_endpoint(pkt, NCACN_NP, table)); + dump_pdu_region(name, pkt->u.request.opnum, + &p->out_data.rdata, offset1, + p->out_data.rdata.length); +-- +1.9.3 + + +From 8bb6f177b210159ea6317b20e2cc12732b4d273a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 7 Aug 2013 17:43:08 +0200 +Subject: [PATCH 111/249] s3-rpc: remove unused source3/librpc/rpc/rpc_common.c +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Stefan Metzmacher + +Autobuild-User(master): Günther Deschner +Autobuild-Date(master): Fri Sep 20 14:57:06 CEST 2013 on sn-devel-104 +(cherry picked from commit 807628ecac445999e75ec9ea1abdc5f2fde356d6) +--- + source3/librpc/rpc/dcerpc.h | 8 -- + source3/librpc/rpc/rpc_common.c | 209 ---------------------------------------- + source3/wscript_build | 1 - + 3 files changed, 218 deletions(-) + delete mode 100644 source3/librpc/rpc/rpc_common.c + +diff --git a/source3/librpc/rpc/dcerpc.h b/source3/librpc/rpc/dcerpc.h +index 38d59cd..b18b7ba 100644 +--- a/source3/librpc/rpc/dcerpc.h ++++ b/source3/librpc/rpc/dcerpc.h +@@ -85,12 +85,4 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, + DATA_BLOB *raw_pkt, + size_t *pad_len); + +-/* The following definitions come from librpc/rpc/rpc_common.c */ +- +-bool smb_register_ndr_interface(const struct ndr_interface_table *interface); +-const struct ndr_interface_table *get_iface_from_syntax( +- const struct ndr_syntax_id *syntax); +-const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx, +- const struct ndr_syntax_id *syntax); +- + #endif /* __S3_DCERPC_H__ */ +diff --git a/source3/librpc/rpc/rpc_common.c b/source3/librpc/rpc/rpc_common.c +deleted file mode 100644 +index 1219b2d..0000000 +--- a/source3/librpc/rpc/rpc_common.c ++++ /dev/null +@@ -1,209 +0,0 @@ +-/* +- * Unix SMB/CIFS implementation. +- * RPC Pipe client / server routines +- * Largely rewritten by Jeremy Allison 2005. +- * +- * 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 . +- */ +- +-#include "includes.h" +-#include "librpc/rpc/dcerpc.h" +-#include "../librpc/gen_ndr/ndr_lsa.h" +-#include "../librpc/gen_ndr/ndr_dssetup.h" +-#include "../librpc/gen_ndr/ndr_samr.h" +-#include "../librpc/gen_ndr/ndr_netlogon.h" +-#include "../librpc/gen_ndr/ndr_srvsvc.h" +-#include "../librpc/gen_ndr/ndr_wkssvc.h" +-#include "../librpc/gen_ndr/ndr_winreg.h" +-#include "../librpc/gen_ndr/ndr_spoolss.h" +-#include "../librpc/gen_ndr/ndr_dfs.h" +-#include "../librpc/gen_ndr/ndr_echo.h" +-#include "../librpc/gen_ndr/ndr_initshutdown.h" +-#include "../librpc/gen_ndr/ndr_svcctl.h" +-#include "../librpc/gen_ndr/ndr_eventlog.h" +-#include "../librpc/gen_ndr/ndr_ntsvcs.h" +-#include "../librpc/gen_ndr/ndr_epmapper.h" +-#include "../librpc/gen_ndr/ndr_drsuapi.h" +-#include "../librpc/gen_ndr/ndr_fsrvp.h" +- +-static const char *get_pipe_name_from_iface( +- TALLOC_CTX *mem_ctx, const struct ndr_interface_table *interface) +-{ +- int i; +- const struct ndr_interface_string_array *ep = interface->endpoints; +- char *p; +- +- for (i=0; icount; i++) { +- if (strncmp(ep->names[i], "ncacn_np:[\\pipe\\", 16) == 0) { +- break; +- } +- } +- if (i == ep->count) { +- return NULL; +- } +- +- /* +- * extract the pipe name without \\pipe from for example +- * ncacn_np:[\\pipe\\epmapper] +- */ +- p = strchr(ep->names[i]+15, ']'); +- if (p == NULL) { +- return "PIPE"; +- } +- return talloc_strndup(mem_ctx, ep->names[i]+15, p - ep->names[i] - 15); +-} +- +-static const struct ndr_interface_table **interfaces; +- +-bool smb_register_ndr_interface(const struct ndr_interface_table *interface) +-{ +- int num_interfaces = talloc_array_length(interfaces); +- const struct ndr_interface_table **tmp; +- int i; +- +- for (i=0; isyntax_id, +- &interface->syntax_id)) { +- return true; +- } +- } +- +- tmp = talloc_realloc(NULL, interfaces, +- const struct ndr_interface_table *, +- num_interfaces + 1); +- if (tmp == NULL) { +- DEBUG(1, ("smb_register_ndr_interface: talloc failed\n")); +- return false; +- } +- interfaces = tmp; +- interfaces[num_interfaces] = interface; +- return true; +-} +- +-static bool initialize_interfaces(void) +-{ +- if (!smb_register_ndr_interface(&ndr_table_lsarpc)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_dssetup)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_samr)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_netlogon)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_srvsvc)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_wkssvc)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_winreg)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_spoolss)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_netdfs)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_rpcecho)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_initshutdown)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_svcctl)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_eventlog)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_ntsvcs)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_epmapper)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_drsuapi)) { +- return false; +- } +- if (!smb_register_ndr_interface(&ndr_table_FileServerVssAgent)) { +- return false; +- } +- return true; +-} +- +-const struct ndr_interface_table *get_iface_from_syntax( +- const struct ndr_syntax_id *syntax) +-{ +- int num_interfaces; +- int i; +- +- if (interfaces == NULL) { +- if (!initialize_interfaces()) { +- return NULL; +- } +- } +- num_interfaces = talloc_array_length(interfaces); +- +- for (i=0; isyntax_id, syntax)) { +- return interfaces[i]; +- } +- } +- +- return NULL; +-} +- +-/**************************************************************************** +- Return the pipe name from the interface. +- ****************************************************************************/ +- +-const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx, +- const struct ndr_syntax_id *syntax) +-{ +- const struct ndr_interface_table *interface; +- char *guid_str; +- const char *result; +- +- interface = get_iface_from_syntax(syntax); +- if (interface != NULL) { +- result = get_pipe_name_from_iface(mem_ctx, interface); +- if (result != NULL) { +- return result; +- } +- } +- +- /* +- * Here we should ask \\epmapper, but for now our code is only +- * interested in the known pipes mentioned in pipe_names[] +- */ +- +- guid_str = GUID_string(talloc_tos(), &syntax->uuid); +- if (guid_str == NULL) { +- return NULL; +- } +- result = talloc_asprintf(mem_ctx, "Interface %s.%d", guid_str, +- (int)syntax->if_version); +- TALLOC_FREE(guid_str); +- +- if (result == NULL) { +- return "PIPE"; +- } +- return result; +-} +- +diff --git a/source3/wscript_build b/source3/wscript_build +index bb2e928..8126cf6 100755 +--- a/source3/wscript_build ++++ b/source3/wscript_build +@@ -141,7 +141,6 @@ LIBSMB_SRC = '''libsmb/clientgen.c libsmb/cliconnect.c libsmb/clifile.c + + LIBMSRPC_SRC = ''' + rpc_client/cli_pipe.c +- librpc/rpc/rpc_common.c + rpc_client/rpc_transport_np.c + rpc_client/rpc_transport_sock.c + rpc_client/rpc_transport_tstream.c +-- +1.9.3 + + +From 2b2d978bd97299371a1fd7798d69ab377a76d389 Mon Sep 17 00:00:00 2001 +From: Volker Lendecke +Date: Wed, 14 Aug 2013 09:27:59 +0000 +Subject: [PATCH 112/249] winbind3: Fix an invalid free +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This fixes a warning I've never seen before :-) + +../source3/winbindd/winbindd_cm.c:781:59: warning: attempt to free a non-heap object ‘machine_krb5_principal’ [-Wfree-nonheap-object] + +Signed-off-by: Volker Lendecke +Reviewed-by: Stefan Metzmacher + +Autobuild-User(master): Stefan Metzmacher +Autobuild-Date(master): Wed Aug 14 14:04:16 CEST 2013 on sn-devel-104 +(cherry picked from commit 5f75814586f2d6f7c2dc8fd9342cb045c1f7e68c) +--- + source3/winbindd/winbindd_cm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c +index facef64..d868826 100644 +--- a/source3/winbindd/winbindd_cm.c ++++ b/source3/winbindd/winbindd_cm.c +@@ -840,7 +840,7 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, + } + + if (!strupper_m(*machine_krb5_principal)) { +- SAFE_FREE(machine_krb5_principal); ++ SAFE_FREE(*machine_krb5_principal); + return NT_STATUS_INVALID_PARAMETER; + } + } +-- +1.9.3 + + +From 1b88903c4f5931397e22874b3751dd05a03a2dea Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Fri, 11 Oct 2013 13:34:13 +1300 +Subject: [PATCH 113/249] s3-winbindd: Remove undocumented winbindd:socket dir + parameter + +This uses the documeted "winbindd socket directory" parameter instead. + +This came about due to the merge of the two smb.conf tables in s3 and +s4 for the Samba 4.0 release. The s4 code used a real parameter, +which caused this to be documented, whereas no automatic procedure +existed to notice the parametric option and the need to document that. +The fact that this was not used consistently in both codebases is one +of the many areas of technical debt we still need to pay off here. + +Andrew Bartlett + +Signed-off-by: Andrew Bartlett +Reviewed-by: Andreas Schneider +(cherry picked from commit e512491552d9ed0dc1005a23ffc8f77ba237f863) +--- + selftest/target/Samba3.pm | 2 +- + source3/include/proto.h | 1 + + source3/param/loadparm.c | 1 + + source3/winbindd/winbindd.c | 9 ++------- + source3/winbindd/winbindd_proto.h | 1 - + 5 files changed, 5 insertions(+), 9 deletions(-) + +diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm +index ba01154..d8f0c27 100755 +--- a/selftest/target/Samba3.pm ++++ b/selftest/target/Samba3.pm +@@ -972,7 +972,7 @@ sub provision($$$$$$) + printing = bsd + printcap name = /dev/null + +- winbindd:socket dir = $wbsockdir ++ winbindd socket directory = $wbsockdir + nmbd:socket dir = $nmbdsockdir + idmap config * : range = 100000-200000 + winbind enum users = yes +diff --git a/source3/include/proto.h b/source3/include/proto.h +index cbad7ac..53cd59d 100644 +--- a/source3/include/proto.h ++++ b/source3/include/proto.h +@@ -1069,6 +1069,7 @@ char *lp_wins_hook(TALLOC_CTX *ctx); + const char *lp_template_homedir(void); + const char *lp_template_shell(void); + const char *lp_winbind_separator(void); ++const char *lp_winbindd_socket_directory(void); + bool lp_winbind_enum_users(void); + bool lp_winbind_enum_groups(void); + bool lp_winbind_use_default_domain(void); +diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c +index 4b31023..b2804ae 100644 +--- a/source3/param/loadparm.c ++++ b/source3/param/loadparm.c +@@ -961,6 +961,7 @@ static void init_globals(bool reinit_globals) + string_set(&Globals.szTemplateShell, "/bin/false"); + string_set(&Globals.szTemplateHomedir, "/home/%D/%U"); + string_set(&Globals.szWinbindSeparator, "\\"); ++ string_set(&Globals.szWinbinddSocketDirectory, dyn_WINBINDD_SOCKET_DIR); + + string_set(&Globals.szCupsServer, ""); + string_set(&Globals.szIPrintServer, ""); +diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c +index f101e52..69a17bf 100644 +--- a/source3/winbindd/winbindd.c ++++ b/source3/winbindd/winbindd.c +@@ -189,7 +189,7 @@ static void terminate(bool is_parent) + char *path = NULL; + + if (asprintf(&path, "%s/%s", +- get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME) > 0) { ++ lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) { + unlink(path); + SAFE_FREE(path); + } +@@ -1067,11 +1067,6 @@ static void winbindd_listen_fde_handler(struct tevent_context *ev, + * Winbindd socket accessor functions + */ + +-const char *get_winbind_pipe_dir(void) +-{ +- return lp_parm_const_string(-1, "winbindd", "socket dir", get_dyn_WINBINDD_SOCKET_DIR()); +-} +- + char *get_winbind_priv_pipe_dir(void) + { + return state_path(WINBINDD_PRIV_SOCKET_SUBDIR); +@@ -1092,7 +1087,7 @@ static bool winbindd_setup_listeners(void) + + pub_state->privileged = false; + pub_state->fd = create_pipe_sock( +- get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME, 0755); ++ lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755); + if (pub_state->fd == -1) { + goto failed; + } +diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h +index 3df7d7c..cfc19d0 100644 +--- a/source3/winbindd/winbindd_proto.h ++++ b/source3/winbindd/winbindd_proto.h +@@ -34,7 +34,6 @@ bool winbindd_setup_stdin_handler(bool parent, bool foreground); + bool winbindd_setup_sig_hup_handler(const char *lfile); + bool winbindd_use_idmap_cache(void); + bool winbindd_use_cache(void); +-const char *get_winbind_pipe_dir(void); + char *get_winbind_priv_pipe_dir(void); + struct tevent_context *winbind_event_context(void); + int main(int argc, char **argv, char **envp); +-- +1.9.3 + + +From d0ae2d10385dea4b8fae3d8932d40f546ff8905b Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Mon, 14 Oct 2013 15:33:20 +1300 +Subject: [PATCH 114/249] lib/param: lp_magicchar takes a const struct + share_params *p so should be FN_LOCAL_PARM_CHAR + +This was found when trying to autogenerate prototypes for lp_ functions again. + +Andrew Bartlett + +Signed-off-by: Andrew Bartlett +Reviewed-by: Stefan Metzmacher +--- + lib/param/loadparm.c | 2 +- + lib/param/param_functions.c | 2 +- + source3/param/loadparm.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c +index 455c5e6..4497dbf 100644 +--- a/lib/param/loadparm.c ++++ b/lib/param/loadparm.c +@@ -314,7 +314,7 @@ static struct loadparm_context *global_loadparm_context; + + #define FN_LOCAL_PARM_INTEGER(fn_name, val) FN_LOCAL_INTEGER(fn_name, val) + +-#define FN_LOCAL_CHAR(fn_name,val) \ ++#define FN_LOCAL_PARM_CHAR(fn_name,val) \ + _PUBLIC_ char lpcfg_ ## fn_name(struct loadparm_service *service, \ + struct loadparm_service *sDefault) { \ + return((service != NULL)? service->val : sDefault->val); \ +diff --git a/lib/param/param_functions.c b/lib/param/param_functions.c +index d9d5df6..60f9c07 100644 +--- a/lib/param/param_functions.c ++++ b/lib/param/param_functions.c +@@ -147,7 +147,7 @@ FN_LOCAL_INTEGER(aio_write_size, iAioWriteSize) + FN_LOCAL_INTEGER(map_readonly, iMap_readonly) + FN_LOCAL_INTEGER(directory_name_cache_size, iDirectoryNameCacheSize) + FN_LOCAL_INTEGER(smb_encrypt, ismb_encrypt) +-FN_LOCAL_CHAR(magicchar, magic_char) ++FN_LOCAL_PARM_CHAR(magicchar, magic_char) + FN_LOCAL_STRING(cups_options, szCupsOptions) + FN_LOCAL_PARM_BOOL(change_notify, bChangeNotify) + FN_LOCAL_PARM_BOOL(kernel_change_notify, bKernelChangeNotify) +diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c +index b2804ae..40f3242 100644 +--- a/source3/param/loadparm.c ++++ b/source3/param/loadparm.c +@@ -1116,7 +1116,7 @@ char *lp_ ## fn_name(TALLOC_CTX *ctx,int i) {return(lp_string((ctx), (LP_SNUM_OK + bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);} + #define FN_LOCAL_PARM_INTEGER(fn_name,val) \ + int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);} +-#define FN_LOCAL_CHAR(fn_name,val) \ ++#define FN_LOCAL_PARM_CHAR(fn_name,val) \ + char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);} + + +-- +1.9.3 + + +From bf5cb3b6c6e2d3171b70fff5deb9a7767d6609a8 Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Mon, 14 Oct 2013 13:47:27 +1300 +Subject: [PATCH 115/249] build: Move loadparm-related build rules to + source3/param/wscript_build + +Signed-off-by: Andrew Bartlett +Reviewed-by: Stefan Metzmacher +--- + source3/param/wscript_build | 32 ++++++++++++++++++++++++++++++++ + source3/wscript_build | 36 ++---------------------------------- + 2 files changed, 34 insertions(+), 34 deletions(-) + create mode 100644 source3/param/wscript_build + +diff --git a/source3/param/wscript_build b/source3/param/wscript_build +new file mode 100644 +index 0000000..278d5f5 +--- /dev/null ++++ b/source3/param/wscript_build +@@ -0,0 +1,32 @@ ++#!/usr/bin/env python ++ ++bld.SAMBA3_SUBSYSTEM('PARAM_UTIL', ++ source='util.c', ++ deps='talloc') ++ ++bld.SAMBA3_SUBSYSTEM('LOADPARM_CTX', ++ source='loadparm_ctx.c', ++ deps='''talloc s3_param_h param''') ++ ++bld.SAMBA_GENERATOR('s3_param_global_h', ++ source= '../../script/mkparamdefs.pl loadparm.c ../../lib/param/param_functions.c', ++ target='param_global.h', ++ rule='${PERL} ${SRC[0].abspath(env)} ${SRC[1].abspath(env)} ${SRC[2].abspath(env)} --file ${TGT} --generate-scope=GLOBAL') ++ ++bld.SAMBA3_PYTHON('pys3param', ++ source='pyparam.c', ++ deps='param', ++ public_deps='samba-hostconfig pytalloc-util talloc', ++ realname='samba/samba3/param.so') ++ ++bld.SAMBA3_SUBSYSTEM('param_service', ++ source='service.c', ++ deps = 'USER_UTIL param PRINTING') ++ ++bld.SAMBA3_BINARY('test_lp_load', ++ source='test_lp_load.c', ++ deps=''' ++ talloc ++ param ++ popt_samba3''', ++ install=False) +diff --git a/source3/wscript_build b/source3/wscript_build +index 8126cf6..13d15c3 100755 +--- a/source3/wscript_build ++++ b/source3/wscript_build +@@ -751,33 +751,9 @@ bld.SAMBA3_SUBSYSTEM('SERVER_MUTEX', + source=SERVER_MUTEX_SRC, + deps='talloc') + +-bld.SAMBA3_SUBSYSTEM('PARAM_UTIL', +- source=PARAM_UTIL_SRC, +- deps='talloc') +- +-bld.SAMBA3_SUBSYSTEM('LOADPARM_CTX', +- source='param/loadparm_ctx.c', +- deps='''talloc s3_param_h param''', +- vars=locals()) +- +-bld.SAMBA_GENERATOR('param/param_global_h', +- source= '../script/mkparamdefs.pl param/loadparm.c ../lib/param/param_functions.c', +- target='param/param_global.h', +- rule='${PERL} ${SRC[0].abspath(env)} ${SRC[1].abspath(env)} ${SRC[2].abspath(env)} --file ${TGT} --generate-scope=GLOBAL') +- + bld.SAMBA3_SUBSYSTEM('param', + source=PARAM_WITHOUT_REG_SRC, +- deps='samba-util PARAM_UTIL ldap lber LOADPARM_CTX samba3core smbconf param_local_h param/param_global_h cups''') +- +-bld.SAMBA3_PYTHON('pys3param', +- source='param/pyparam.c', +- deps='param', +- public_deps='samba-hostconfig pytalloc-util talloc', +- realname='samba/samba3/param.so') +- +-bld.SAMBA3_SUBSYSTEM('param_service', +- source='param/service.c', +- deps = 'USER_UTIL param PRINTING') ++ deps='samba-util PARAM_UTIL ldap lber LOADPARM_CTX samba3core smbconf param_local_h s3_param_global_h cups''') + + bld.SAMBA3_SUBSYSTEM('REGFIO', + source=REGFIO_SRC, +@@ -1566,15 +1542,6 @@ bld.SAMBA3_BINARY('rpc_open_tcp', + install=False, + vars=locals()) + +-bld.SAMBA3_BINARY('test_lp_load', +- source=TEST_LP_LOAD_SRC, +- deps=''' +- talloc +- param +- popt_samba3''', +- install=False, +- vars=locals()) +- + bld.SAMBA3_BINARY('dbwrap_tool', + source=DBWRAP_TOOL_SRC, + deps=''' +@@ -1638,6 +1605,7 @@ bld.RECURSE('librpc/idl') + bld.RECURSE('libsmb') + bld.RECURSE('modules') + bld.RECURSE('pam_smbpass') ++bld.RECURSE('param') + bld.RECURSE('passdb') + bld.RECURSE('rpc_server') + bld.RECURSE('script') +-- +1.9.3 + + +From 281cb415404f7044a4bdbc93a21b2f755cbc74ee Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Mon, 14 Oct 2013 15:34:40 +1300 +Subject: [PATCH 116/249] lib/param: Do not attempt to access the s3 function + for allocated and subbed string parameters + +This allows us not to generate array entries for these, which in turn allows +us to avoid initialising them. The issue is that we do not have the +% macro sub context nor a talloc context handy (yet). + +Andrew Bartlett + +Signed-off-by: Andrew Bartlett +Reviewed-by: Stefan Metzmacher +--- + lib/param/loadparm.c | 21 ++++++++++----------- + 1 file changed, 10 insertions(+), 11 deletions(-) + +diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c +index 4497dbf..23b45e2 100644 +--- a/lib/param/loadparm.c ++++ b/lib/param/loadparm.c +@@ -232,7 +232,16 @@ static struct loadparm_context *global_loadparm_context; + #define lpcfg_default_service global_loadparm_context->sDefault + #define lpcfg_global_service(i) global_loadparm_context->services[i] + +-#define FN_GLOBAL_STRING(fn_name,var_name) \ ++#define FN_GLOBAL_STRING(fn_name,var_name) \ ++ _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {\ ++ if (lp_ctx == NULL) return NULL; \ ++ if (lp_ctx->s3_fns) { \ ++ smb_panic( __location__ ": " #fn_name " not implemented because it is an allocated and substiuted string"); \ ++ } \ ++ return lp_ctx->globals->var_name ? lp_string(lp_ctx->globals->var_name) : ""; \ ++} ++ ++#define FN_GLOBAL_CONST_STRING(fn_name,var_name) \ + _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \ + if (lp_ctx == NULL) return NULL; \ + if (lp_ctx->s3_fns) { \ +@@ -242,16 +251,6 @@ static struct loadparm_context *global_loadparm_context; + return lp_ctx->globals->var_name ? lp_string(lp_ctx->globals->var_name) : ""; \ + } + +-#define FN_GLOBAL_CONST_STRING(fn_name,var_name) \ +- _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {\ +- if (lp_ctx == NULL) return NULL; \ +- if (lp_ctx->s3_fns) { \ +- SMB_ASSERT(lp_ctx->s3_fns->fn_name); \ +- return lp_ctx->s3_fns->fn_name(); \ +- } \ +- return lp_ctx->globals->var_name ? lp_string(lp_ctx->globals->var_name) : ""; \ +- } +- + #define FN_GLOBAL_LIST(fn_name,var_name) \ + _PUBLIC_ const char **lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \ + if (lp_ctx == NULL) return NULL; \ +-- +1.9.3 + + +From e610d185d26910e6cb96ddf8507c31c5f1503271 Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Mon, 14 Oct 2013 15:36:18 +1300 +Subject: [PATCH 117/249] param: Skip generating hooks for local and string + parameters + +Signed-off-by: Andrew Bartlett +Reviewed-by: Stefan Metzmacher +--- + script/mks3param.pl | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/script/mks3param.pl b/script/mks3param.pl +index 4222ca5..799958c 100644 +--- a/script/mks3param.pl ++++ b/script/mks3param.pl +@@ -108,7 +108,14 @@ sub handle_loadparm($$) + { + my ($file,$line) = @_; + +- if ($line =~ /^FN_(GLOBAL|LOCAL)_(CONST_STRING|STRING|BOOL|bool|CHAR|INTEGER|LIST)\((\w+),.*\)/o) { ++ # Local parameters don't need the ->s3_fns because the struct ++ # loadparm_service is shared and lpcfg_service() checks the ->s3_fns ++ # hook ++ # ++ # STRING isn't handled as we do not yet have a way to pass in a memory context nor ++ # do we have a good way of dealing with the % macros yet. ++ ++ if ($line =~ /^FN_(GLOBAL)_(CONST_STRING|BOOL|bool|CHAR|INTEGER|LIST)\((\w+),.*\)/o) { + my $scope = $1; + my $type = $2; + my $name = $3; +-- +1.9.3 + + +From 970290dc75404ab366617210edfca718fe21864b Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Mon, 14 Oct 2013 15:39:10 +1300 +Subject: [PATCH 118/249] s3/param: Autogenerate parameters prototypes again + after proto.h was frozen + +This autogenerates the parameters so that we can keep everything in sync easier, +particularly when adding new parameters. This will also make it easier to move +to a fully autogenerated system in the future, as it reduces special cases. + +Andrew Bartlett + +Signed-off-by: Andrew Bartlett +Reviewed-by: Stefan Metzmacher +--- + script/mks3param_proto.pl | 199 ++++++++++++++++++++++++++++++++++++++++++++ + source3/include/proto.h | 2 + + source3/param/wscript_build | 5 ++ + 3 files changed, 206 insertions(+) + create mode 100644 script/mks3param_proto.pl + +diff --git a/script/mks3param_proto.pl b/script/mks3param_proto.pl +new file mode 100644 +index 0000000..446e343 +--- /dev/null ++++ b/script/mks3param_proto.pl +@@ -0,0 +1,199 @@ ++#!/usr/bin/perl ++# Generate loadparm interfaces tables for Samba3/Samba4 integration ++# by Andrew Bartlett ++# based on mkproto.pl Written by Jelmer Vernooij ++# based on the original mkproto.sh by Andrew Tridgell ++ ++use strict; ++ ++# don't use warnings module as it is not portable enough ++# use warnings; ++ ++use Getopt::Long; ++use File::Basename; ++use File::Path; ++ ++##################################################################### ++# read a file into a string ++ ++my $file = undef; ++my $public_define = undef; ++my $_public = ""; ++my $_private = ""; ++my $public_data = \$_public; ++my $builddir = "."; ++my $srcdir = "."; ++ ++sub public($) ++{ ++ my ($d) = @_; ++ $$public_data .= $d; ++} ++ ++sub usage() ++{ ++ print "Usage: mks3param.pl [options] [c files]\n"; ++ print "OPTIONS:\n"; ++ print " --srcdir=path Read files relative to this directory\n"; ++ print " --builddir=path Write file relative to this directory\n"; ++ print " --help Print this help message\n\n"; ++ exit 0; ++} ++ ++GetOptions( ++ 'file=s' => sub { my ($f,$v) = @_; $file = $v; }, ++ 'srcdir=s' => sub { my ($f,$v) = @_; $srcdir = $v; }, ++ 'builddir=s' => sub { my ($f,$v) = @_; $builddir = $v; }, ++ 'help' => \&usage ++) or exit(1); ++ ++sub normalize_define($$) ++{ ++ my ($define, $file) = @_; ++ ++ if (not defined($define) and defined($file)) { ++ $define = "__" . uc($file) . "__"; ++ $define =~ tr{./}{__}; ++ $define =~ tr{\-}{_}; ++ } elsif (not defined($define)) { ++ $define = '_S3_PARAM_PROTO_H_'; ++ } ++ ++ return $define; ++} ++ ++$public_define = normalize_define($public_define, $file); ++ ++sub file_load($) ++{ ++ my($filename) = @_; ++ local(*INPUTFILE); ++ open(INPUTFILE, $filename) or return undef; ++ my($saved_delim) = $/; ++ undef $/; ++ my($data) = ; ++ close(INPUTFILE); ++ $/ = $saved_delim; ++ return $data; ++} ++ ++sub print_header($$) ++{ ++ my ($file, $header_name) = @_; ++ $file->("#ifndef $header_name\n"); ++ $file->("#define $header_name\n\n"); ++ $file->("/* This file was automatically generated by mks3param_proto.pl. DO NOT EDIT */\n\n"); ++} ++ ++sub print_footer($$) ++{ ++ my ($file, $header_name) = @_; ++ $file->("\n#endif /* $header_name */\n\n"); ++} ++ ++sub handle_loadparm($$) ++{ ++ my ($file,$line) = @_; ++ ++ my $scope; ++ my $type; ++ my $name; ++ my $var; ++ my $param; ++ ++ if ($line =~ /^FN_(GLOBAL|LOCAL)_(CONST_STRING|STRING|BOOL|bool|CHAR|INTEGER|LIST)\((\w+),(.*)\)/o) { ++ $scope = $1; ++ $type = $2; ++ $name = $3; ++ $var = $4; ++ $param = "int"; ++ } elsif ($line =~ /^FN_(GLOBAL|LOCAL)_PARM_(CONST_STRING|STRING|BOOL|bool|CHAR|INTEGER|LIST)\((\w+),(.*)\)/o) { ++ $scope = $1; ++ $type = $2; ++ $name = $3; ++ $var = $4; ++ $param = "const struct share_params *p"; ++ } else { ++ return; ++ } ++ ++ my %tmap = ( ++ "BOOL" => "bool ", ++ "CONST_STRING" => "const char *", ++ "STRING" => "char *", ++ "INTEGER" => "int ", ++ "CHAR" => "char ", ++ "LIST" => "const char **", ++ ); ++ ++ my %smap = ( ++ "GLOBAL" => "void", ++ "LOCAL" => "$param" ++ ); ++ ++ if (($type eq "STRING") and ($scope eq "GLOBAL")) { ++ $file->("$tmap{$type}lp_$name(TALLOC_CTX *ctx);\n"); ++ } elsif (($type eq "STRING") and ($scope eq "LOCAL")) { ++ $file->("$tmap{$type}lp_$name(TALLOC_CTX *ctx, $smap{$scope});\n"); ++ } else { ++ $file->("$tmap{$type}lp_$name($smap{$scope});\n"); ++ } ++} ++ ++sub process_file($$) ++{ ++ my ($file, $filename) = @_; ++ ++ $filename =~ s/\.o$/\.c/g; ++ ++ if ($filename =~ /^\//) { ++ open(FH, "<$filename") or die("Failed to open $filename"); ++ } elsif (!open(FH, "< $builddir/$filename")) { ++ open(FH, "< $srcdir/$filename") || die "Failed to open $filename"; ++ } ++ ++ my $comment = undef; ++ my $incomment = 0; ++ while (my $line = ) { ++ if ($line =~ /^\/\*\*/) { ++ $comment = ""; ++ $incomment = 1; ++ } ++ ++ if ($incomment) { ++ $comment .= $line; ++ if ($line =~ /\*\//) { ++ $incomment = 0; ++ } ++ } ++ ++ # these are ordered for maximum speed ++ next if ($line =~ /^\s/); ++ ++ next unless ($line =~ /\(/); ++ ++ next if ($line =~ /^\/|[;]/); ++ ++ if ($line =~ /^FN_/) { ++ handle_loadparm($file, $line); ++ } ++ next; ++ } ++ ++ close(FH); ++} ++ ++ ++print_header(\&public, $public_define); ++ ++process_file(\&public, $_) foreach (@ARGV); ++print_footer(\&public, $public_define); ++ ++if (not defined($file)) { ++ print STDOUT $$public_data; ++} ++ ++mkpath(dirname($file), 0, 0755); ++open(PUBLIC, ">$file") or die("Can't open `$file': $!"); ++print PUBLIC "$$public_data"; ++close(PUBLIC); +diff --git a/source3/include/proto.h b/source3/include/proto.h +index 53cd59d..614baa4 100644 +--- a/source3/include/proto.h ++++ b/source3/include/proto.h +@@ -993,6 +993,8 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m + + /* The following definitions come from param/loadparm.c */ + ++#include "source3/param/param_proto.h" ++ + const char **lp_smb_ports(void); + const char *lp_dos_charset(void); + const char *lp_unix_charset(void); +diff --git a/source3/param/wscript_build b/source3/param/wscript_build +index 278d5f5..643c27e 100644 +--- a/source3/param/wscript_build ++++ b/source3/param/wscript_build +@@ -13,6 +13,11 @@ bld.SAMBA_GENERATOR('s3_param_global_h', + target='param_global.h', + rule='${PERL} ${SRC[0].abspath(env)} ${SRC[1].abspath(env)} ${SRC[2].abspath(env)} --file ${TGT} --generate-scope=GLOBAL') + ++bld.SAMBA_GENERATOR('s3_param_proto_h', ++ source= '../../script/mks3param_proto.pl loadparm.c ../../lib/param/param_functions.c', ++ target='param_proto.h', ++ rule='${PERL} ${SRC[0].abspath(env)} ${SRC[1].abspath(env)} ${SRC[2].abspath(env)} --file ${TGT}') ++ + bld.SAMBA3_PYTHON('pys3param', + source='pyparam.c', + deps='param', +-- +1.9.3 + + +From 4f87a4ca65b386e90cca479aabdf9051de2c67e3 Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Mon, 14 Oct 2013 15:46:43 +1300 +Subject: [PATCH 119/249] param: Autogenerate s3 lp_ctx glue table + +This allows us to use more lpcfg_ functions without adding them +manually. + +Signed-off-by: Andrew Bartlett +Reviewed-by: Stefan Metzmacher +--- + lib/param/wscript_build | 1 + + script/mks3param_ctx_table.pl | 139 ++++++++++++++++++++++++++++++++++++++++++ + source3/param/loadparm_ctx.c | 64 +------------------ + source3/param/wscript_build | 5 ++ + 4 files changed, 146 insertions(+), 63 deletions(-) + create mode 100644 script/mks3param_ctx_table.pl + +diff --git a/lib/param/wscript_build b/lib/param/wscript_build +index 10e05a3..0e1a2e0 100644 +--- a/lib/param/wscript_build ++++ b/lib/param/wscript_build +@@ -11,6 +11,7 @@ bld.SAMBA_GENERATOR('s3_param_h', + target='s3_param.h', + rule='${PERL} ${SRC[0].abspath(env)} ${SRC[1].abspath(env)} ${SRC[2].abspath(env)} --file ${TGT}') + ++ + bld.SAMBA_GENERATOR('param_global_h', + source= '../../script/mkparamdefs.pl loadparm.c param_functions.c', + target='param_global.h', +diff --git a/script/mks3param_ctx_table.pl b/script/mks3param_ctx_table.pl +new file mode 100644 +index 0000000..cfd6e02 +--- /dev/null ++++ b/script/mks3param_ctx_table.pl +@@ -0,0 +1,139 @@ ++#!/usr/bin/perl ++# Generate loadparm interfaces tables for Samba3/Samba4 integration ++# by Andrew Bartlett ++# based on mkproto.pl Written by Jelmer Vernooij ++# based on the original mkproto.sh by Andrew Tridgell ++ ++use strict; ++ ++# don't use warnings module as it is not portable enough ++# use warnings; ++ ++use Getopt::Long; ++use File::Basename; ++use File::Path; ++ ++##################################################################### ++# read a file into a string ++ ++my $file = undef; ++my $public_define = undef; ++my $_public = ""; ++my $_private = ""; ++my $public_data = \$_public; ++my $builddir = "."; ++my $srcdir = "."; ++ ++sub public($) ++{ ++ my ($d) = @_; ++ $$public_data .= $d; ++} ++ ++sub usage() ++{ ++ print "Usage: mks3param.pl [options] [c files]\n"; ++ print "OPTIONS:\n"; ++ print " --srcdir=path Read files relative to this directory\n"; ++ print " --builddir=path Write file relative to this directory\n"; ++ print " --help Print this help message\n\n"; ++ exit 0; ++} ++ ++GetOptions( ++ 'file=s' => sub { my ($f,$v) = @_; $file = $v; }, ++ 'srcdir=s' => sub { my ($f,$v) = @_; $srcdir = $v; }, ++ 'builddir=s' => sub { my ($f,$v) = @_; $builddir = $v; }, ++ 'help' => \&usage ++) or exit(1); ++ ++sub file_load($) ++{ ++ my($filename) = @_; ++ local(*INPUTFILE); ++ open(INPUTFILE, $filename) or return undef; ++ my($saved_delim) = $/; ++ undef $/; ++ my($data) = ; ++ close(INPUTFILE); ++ $/ = $saved_delim; ++ return $data; ++} ++ ++sub print_header($) ++{ ++ my ($file) = @_; ++ $file->("/* This file was automatically generated by mks3param_ctx.pl. DO NOT EDIT */\n\n"); ++ $file->("static const struct loadparm_s3_helpers s3_fns = \n"); ++ $file->("{\n"); ++ $file->("\t.get_parametric = lp_parm_const_string_service,\n"); ++ $file->("\t.get_parm_struct = lp_get_parameter,\n"); ++ $file->("\t.get_parm_ptr = lp_parm_ptr,\n"); ++ $file->("\t.get_service = lp_service_for_s4_ctx,\n"); ++ $file->("\t.get_servicebynum = lp_servicebynum_for_s4_ctx,\n"); ++ $file->("\t.get_default_loadparm_service = lp_default_loadparm_service,\n"); ++ $file->("\t.get_numservices = lp_numservices,\n"); ++ $file->("\t.load = lp_load_for_s4_ctx,\n"); ++ $file->("\t.set_cmdline = lp_set_cmdline,\n"); ++ $file->("\t.dump = lp_dump,\n"); ++} ++ ++sub print_footer($) ++{ ++ my ($file) = @_; ++ $file->("};"); ++} ++ ++sub handle_loadparm($$) ++{ ++ my ($file,$line) = @_; ++ ++ # STRING isn't handled here, as we still don't know what to do with the substituted vars */ ++ # LOCAL also isn't handled here ++ if ($line =~ /^FN_(GLOBAL)_(CONST_STRING|BOOL|bool|CHAR|INTEGER|LIST)\((\w+),.*\)/o) { ++ my $scope = $1; ++ my $type = $2; ++ my $name = $3; ++ ++ $file->(".$name = lp_$name,\n"); ++ } ++} ++ ++sub process_file($$) ++{ ++ my ($file, $filename) = @_; ++ ++ $filename =~ s/\.o$/\.c/g; ++ ++ if ($filename =~ /^\//) { ++ open(FH, "<$filename") or die("Failed to open $filename"); ++ } elsif (!open(FH, "< $builddir/$filename")) { ++ open(FH, "< $srcdir/$filename") || die "Failed to open $filename"; ++ } ++ ++ my $comment = undef; ++ my $incomment = 0; ++ while (my $line = ) { ++ if ($line =~ /^FN_/) { ++ handle_loadparm($file, $line); ++ } ++ next; ++ } ++ ++ close(FH); ++} ++ ++ ++print_header(\&public); ++ ++process_file(\&public, $_) foreach (@ARGV); ++print_footer(\&public); ++ ++if (not defined($file)) { ++ print STDOUT $$public_data; ++} ++ ++mkpath(dirname($file), 0, 0755); ++open(PUBLIC, ">$file") or die("Can't open `$file': $!"); ++print PUBLIC "$$public_data"; ++close(PUBLIC); +diff --git a/source3/param/loadparm_ctx.c b/source3/param/loadparm_ctx.c +index 63ead53..5cbc920 100644 +--- a/source3/param/loadparm_ctx.c ++++ b/source3/param/loadparm_ctx.c +@@ -56,69 +56,7 @@ static bool lp_load_for_s4_ctx(const char *filename) + return status; + } + +-/* These are in the order that they appear in the s4 loadparm file. +- * All of the s4 loadparm functions should be here eventually, once +- * they are implemented in the s3 loadparm, have the same format (enum +- * values in particular) and defaults. */ +-static const struct loadparm_s3_helpers s3_fns = +-{ +- .get_parametric = lp_parm_const_string_service, +- .get_parm_struct = lp_get_parameter, +- .get_parm_ptr = lp_parm_ptr, +- .get_service = lp_service_for_s4_ctx, +- .get_servicebynum = lp_servicebynum_for_s4_ctx, +- .get_default_loadparm_service = lp_default_loadparm_service, +- .get_numservices = lp_numservices, +- .load = lp_load_for_s4_ctx, +- .set_cmdline = lp_set_cmdline, +- .dump = lp_dump, +- +- ._server_role = lp__server_role, +- ._security = lp__security, +- ._domain_master = lp__domain_master, +- ._domain_logons = lp__domain_logons, +- +- .winbind_separator = lp_winbind_separator, +- .template_homedir = lp_template_homedir, +- .template_shell = lp_template_shell, +- +- .dos_charset = lp_dos_charset, +- .unix_charset = lp_unix_charset, +- +- .realm = lp_realm, +- .dnsdomain = lp_dnsdomain, +- .socket_options = lp_socket_options, +- .workgroup = lp_workgroup, +- +- .netbios_name = lp_netbios_name, +- .netbios_scope = lp_netbios_scope, +- .netbios_aliases = lp_netbios_aliases, +- +- .lanman_auth = lp_lanman_auth, +- .ntlm_auth = lp_ntlm_auth, +- +- .client_plaintext_auth = lp_client_plaintext_auth, +- .client_lanman_auth = lp_client_lanman_auth, +- .client_ntlmv2_auth = lp_client_ntlmv2_auth, +- .client_use_spnego_principal = lp_client_use_spnego_principal, +- +- .private_dir = lp_private_dir, +- .ncalrpc_dir = lp_ncalrpc_dir, +- .lockdir = lp_lockdir, +- +- .passdb_backend = lp_passdb_backend, +- +- .host_msdfs = lp_host_msdfs, +- .unix_extensions = lp_unix_extensions, +- .use_spnego = lp_use_spnego, +- .use_mmap = lp_use_mmap, +- .use_ntdb = lp_use_ntdb, +- +- .srv_minprotocol = lp_srv_minprotocol, +- .srv_maxprotocol = lp_srv_maxprotocol, +- +- .passwordserver = lp_passwordserver +-}; ++#include "loadparm_ctx_table.c" + + const struct loadparm_s3_helpers *loadparm_s3_helpers(void) + { +diff --git a/source3/param/wscript_build b/source3/param/wscript_build +index 643c27e..673cb4d 100644 +--- a/source3/param/wscript_build ++++ b/source3/param/wscript_build +@@ -18,6 +18,11 @@ bld.SAMBA_GENERATOR('s3_param_proto_h', + target='param_proto.h', + rule='${PERL} ${SRC[0].abspath(env)} ${SRC[1].abspath(env)} ${SRC[2].abspath(env)} --file ${TGT}') + ++bld.SAMBA_GENERATOR('s3_loadparm_ctx_table_c', ++ source= ' ../../script/mks3param_ctx_table.pl ../../lib/param/loadparm.c ../../lib/param/param_functions.c', ++ target='loadparm_ctx_table.c', ++ rule='${PERL} ${SRC[0].abspath(env)} ${SRC[1].abspath(env)} ${SRC[2].abspath(env)} --file ${TGT}') ++ + bld.SAMBA3_PYTHON('pys3param', + source='pyparam.c', + deps='param', +-- +1.9.3 + + +From 0046f49e1c690cf5b119859650f06559697fd103 Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Mon, 14 Oct 2013 15:49:25 +1300 +Subject: [PATCH 120/249] proto: Remove manually written lp_ prototypes + +This also ensures we remove prototypes from parameters we remove or +rename, and easily see how many special cases we have left. + +Signed-off-by: Andrew Bartlett +Reviewed-by: Stefan Metzmacher +--- + source3/include/proto.h | 361 +----------------------------------------------- + 1 file changed, 1 insertion(+), 360 deletions(-) + +diff --git a/source3/include/proto.h b/source3/include/proto.h +index 614baa4..5e068d2 100644 +--- a/source3/include/proto.h ++++ b/source3/include/proto.h +@@ -995,379 +995,20 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m + + #include "source3/param/param_proto.h" + +-const char **lp_smb_ports(void); +-const char *lp_dos_charset(void); +-const char *lp_unix_charset(void); +-char *lp_logfile(TALLOC_CTX *ctx); +-char *lp_configfile(TALLOC_CTX *ctx); +-const char *lp_smb_passwd_file(void); +-const char *lp_private_dir(void); +-char *lp_serverstring(TALLOC_CTX *ctx); +-int lp_printcap_cache_time(void); +-char *lp_addport_cmd(TALLOC_CTX *ctx); +-char *lp_enumports_cmd(TALLOC_CTX *ctx); +-char *lp_addprinter_cmd(TALLOC_CTX *ctx); +-char *lp_deleteprinter_cmd(TALLOC_CTX *ctx); +-char *lp_os2_driver_map(TALLOC_CTX *ctx); +-const char *lp_lockdir(void); + const char *lp_statedir(void); + const char *lp_cachedir(void); +-const char *lp_piddir(void); +-char *lp_mangling_method(TALLOC_CTX *ctx); +-int lp_mangle_prefix(void); +-const char *lp_utmpdir(void); +-const char *lp_wtmpdir(void); +-bool lp_utmp(void); +-char *lp_rootdir(TALLOC_CTX *ctx); +-char *lp_defaultservice(TALLOC_CTX *ctx); +-char *lp_msg_command(TALLOC_CTX *ctx); +-char *lp_get_quota_command(TALLOC_CTX *ctx); +-char *lp_set_quota_command(TALLOC_CTX *ctx); +-char *lp_auto_services(TALLOC_CTX *ctx); +-char *lp_passwd_program(TALLOC_CTX *ctx); +-char *lp_passwd_chat(TALLOC_CTX *ctx); +-const char *lp_passwordserver(void); +-const char **lp_name_resolve_order(void); +-const char *lp_netbios_scope(void); +-const char *lp_netbios_name(void); +-const char *lp_workgroup(void); +-const char *lp_realm(void); +-const char *lp_dnsdomain(void); +-const char *lp_afs_username_map(void); +-int lp_afs_token_lifetime(void); +-char *lp_log_nt_token_command(TALLOC_CTX *ctx); +-char *lp_username_map(TALLOC_CTX *ctx); +-const char *lp_logon_script(void); +-const char *lp_logon_path(void); +-const char *lp_logon_drive(void); +-const char *lp_logon_home(void); +-char *lp_remote_announce(TALLOC_CTX *ctx); +-char *lp_remote_browse_sync(TALLOC_CTX *ctx); +-bool lp_nmbd_bind_explicit_broadcast(void); +-const char **lp_wins_server_list(void); +-const char **lp_interfaces(void); +-const char *lp_nbt_client_socket_address(void); +-char *lp_nis_home_map_name(TALLOC_CTX *ctx); +-const char **lp_netbios_aliases(void); +-const char *lp_passdb_backend(void); +-const char **lp_preload_modules(void); +-char *lp_panic_action(TALLOC_CTX *ctx); +-char *lp_adduser_script(TALLOC_CTX *ctx); +-char *lp_renameuser_script(TALLOC_CTX *ctx); +-char *lp_deluser_script(TALLOC_CTX *ctx); +-const char *lp_guestaccount(void); +-char *lp_addgroup_script(TALLOC_CTX *ctx); +-char *lp_delgroup_script(TALLOC_CTX *ctx); +-char *lp_addusertogroup_script(TALLOC_CTX *ctx); +-char *lp_deluserfromgroup_script(TALLOC_CTX *ctx); +-char *lp_setprimarygroup_script(TALLOC_CTX *ctx); +-char *lp_addmachine_script(TALLOC_CTX *ctx); +-char *lp_shutdown_script(TALLOC_CTX *ctx); +-char *lp_abort_shutdown_script(TALLOC_CTX *ctx); +-char *lp_username_map_script(TALLOC_CTX *ctx); +-int lp_username_map_cache_time(void); +-char *lp_check_password_script(TALLOC_CTX *ctx); +-char *lp_wins_hook(TALLOC_CTX *ctx); +-const char *lp_template_homedir(void); +-const char *lp_template_shell(void); +-const char *lp_winbind_separator(void); +-const char *lp_winbindd_socket_directory(void); +-bool lp_winbind_enum_users(void); +-bool lp_winbind_enum_groups(void); +-bool lp_winbind_use_default_domain(void); +-bool lp_winbind_trusted_domains_only(void); +-bool lp_winbind_nested_groups(void); +-int lp_winbind_expand_groups(void); +-bool lp_winbind_refresh_tickets(void); +-bool lp_winbind_offline_logon(void); +-bool lp_winbind_normalize_names(void); +-bool lp_winbind_rpc_only(void); +-bool lp_create_krb5_conf(void); + int lp_winbind_max_domain_connections(void); +-int lp_idmap_cache_time(void); +-int lp_idmap_negative_cache_time(void); + bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high); + bool lp_idmap_default_range(uint32_t *low, uint32_t *high); + const char *lp_idmap_backend(const char *domain_name); + const char *lp_idmap_default_backend (void); +-int lp_keepalive(void); +-bool lp_passdb_expand_explicit(void); +-char *lp_ldap_suffix(TALLOC_CTX *ctx); +-char *lp_ldap_admin_dn(TALLOC_CTX *ctx); +-int lp_ldap_ssl(void); +-bool lp_ldap_ssl_ads(void); +-int lp_ldap_deref(void); +-int lp_ldap_follow_referral(void); +-int lp_ldap_passwd_sync(void); +-bool lp_ldap_delete_dn(void); +-int lp_ldap_replication_sleep(void); +-int lp_ldap_timeout(void); +-int lp_ldap_connection_timeout(void); +-int lp_ldap_page_size(void); +-int lp_ldap_debug_level(void); +-int lp_ldap_debug_threshold(void); +-char *lp_add_share_cmd(TALLOC_CTX *ctx); +-char *lp_change_share_cmd(TALLOC_CTX *ctx); +-char *lp_delete_share_cmd(TALLOC_CTX *ctx); +-char *lp_usershare_path(TALLOC_CTX *ctx); +-const char **lp_usershare_prefix_allow_list(void); +-const char **lp_usershare_prefix_deny_list(void); +-const char **lp_eventlog_list(void); +-bool lp_registry_shares(void); +-bool lp_usershare_allow_guests(void); +-bool lp_usershare_owner_only(void); +-bool lp_disable_netbios(void); +-bool lp_reset_on_zero_vc(void); +-bool lp_log_writeable_files_on_exit(void); +-bool lp_ms_add_printer_wizard(void); +-bool lp_wins_dns_proxy(void); +-bool lp_we_are_a_wins_server(void); +-bool lp_wins_proxy(void); +-bool lp_local_master(void); +-const char **lp_init_logon_delayed_hosts(void); +-int lp_init_logon_delay(void); +-bool lp_load_printers(void); + bool lp_readraw(void); +-bool lp_large_readwrite(void); + bool lp_writeraw(void); +-bool lp_null_passwords(void); +-bool lp_obey_pam_restrictions(void); +-bool lp_encrypted_passwords(void); +-int lp_client_schannel(void); +-int lp_server_schannel(void); +-bool lp_syslog_only(void); +-bool lp_timestamp_logs(void); +-bool lp_debug_prefix_timestamp(void); +-bool lp_debug_hires_timestamp(void); +-bool lp_debug_pid(void); +-bool lp_debug_uid(void); +-bool lp_debug_class(void); +-bool lp_enable_core_files(void); +-bool lp_browse_list(void); +-bool lp_nis_home_map(void); +-bool lp_bind_interfaces_only(void); +-bool lp_pam_password_change(void); +-bool lp_unix_password_sync(void); +-bool lp_passwd_chat_debug(void); +-int lp_passwd_chat_timeout(void); +-bool lp_nt_pipe_support(void); +-bool lp_nt_status_support(void); +-bool lp_stat_cache(void); +-int lp_max_stat_cache_size(void); +-bool lp_allow_trusted_domains(void); +-bool lp_map_untrusted_to_domain(void); +-int lp_restrict_anonymous(void); +-bool lp_lanman_auth(void); +-bool lp_ntlm_auth(void); +-bool lp_client_plaintext_auth(void); +-bool lp_client_lanman_auth(void); +-bool lp_client_ntlmv2_auth(void); +-bool lp_host_msdfs(void); +-bool lp_enhanced_browsing(void); +-bool lp_use_mmap(void); +-bool lp_use_ntdb(void); +-bool lp_unix_extensions(void); +-bool lp_unicode(void); +-bool lp_use_spnego(void); +-bool lp_client_use_spnego(void); +-bool lp_client_use_spnego_principal(void); +-bool lp_hostname_lookups(void); +-bool lp_change_notify(const struct share_params *p ); +-bool lp_kernel_change_notify(const struct share_params *p ); +-const char * lp_dedicated_keytab_file(void); +-int lp_kerberos_method(void); +-bool lp_defer_sharing_violations(void); +-bool lp_enable_privileges(void); +-bool lp_enable_asu_support(void); +-int lp_os_level(void); +-int lp_max_ttl(void); +-int lp_max_wins_ttl(void); +-int lp_min_wins_ttl(void); +-int lp_max_log_size(void); +-int lp_max_open_files(void); +-int lp_open_files_db_hash_size(void); +-int lp_max_xmit(void); +-int lp_maxmux(void); +-int lp_passwordlevel(void); +-int lp_usernamelevel(void); +-int lp_deadtime(void); +-bool lp_getwd_cache(void); +-int lp_srv_maxprotocol(void); +-int lp_srv_minprotocol(void); +-int lp_cli_maxprotocol(void); +-int lp_cli_minprotocol(void); + int lp_security(void); +-int lp__server_role(void); +-int lp__security(void); +-int lp__domain_master(void); +-bool lp__domain_logons(void); +-const char **lp_auth_methods(void); +-bool lp_paranoid_server_security(void); +-int lp_maxdisksize(void); +-int lp_lpqcachetime(void); +-int lp_max_smbd_processes(void); +-bool lp__disable_spoolss(void); +-int lp_syslog(void); +-int lp_lm_announce(void); +-int lp_lm_interval(void); +-int lp_machine_password_timeout(void); +-int lp_map_to_guest(void); +-int lp_oplock_break_wait_time(void); +-int lp_lock_spin_time(void); +-int lp_usershare_max_shares(void); +-const char *lp_socket_options(void); +-int lp_config_backend(void); +-int lp_smb2_max_read(void); +-int lp_smb2_max_write(void); +-int lp_smb2_max_trans(void); + int lp_smb2_max_credits(void); +-char *lp_preexec(TALLOC_CTX *ctx, int ); +-char *lp_postexec(TALLOC_CTX *ctx, int ); +-char *lp_rootpreexec(TALLOC_CTX *ctx, int ); +-char *lp_rootpostexec(TALLOC_CTX *ctx, int ); +-char *lp_servicename(TALLOC_CTX *ctx, int ); +-const char *lp_const_servicename(int ); +-char *lp_pathname(TALLOC_CTX *ctx, int ); +-char *lp_dontdescend(TALLOC_CTX *ctx, int ); +-char *lp_username(TALLOC_CTX *ctx, int ); +-const char **lp_invalid_users(int ); +-const char **lp_valid_users(int ); +-const char **lp_admin_users(int ); +-const char **lp_svcctl_list(void); +-char *lp_cups_options(TALLOC_CTX *ctx, int ); +-char *lp_cups_server(TALLOC_CTX *ctx); + int lp_cups_encrypt(void); +-char *lp_iprint_server(TALLOC_CTX *ctx); +-int lp_cups_connection_timeout(void); +-const char *lp_ctdbd_socket(void); +-const char *_lp_ctdbd_socket(void); +-const char **lp_cluster_addresses(void); +-bool lp_clustering(void); +-int lp_ctdb_timeout(void); +-int lp_ctdb_locktime_warn_threshold(void); +-char *lp_printcommand(TALLOC_CTX *ctx, int ); +-char *lp_lpqcommand(TALLOC_CTX *ctx, int ); +-char *lp_lprmcommand(TALLOC_CTX *ctx, int ); +-char *lp_lppausecommand(TALLOC_CTX *ctx, int ); +-char *lp_lpresumecommand(TALLOC_CTX *ctx, int ); +-char *lp_queuepausecommand(TALLOC_CTX *ctx, int ); +-char *lp_queueresumecommand(TALLOC_CTX *ctx, int ); +-const char *lp_printjob_username(int ); +-const char **lp_hostsallow(int ); +-const char **lp_hostsdeny(int ); +-char *lp_magicscript(TALLOC_CTX *ctx, int ); +-char *lp_magicoutput(TALLOC_CTX *ctx, int ); +-char *lp_comment(TALLOC_CTX *ctx, int ); +-char *lp_force_user(TALLOC_CTX *ctx, int ); +-char *lp_force_group(TALLOC_CTX *ctx, int ); +-const char **lp_readlist(int ); +-const char **lp_writelist(int ); +-char *lp_fstype(TALLOC_CTX *ctx, int ); +-const char **lp_vfs_objects(int ); +-char *lp_msdfs_proxy(TALLOC_CTX *ctx, int ); +-char *lp_veto_files(TALLOC_CTX *ctx, int ); +-char *lp_hide_files(TALLOC_CTX *ctx, int ); +-char *lp_veto_oplocks(TALLOC_CTX *ctx, int ); +-bool lp_msdfs_root(int ); +-char *lp_aio_write_behind(TALLOC_CTX *ctx, int ); +-char *lp_dfree_command(TALLOC_CTX *ctx, int ); +-bool lp_autoloaded(int ); +-bool lp_preexec_close(int ); +-bool lp_rootpreexec_close(int ); +-int lp_casesensitive(int ); +-bool lp_preservecase(int ); +-bool lp_shortpreservecase(int ); +-bool lp_hide_dot_files(int ); +-bool lp_hide_special_files(int ); +-bool lp_hideunreadable(int ); +-bool lp_hideunwriteable_files(int ); +-bool lp_browseable(int ); +-bool lp_access_based_share_enum(int ); +-bool lp_readonly(int ); +-bool lp_guest_ok(int ); +-bool lp_guest_only(int ); +-bool lp_administrative_share(int ); +-bool lp_print_ok(int ); +-bool lp_print_notify_backchannel(int ); +-bool lp_map_hidden(int ); +-bool lp_map_archive(int ); +-bool lp_store_dos_attributes(int ); +-bool lp_dmapi_support(int ); +-bool lp_locking(const struct share_params *p ); +-int lp_strict_locking(const struct share_params *p ); +-bool lp_posix_locking(const struct share_params *p ); +-bool lp_oplocks(int ); +-bool lp_kernel_oplocks(int ); +-bool lp_level2_oplocks(int ); +-bool lp_kernel_share_modes(int); +-bool lp_onlyuser(int ); +-bool lp_manglednames(const struct share_params *p ); +-bool lp_allow_insecure_widelinks(void); + bool lp_widelinks(int ); +-bool lp_symlinks(int ); +-bool lp_syncalways(int ); +-bool lp_strict_allocate(int ); +-bool lp_strict_sync(int ); +-bool lp_map_system(int ); +-bool lp_delete_readonly(int ); +-bool lp_fake_oplocks(int ); +-bool lp_recursive_veto_delete(int ); +-bool lp_dos_filemode(int ); +-bool lp_dos_filetimes(int ); +-bool lp_dos_filetime_resolution(int ); +-bool lp_fake_dir_create_times(int); +-bool lp_async_smb_echo_handler(void); +-bool lp_multicast_dns_register(void); +-bool lp_blocking_locks(int ); +-bool lp_inherit_perms(int ); +-bool lp_inherit_acls(int ); +-bool lp_inherit_owner(int ); +-bool lp_use_client_driver(int ); +-bool lp_default_devmode(int ); +-bool lp_force_printername(int ); +-bool lp_nt_acl_support(int ); +-bool lp_force_unknown_acl_user(int ); +-bool lp_ea_support(int ); +-bool lp__use_sendfile(int ); +-bool lp_profile_acls(int ); +-bool lp_map_acl_inherit(int ); +-bool lp_afs_share(int ); +-bool lp_acl_check_permissions(int ); +-bool lp_acl_group_control(int ); +-bool lp_acl_map_full_control(int ); +-bool lp_acl_allow_execute_always(int); +-bool lp_durable_handles(int); +-int lp_create_mask(int ); +-int lp_force_create_mode(int ); +-int lp_dir_mask(int ); +-int lp_force_dir_mode(int ); +-int lp_max_connections(int ); +-int lp_defaultcase(int ); +-int lp_minprintspace(int ); +-int lp_printing(int ); +-int lp_max_reported_jobs(int ); +-int lp_oplock_contention_limit(int ); +-int lp_csc_policy(int ); +-int lp_write_cache_size(int ); +-int lp_block_size(int ); +-int lp_dfree_cache_time(int ); +-int lp_allocation_roundup_size(int ); +-int lp_aio_read_size(int ); +-int lp_aio_write_size(int ); +-int lp_map_readonly(int ); +-int lp_directory_name_cache_size(int ); +-int lp_smb_encrypt(int ); +-char lp_magicchar(const struct share_params *p ); +-int lp_winbind_cache_time(void); +-int lp_winbind_reconnect_delay(void); +-int lp_winbind_request_timeout(void); +-int lp_winbind_max_clients(void); +-const char **lp_winbind_nss_info(void); +-int lp_algorithmic_rid_base(void); +-int lp_name_cache_timeout(void); +-int lp_client_signing(void); +-int lp_server_signing(void); +-int lp_client_ldap_sasl_wrapping(void); ++ + char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def); + const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def); + struct loadparm_service; +-- +1.9.3 + + +From 5d2278756b5a7372106cbdf9b8d66fb8a0cf5033 Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Wed, 16 Oct 2013 14:45:31 +1300 +Subject: [PATCH 121/249] lib/param: Add documentation on how loadparm works + +Signed-off-by: Andrew Bartlett +Reviewed-by: Stefan Metzmacher +Reviewed-by: Volker Lendecke +--- + lib/param/README | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 69 insertions(+) + +diff --git a/lib/param/README b/lib/param/README +index 403a217..b567d71 100644 +--- a/lib/param/README ++++ b/lib/param/README +@@ -1,4 +1,73 @@ ++libsamba-hostconfig ++------------------- ++ + This directory contains "libsamba-hostconfig". + + The libsamba-hostconfig library provides access to all host-wide configuration + such as the configured shares, default parameter values and host secret keys. ++ ++ ++Adding a parameter ++------------------ ++ ++To add or change an smb.conf option, you only have to modify ++lib/param/param_table.c and lib/param/param_functions.c. The rest is ++generated for you. ++ ++ ++Using smb.conf parameters in the code ++------------------------------------- ++ ++Call the lpcfg_*() function. To get the lp_ctx, have the caller pass ++it to you. To get a lp_ctx for the source3/param loadparm system, use: ++ ++struct loadparm_context *lp_ctx = loadparm_init_s3(tmp_ctx, loadparm_s3_helpers()); ++ ++Remember to talloc_unlink(tmp_ctx, lp_ctx) the result when you are done! ++ ++To get a lp_ctx for the lib/param loadparm system, typically the ++pointer is already set up by popt at startup, and is passed down from ++cmdline_lp_ctx. ++ ++In pure source3/ code, you may use lp_*() functions, but are ++encouraged to use the lpcfg_*() functions so that code can be made ++common. ++ ++ ++How does loadparm_init_s3() work? ++--------------------------------- ++ ++loadparm_s3_helpers() returns a initialised table of function ++pointers, pointing at all global lp_*() functions, except for those ++that return substituted strings (% macros). The lpcfg_*() function ++then calls this plugged in function, allowing the one function and ++pattern to use either loadparm system. ++ ++ ++There is a lot of generated code, here, what generates what? ++------------------------------------------------------------ ++ ++The regular format of the CPP macros in param_functions.c is used to ++generate up the prototypes (mkproto.pl, mks3param_proto.pl), the service ++and globals table (mkparamdefs.pl), the glue table (mmks3param.pl) and ++the initilisation of the glue table (mks3param_ctx_table.pl). ++ ++I have tried combining some of these, but it just makes the scripts more ++complex. ++ ++The CPP macros are defined in and expand in lib/param/loadparm.c and ++source3/param/loadparm.c to read the values from the generated ++stuctures. They are CPP #included into these files so that the same ++macro has two definitions, depending on the system it is loading into. ++ ++ ++Why was this done, rather than a 'proper' fix, or just using one system or the other? ++------------------------------------------------------------------------------------- ++ ++This was done to allow merging from both ends - merging more parts of ++the loadparm handling, and merging code that needs to read the ++smb.conf, without having to do it all at once. Ideally ++param_functions.c would be generated from param_table.c or (even ++better) our XML manpage source, and the CPP macros would instead be ++generated expanded as generated C files, but this is a task nobody has ++taken on yet. +-- +1.9.3 + + +From 7734a867500f5b7415f818077229f74486101c51 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 12 Aug 2013 08:19:08 +0200 +Subject: [PATCH 122/249] librpc/rpc: add dcerpc_binding_handle_auth_info() + +Signed-off-by: Stefan Metzmacher +--- + librpc/rpc/binding_handle.c | 25 +++++++++++++++++++++++++ + librpc/rpc/rpc_common.h | 8 ++++++++ + 2 files changed, 33 insertions(+) + +diff --git a/librpc/rpc/binding_handle.c b/librpc/rpc/binding_handle.c +index 9354bbd..714baa7 100644 +--- a/librpc/rpc/binding_handle.c ++++ b/librpc/rpc/binding_handle.c +@@ -98,6 +98,31 @@ uint32_t dcerpc_binding_handle_set_timeout(struct dcerpc_binding_handle *h, + return h->ops->set_timeout(h, timeout); + } + ++void dcerpc_binding_handle_auth_info(struct dcerpc_binding_handle *h, ++ enum dcerpc_AuthType *auth_type, ++ enum dcerpc_AuthLevel *auth_level) ++{ ++ enum dcerpc_AuthType _auth_type; ++ enum dcerpc_AuthLevel _auth_level; ++ ++ if (auth_type == NULL) { ++ auth_type = &_auth_type; ++ } ++ ++ if (auth_level == NULL) { ++ auth_level = &_auth_level; ++ } ++ ++ *auth_type = DCERPC_AUTH_TYPE_NONE; ++ *auth_level = DCERPC_AUTH_LEVEL_NONE; ++ ++ if (h->ops->auth_info == NULL) { ++ return; ++ } ++ ++ h->ops->auth_info(h, auth_type, auth_level); ++} ++ + struct dcerpc_binding_handle_raw_call_state { + const struct dcerpc_binding_handle_ops *ops; + uint8_t *out_data; +diff --git a/librpc/rpc/rpc_common.h b/librpc/rpc/rpc_common.h +index d2816f5..978229e 100644 +--- a/librpc/rpc/rpc_common.h ++++ b/librpc/rpc/rpc_common.h +@@ -189,6 +189,10 @@ struct dcerpc_binding_handle_ops { + uint32_t (*set_timeout)(struct dcerpc_binding_handle *h, + uint32_t timeout); + ++ void (*auth_info)(struct dcerpc_binding_handle *h, ++ enum dcerpc_AuthType *auth_type, ++ enum dcerpc_AuthLevel *auth_level); ++ + struct tevent_req *(*raw_call_send)(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct dcerpc_binding_handle *h, +@@ -259,6 +263,10 @@ bool dcerpc_binding_handle_is_connected(struct dcerpc_binding_handle *h); + uint32_t dcerpc_binding_handle_set_timeout(struct dcerpc_binding_handle *h, + uint32_t timeout); + ++void dcerpc_binding_handle_auth_info(struct dcerpc_binding_handle *h, ++ enum dcerpc_AuthType *auth_type, ++ enum dcerpc_AuthLevel *auth_level); ++ + struct tevent_req *dcerpc_binding_handle_raw_call_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct dcerpc_binding_handle *h, +-- +1.9.3 + + +From 04a9531474630c62c3f717e251d9f1469013f5ae Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 12 Aug 2013 08:19:35 +0200 +Subject: [PATCH 123/249] s3:rpc_client: implement + dcerpc_binding_handle_auth_info() + +Signed-off-by: Stefan Metzmacher +--- + source3/rpc_client/cli_pipe.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 64e7f1c..a343997 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -1867,6 +1867,25 @@ static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h, + return rpccli_set_timeout(hs->rpc_cli, timeout); + } + ++static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h, ++ enum dcerpc_AuthType *auth_type, ++ enum dcerpc_AuthLevel *auth_level) ++{ ++ struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h, ++ struct rpccli_bh_state); ++ ++ if (hs->rpc_cli == NULL) { ++ return; ++ } ++ ++ if (hs->rpc_cli->auth == NULL) { ++ return; ++ } ++ ++ *auth_type = hs->rpc_cli->auth->auth_type; ++ *auth_level = hs->rpc_cli->auth->auth_level; ++} ++ + struct rpccli_bh_raw_call_state { + DATA_BLOB in_data; + DATA_BLOB out_data; +@@ -2046,6 +2065,7 @@ static const struct dcerpc_binding_handle_ops rpccli_bh_ops = { + .name = "rpccli", + .is_connected = rpccli_bh_is_connected, + .set_timeout = rpccli_bh_set_timeout, ++ .auth_info = rpccli_bh_auth_info, + .raw_call_send = rpccli_bh_raw_call_send, + .raw_call_recv = rpccli_bh_raw_call_recv, + .disconnect_send = rpccli_bh_disconnect_send, +-- +1.9.3 + + +From 1db891bac30bb6c3bb0a022c5d1529a9f001237d Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 12 Aug 2013 08:19:57 +0200 +Subject: [PATCH 124/249] s4:librpc: implement + dcerpc_binding_handle_auth_info() + +Signed-off-by: Stefan Metzmacher +--- + source4/librpc/rpc/dcerpc.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c +index 2826160..56b821e 100644 +--- a/source4/librpc/rpc/dcerpc.c ++++ b/source4/librpc/rpc/dcerpc.c +@@ -200,6 +200,29 @@ static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle *h, + return old; + } + ++static void dcerpc_bh_auth_info(struct dcerpc_binding_handle *h, ++ enum dcerpc_AuthType *auth_type, ++ enum dcerpc_AuthLevel *auth_level) ++{ ++ struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h, ++ struct dcerpc_bh_state); ++ ++ if (hs->p == NULL) { ++ return; ++ } ++ ++ if (hs->p->conn == NULL) { ++ return; ++ } ++ ++ if (hs->p->conn->security_state.auth_info == NULL) { ++ return; ++ } ++ ++ *auth_type = hs->p->conn->security_state.auth_info->auth_type; ++ *auth_level = hs->p->conn->security_state.auth_info->auth_level; ++} ++ + struct dcerpc_bh_raw_call_state { + struct tevent_context *ev; + struct dcerpc_binding_handle *h; +@@ -552,6 +575,7 @@ static const struct dcerpc_binding_handle_ops dcerpc_bh_ops = { + .name = "dcerpc", + .is_connected = dcerpc_bh_is_connected, + .set_timeout = dcerpc_bh_set_timeout, ++ .auth_info = dcerpc_bh_auth_info, + .raw_call_send = dcerpc_bh_raw_call_send, + .raw_call_recv = dcerpc_bh_raw_call_recv, + .disconnect_send = dcerpc_bh_disconnect_send, +-- +1.9.3 + + +From 76304ed57d561eb89dceb3881236a78209dd592c Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 17 Sep 2013 04:25:39 +0200 +Subject: [PATCH 125/249] s3:winbindd: don't hide the error in cm_connect_lsa() + +We should not overwrite the error with NT_STATUS_PIPE_NOT_AVAILABLE. + +Signed-off-by: Stefan Metzmacher +--- + source3/winbindd/winbindd_cm.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c +index d868826..c4f59d3 100644 +--- a/source3/winbindd/winbindd_cm.c ++++ b/source3/winbindd/winbindd_cm.c +@@ -2677,7 +2677,6 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + &ndr_table_lsarpc, + &conn->lsa_pipe); + if (!NT_STATUS_IS_OK(result)) { +- result = NT_STATUS_PIPE_NOT_AVAILABLE; + goto done; + } + +-- +1.9.3 + + +From 9948366e88b1d11127317008c79a2f7182a34d65 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 2 Sep 2013 09:24:42 +0200 +Subject: [PATCH 126/249] s3:include: add forward declaration for struct + messaging_context; in g_lock.h + +Signed-off-by: Stefan Metzmacher +--- + source3/include/g_lock.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/source3/include/g_lock.h b/source3/include/g_lock.h +index 004c452..f513349 100644 +--- a/source3/include/g_lock.h ++++ b/source3/include/g_lock.h +@@ -23,6 +23,7 @@ + #include "dbwrap/dbwrap.h" + + struct g_lock_ctx; ++struct messaging_context; + + enum g_lock_type { + G_LOCK_READ = 0, +-- +1.9.3 + + +From 4c30267e3c26cb065b908ff396ca21937fc870c4 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 2 Sep 2013 19:29:05 +0200 +Subject: [PATCH 127/249] s3:include: fix messaging_send_buf() protype in + messages.h + +The function already used 'uint8_t' instead of 'uint8'. + +Signed-off-by: Stefan Metzmacher +--- + source3/include/messages.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source3/include/messages.h b/source3/include/messages.h +index 09c39cc..50b2a84 100644 +--- a/source3/include/messages.h ++++ b/source3/include/messages.h +@@ -139,7 +139,7 @@ NTSTATUS messaging_send(struct messaging_context *msg_ctx, + + NTSTATUS messaging_send_buf(struct messaging_context *msg_ctx, + struct server_id server, uint32_t msg_type, +- const uint8 *buf, size_t len); ++ const uint8_t *buf, size_t len); + void messaging_dispatch_rec(struct messaging_context *msg_ctx, + struct messaging_rec *rec); + +-- +1.9.3 + + +From ff45e4d1ca6cff9b2f329d18e98ebd4883639ed9 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 27 Aug 2013 12:09:51 +0200 +Subject: [PATCH 128/249] s3:auth_domain: remove dead code in + check_trustdomain_security() + +Signed-off-by: Stefan Metzmacher +--- + source3/auth/auth_domain.c | 22 ---------------------- + 1 file changed, 22 deletions(-) + +diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c +index 06078e2..9f88c4a 100644 +--- a/source3/auth/auth_domain.c ++++ b/source3/auth/auth_domain.c +@@ -378,8 +378,6 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte + struct auth_serversupplied_info **server_info) + { + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; +- unsigned char trust_md4_password[16]; +- char *trust_password; + fstring dc_name; + struct sockaddr_storage dc_ss; + +@@ -408,26 +406,6 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte + if ( !is_trusted_domain( user_info->mapped.domain_name ) ) + return NT_STATUS_NOT_IMPLEMENTED; + +- /* +- * Get the trusted account password for the trusted domain +- * No need to become_root() as secrets_init() is done at startup. +- */ +- +- if (!pdb_get_trusteddom_pw(user_info->mapped.domain_name, &trust_password, +- NULL, NULL)) { +- DEBUG(0, ("check_trustdomain_security: could not fetch trust " +- "account password for domain %s\n", +- user_info->mapped.domain_name)); +- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; +- } +- +-#ifdef DEBUG_PASSWORD +- DEBUG(100, ("Trust password for domain %s is %s\n", user_info->mapped.domain_name, +- trust_password)); +-#endif +- E_md4hash(trust_password, trust_md4_password); +- SAFE_FREE(trust_password); +- + /* use get_dc_name() for consistency even through we know that it will be + a netbios name */ + +-- +1.9.3 + + +From d9160b0834f74508b711eeec0354aa43d5a1b215 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 2 Sep 2013 20:18:39 +0200 +Subject: [PATCH 129/249] s3:libsmb: remove unused + change_trust_account_password() + +Signed-off-by: Stefan Metzmacher +--- + source3/include/proto.h | 1 - + source3/libsmb/trusts_util.c | 72 -------------------------------------------- + 2 files changed, 73 deletions(-) + +diff --git a/source3/include/proto.h b/source3/include/proto.h +index 5e068d2..a40d3c1 100644 +--- a/source3/include/proto.h ++++ b/source3/include/proto.h +@@ -989,7 +989,6 @@ NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *m + NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *domain) ; +-NTSTATUS change_trust_account_password( const char *domain, const char *remote_machine); + + /* The following definitions come from param/loadparm.c */ + +diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c +index 6156ba0..8a0e53d 100644 +--- a/source3/libsmb/trusts_util.c ++++ b/source3/libsmb/trusts_util.c +@@ -135,75 +135,3 @@ NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, + sec_channel_type); + } + +-NTSTATUS change_trust_account_password( const char *domain, const char *remote_machine) +-{ +- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; +- struct sockaddr_storage pdc_ss; +- fstring dc_name; +- struct cli_state *cli = NULL; +- struct rpc_pipe_client *netlogon_pipe = NULL; +- +- DEBUG(5,("change_trust_account_password: Attempting to change trust account password in domain %s....\n", +- domain)); +- +- if (remote_machine == NULL || !strcmp(remote_machine, "*")) { +- /* Use the PDC *only* for this */ +- +- if ( !get_pdc_ip(domain, &pdc_ss) ) { +- DEBUG(0,("Can't get IP for PDC for domain %s\n", domain)); +- goto failed; +- } +- +- if ( !name_status_find( domain, 0x1b, 0x20, &pdc_ss, dc_name) ) +- goto failed; +- } else { +- /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */ +- fstrcpy( dc_name, remote_machine ); +- } +- +- /* if this next call fails, then give up. We can't do +- password changes on BDC's --jerry */ +- +- if (!NT_STATUS_IS_OK(cli_full_connection(&cli, lp_netbios_name(), dc_name, +- NULL, 0, +- "IPC$", "IPC", +- "", "", +- "", 0, SMB_SIGNING_DEFAULT))) { +- DEBUG(0,("modify_trust_password: Connection to %s failed!\n", dc_name)); +- nt_status = NT_STATUS_UNSUCCESSFUL; +- goto failed; +- } +- +- /* +- * Ok - we have an anonymous connection to the IPC$ share. +- * Now start the NT Domain stuff :-). +- */ +- +- /* Shouldn't we open this with schannel ? JRA. */ +- +- nt_status = cli_rpc_pipe_open_noauth( +- cli, &ndr_table_netlogon, &netlogon_pipe); +- if (!NT_STATUS_IS_OK(nt_status)) { +- DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", +- dc_name, nt_errstr(nt_status))); +- cli_shutdown(cli); +- cli = NULL; +- goto failed; +- } +- +- nt_status = trust_pw_find_change_and_store_it( +- netlogon_pipe, netlogon_pipe, domain); +- +- cli_shutdown(cli); +- cli = NULL; +- +-failed: +- if (!NT_STATUS_IS_OK(nt_status)) { +- DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n", +- current_timestring(talloc_tos(), False), domain)); +- } +- else +- DEBUG(5,("change_trust_account_password: sucess!\n")); +- +- return nt_status; +-} +-- +1.9.3 + + +From c6b50a3d8c382f19a8ae16428d557928438be464 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 2 Sep 2013 20:19:28 +0200 +Subject: [PATCH 130/249] s3:libsmb: inline trust_pw_change_and_store_it() into + trust_pw_find_change_and_store_it() + +Signed-off-by: Stefan Metzmacher +--- + source3/include/proto.h | 5 ----- + source3/libsmb/trusts_util.c | 50 +++++++++++++------------------------------- + 2 files changed, 15 insertions(+), 40 deletions(-) + +diff --git a/source3/include/proto.h b/source3/include/proto.h +index a40d3c1..216a377 100644 +--- a/source3/include/proto.h ++++ b/source3/include/proto.h +@@ -981,11 +981,6 @@ void update_trustdom_cache( void ); + + /* The following definitions come from libsmb/trusts_util.c */ + +-NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, +- const char *domain, +- const char *account_name, +- unsigned char orig_trust_passwd_hash[16], +- enum netr_SchannelType sec_channel_type); + NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *domain) ; +diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c +index 8a0e53d..428e0c1 100644 +--- a/source3/libsmb/trusts_util.c ++++ b/source3/libsmb/trusts_util.c +@@ -29,20 +29,27 @@ + + /********************************************************* + Change the domain password on the PDC. +- Store the password ourselves, but use the supplied password +- Caller must have already setup the connection to the NETLOGON pipe ++ Do most of the legwork ourselfs. Caller must have ++ already setup the connection to the NETLOGON pipe + **********************************************************/ + +-NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, +- const char *domain, +- const char *account_name, +- unsigned char orig_trust_passwd_hash[16], +- enum netr_SchannelType sec_channel_type) ++NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, ++ TALLOC_CTX *mem_ctx, ++ const char *domain) + { ++ unsigned char old_trust_passwd_hash[16]; + unsigned char new_trust_passwd_hash[16]; ++ enum netr_SchannelType sec_channel_type = SEC_CHAN_NULL; ++ const char *account_name; + char *new_trust_passwd; + NTSTATUS nt_status; + ++ if (!get_trust_pw_hash(domain, old_trust_passwd_hash, &account_name, ++ &sec_channel_type)) { ++ DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain)); ++ return NT_STATUS_UNSUCCESSFUL; ++ } ++ + switch (sec_channel_type) { + case SEC_CHAN_WKSTA: + case SEC_CHAN_DOMAIN: +@@ -64,7 +71,7 @@ NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *m + + nt_status = rpccli_netlogon_set_trust_password(cli, mem_ctx, + account_name, +- orig_trust_passwd_hash, ++ old_trust_passwd_hash, + new_trust_passwd, + new_trust_passwd_hash, + sec_channel_type); +@@ -108,30 +115,3 @@ NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *m + + return nt_status; + } +- +-/********************************************************* +- Change the domain password on the PDC. +- Do most of the legwork ourselfs. Caller must have +- already setup the connection to the NETLOGON pipe +-**********************************************************/ +- +-NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, +- TALLOC_CTX *mem_ctx, +- const char *domain) +-{ +- unsigned char old_trust_passwd_hash[16]; +- enum netr_SchannelType sec_channel_type = SEC_CHAN_NULL; +- const char *account_name; +- +- if (!get_trust_pw_hash(domain, old_trust_passwd_hash, &account_name, +- &sec_channel_type)) { +- DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain)); +- return NT_STATUS_UNSUCCESSFUL; +- } +- +- return trust_pw_change_and_store_it(cli, mem_ctx, domain, +- account_name, +- old_trust_passwd_hash, +- sec_channel_type); +-} +- +-- +1.9.3 + + +From fdac5d6b0ed96f262830a3a923b9d2a42d7fd98d Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 20 Sep 2013 04:14:00 +0200 +Subject: [PATCH 131/249] s4:librpc: make dcerpc_schannel_key_send/recv static + +Signed-off-by: Stefan Metzmacher +--- + source4/librpc/rpc/dcerpc_schannel.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c +index 130ebeb..cd62508 100644 +--- a/source4/librpc/rpc/dcerpc_schannel.c ++++ b/source4/librpc/rpc/dcerpc_schannel.c +@@ -306,7 +306,7 @@ static void continue_srv_auth2(struct tevent_req *subreq) + Initiate establishing a schannel key using netlogon challenge + on a secondary pipe + */ +-struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, ++static struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, + struct dcerpc_pipe *p, + struct cli_credentials *credentials, + struct loadparm_context *lp_ctx) +@@ -369,7 +369,7 @@ struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, + /* + Receive result of schannel key request + */ +-NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c) ++static NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c) + { + NTSTATUS status = composite_wait(c); + +-- +1.9.3 + + +From de42a3f8b1a69a5abd5fb1a95e1c5f80ee68430e Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 20 Sep 2013 04:16:00 +0200 +Subject: [PATCH 132/249] s4:librpc: let dcerpc_schannel_key_recv() return + netlogon_creds_CredentialState + +cli_credentials_set_netlogon_creds() should only be used directly before +a DCERPC bind in order to pass the session information to the +gensec layer. + +Signed-off-by: Stefan Metzmacher +--- + source4/librpc/rpc/dcerpc_schannel.c | 24 +++++++++++++++--------- + 1 file changed, 15 insertions(+), 9 deletions(-) + +diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c +index cd62508..c4bedfa 100644 +--- a/source4/librpc/rpc/dcerpc_schannel.c ++++ b/source4/librpc/rpc/dcerpc_schannel.c +@@ -296,9 +296,6 @@ static void continue_srv_auth2(struct tevent_req *subreq) + return; + } + +- /* setup current netlogon credentials */ +- cli_credentials_set_netlogon_creds(s->credentials, s->creds); +- + composite_done(c); + } + +@@ -369,10 +366,19 @@ static struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, + /* + Receive result of schannel key request + */ +-static NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c) ++static NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_CredentialState **creds) + { + NTSTATUS status = composite_wait(c); +- ++ ++ if (NT_STATUS_IS_OK(status)) { ++ struct schannel_key_state *s = ++ talloc_get_type_abort(c->private_data, ++ struct schannel_key_state); ++ *creds = talloc_move(mem_ctx, &s->creds); ++ } ++ + talloc_free(c); + return status; + } +@@ -410,13 +416,15 @@ static void continue_schannel_key(struct composite_context *ctx) + NTSTATUS status; + + /* receive schannel key */ +- status = c->status = dcerpc_schannel_key_recv(ctx); ++ status = c->status = dcerpc_schannel_key_recv(ctx, s, &s->creds_state); + if (!composite_is_ok(c)) { + DEBUG(1, ("Failed to setup credentials: %s\n", nt_errstr(status))); + return; + } + + /* send bind auth request with received creds */ ++ cli_credentials_set_netlogon_creds(s->credentials, s->creds_state); ++ + auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table, s->credentials, + lpcfg_gensec_settings(c, s->lp_ctx), + DCERPC_AUTH_TYPE_SCHANNEL, s->auth_level, +@@ -447,9 +455,6 @@ static void continue_bind_auth(struct composite_context *ctx) + &ndr_table_netlogon.syntax_id)) { + ZERO_STRUCT(s->return_auth); + +- s->creds_state = cli_credentials_get_netlogon_creds(s->credentials); +- if (composite_nomem(s->creds_state, c)) return; +- + s->save_creds_state = *s->creds_state; + netlogon_creds_client_authenticator(&s->save_creds_state, &s->auth); + +@@ -528,6 +533,7 @@ static void continue_get_capabilities(struct tevent_req *subreq) + } + + *s->creds_state = s->save_creds_state; ++ cli_credentials_set_netlogon_creds(s->credentials, s->creds_state); + + if (!NT_STATUS_IS_OK(s->c.out.result)) { + composite_error(c, s->c.out.result); +-- +1.9.3 + + +From f6a6e4e91b676461dc8b6dd5abca4120d9bf920a Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 20 Sep 2013 04:33:07 +0200 +Subject: [PATCH 133/249] auth:credentials: avoid talloc_reference in + cli_credentials_set_netlogon_creds() + +Typically cli_credentials_set_netlogon_creds() should be used directly +before the DCERPC bind. And cli_credentials_get_netlogon_creds() +should be only used by the gensec layer, which only needs a copy. + +Signed-off-by: Stefan Metzmacher +--- + auth/credentials/credentials.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c +index 57a7c0b..9ce38d0 100644 +--- a/auth/credentials/credentials.c ++++ b/auth/credentials/credentials.c +@@ -814,7 +814,11 @@ _PUBLIC_ void cli_credentials_guess(struct cli_credentials *cred, + _PUBLIC_ void cli_credentials_set_netlogon_creds(struct cli_credentials *cred, + struct netlogon_creds_CredentialState *netlogon_creds) + { +- cred->netlogon_creds = talloc_reference(cred, netlogon_creds); ++ TALLOC_FREE(cred->netlogon_creds); ++ if (netlogon_creds == NULL) { ++ return; ++ } ++ cred->netlogon_creds = netlogon_creds_copy(cred, netlogon_creds); + } + + /** +-- +1.9.3 + + +From 14b9bb276a798ad71776ebcb698afeeb44aa173a Mon Sep 17 00:00:00 2001 +From: Volker Lendecke +Date: Sat, 9 Nov 2013 19:14:15 +0100 +Subject: [PATCH 134/249] libsmb: Fix CID 1127343 Dead default in switch + +We have checked sec_channel_type a few lines above already + +Signed-off-by: Volker Lendecke +Reviewed-by: Ira Cooper +(cherry picked from commit 1cae867f72b79995a02eed96265fe9f69ce945da) +--- + source3/libsmb/trusts_util.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c +index 428e0c1..52fb481 100644 +--- a/source3/libsmb/trusts_util.c ++++ b/source3/libsmb/trusts_util.c +@@ -108,8 +108,6 @@ NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, + } + break; + } +- default: +- break; + } + } + +-- +1.9.3 + + +From efb32bbe25d534f69aca03e0945220cb5049c366 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 29 Nov 2013 09:46:01 +0100 +Subject: [PATCH 135/249] s3:rpc_server: use make_session_info_guest() directly + +This removes the useless static auth_anonymous_session_info() wrapper. + +auth_anonymous_session_info() is also a public function in source4. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit ae6720117ae5fb3c922486ce46e2b0d51e020301) +--- + source3/rpc_server/rpc_server.c | 22 ++++++---------------- + 1 file changed, 6 insertions(+), 16 deletions(-) + +diff --git a/source3/rpc_server/rpc_server.c b/source3/rpc_server/rpc_server.c +index de54ddc..c3a7f28 100644 +--- a/source3/rpc_server/rpc_server.c ++++ b/source3/rpc_server/rpc_server.c +@@ -37,19 +37,6 @@ + #define SERVER_TCP_LOW_PORT 1024 + #define SERVER_TCP_HIGH_PORT 1300 + +-static NTSTATUS auth_anonymous_session_info(TALLOC_CTX *mem_ctx, +- struct auth_session_info **session_info) +-{ +- NTSTATUS status; +- +- status = make_session_info_guest(mem_ctx, session_info); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- +- return NT_STATUS_OK; +-} +- + /* Creates a pipes_struct and initializes it with the information + * sent from the client */ + static int make_server_pipes_struct(TALLOC_CTX *mem_ctx, +@@ -1067,11 +1054,14 @@ void dcerpc_ncacn_accept(struct tevent_context *ev_ctx, + } + + if (ncacn_conn->session_info == NULL) { +- status = auth_anonymous_session_info(ncacn_conn, +- &ncacn_conn->session_info); ++ /* ++ * TODO: use auth_anonymous_session_info() here? ++ */ ++ status = make_session_info_guest(ncacn_conn, ++ &ncacn_conn->session_info); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(2, ("Failed to create " +- "auth_anonymous_session_info - %s\n", ++ "make_session_info_guest - %s\n", + nt_errstr(status))); + talloc_free(ncacn_conn); + return; +-- +1.9.3 + + +From 215d591403e63b785308ff5d6b2e3c87ad9ee408 Mon Sep 17 00:00:00 2001 +From: Garming Sam +Date: Fri, 29 Nov 2013 16:51:08 +1300 +Subject: [PATCH 136/249] selftest: add new rpc client test + +Pair-programmed-with: Andrew Bartlett + +Signed-off-by: Garming Sam +Signed-off-by: Andrew Bartlett +Reviewed-by: Andrew Bartlett +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 0e46205ff83d137ca486868e4376b258b6dfa1a2) +--- + source3/script/tests/test_rpcclient_samlogon.sh | 27 +++++++++++++++++++++++++ + source3/selftest/tests.py | 2 ++ + 2 files changed, 29 insertions(+) + create mode 100755 source3/script/tests/test_rpcclient_samlogon.sh + +diff --git a/source3/script/tests/test_rpcclient_samlogon.sh b/source3/script/tests/test_rpcclient_samlogon.sh +new file mode 100755 +index 0000000..01af7f8 +--- /dev/null ++++ b/source3/script/tests/test_rpcclient_samlogon.sh +@@ -0,0 +1,27 @@ ++#!/bin/sh ++ ++if [ $# -lt 3 ]; then ++cat < ++EOF ++exit 1; ++fi ++ ++USERNAME="$1" ++PASSWORD="$2" ++shift 2 ++ADDARGS="$*" ++ ++rpcclient_samlogon() ++{ ++ $VALGRIND $BINDIR/rpcclient -U% -c "samlogon $USERNAME $PASSWORD;samlogon $USERNAME $PASSWORD" $@ ++} ++ ++ ++incdir=`dirname $0`/../../../testprogs/blackbox ++. $incdir/subunit.sh ++testit "rpcclient dsenumdomtrusts" $VALGRIND $BINDIR/rpcclient $ADDARGS -U% -c "dsenumdomtrusts" || failed=`expr $failed + 1` ++testit "rpcclient getdcsitecoverage" $VALGRIND $BINDIR/rpcclient $ADDARGS -U% -c "getdcsitecoverage" || failed=`expr $failed + 1` ++testit "rpcclient samlogon" rpcclient_samlogon $ADDARGS || failed=`expr $failed +1` ++ ++testok $0 $failed +diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py +index 85d67d6..f9cc3d1 100755 +--- a/source3/selftest/tests.py ++++ b/source3/selftest/tests.py +@@ -394,6 +394,8 @@ for s in signseal_options: + plantestsuite("samba3.blackbox.rpcclient krb5 ncacn_np with [%s%s%s] " % (a, s, e), "ktest:local", [os.path.join(samba3srcdir, "script/tests/test_rpcclient.sh"), + "$PREFIX/ktest/krb5_ccache-3", binding_string, "-k", configuration]) + ++plantestsuite("samba3.blackbox.rpcclient_samlogon", "s3member:local", [os.path.join(samba3srcdir, "script/tests/test_rpcclient_samlogon.sh"), ++ "$DC_USERNAME", "$DC_PASSWORD", "ncacn_np:$DC_SERVER", configuration]) + + options_list = ["", "-e"] + for options in options_list: +-- +1.9.3 + + +From 05251d449931c29a0bb0c0b8ad194253dc5b66cb Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 29 Nov 2013 08:45:38 +0100 +Subject: [PATCH 137/249] s3:rpcclient: close the connection if setting up the + netlogon secure channel fails + +This is based on a patch from Garming Sam . + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 2fae806550f3355298541a344b217bf810bf92e4) +--- + source3/rpcclient/rpcclient.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c +index cb7b70f..0cbec20 100644 +--- a/source3/rpcclient/rpcclient.c ++++ b/source3/rpcclient/rpcclient.c +@@ -768,6 +768,10 @@ static NTSTATUS do_cmd(struct cli_state *cli, + trust_password, &machine_account, + &sec_channel_type)) + { ++ DEBUG(0, ("Failed to fetch trust password for %s to connect to %s.\n", ++ get_cmdline_auth_info_domain(auth_info), ++ cmd_entry->table->name)); ++ TALLOC_FREE(cmd_entry->rpc_pipe); + talloc_free(mem_ctx); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } +@@ -784,6 +788,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, + if (!NT_STATUS_IS_OK(ntresult)) { + DEBUG(0, ("Could not initialise credentials for %s.\n", + cmd_entry->table->name)); ++ TALLOC_FREE(cmd_entry->rpc_pipe); + talloc_free(mem_ctx); + return ntresult; + } +-- +1.9.3 + + +From 8d3336b9a61a185a4194313fec338321fed6b151 Mon Sep 17 00:00:00 2001 +From: Garming Sam +Date: Mon, 2 Dec 2013 13:20:39 +1300 +Subject: [PATCH 138/249] selftest: add new credential change test + +Signed-off-by: Garming Sam +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 48820b95285f7dffd827143ba56f432f3e283a6f) +--- + source3/script/tests/test_net_cred_change.sh | 16 ++++++++++++++++ + source3/selftest/tests.py | 3 +++ + 2 files changed, 19 insertions(+) + create mode 100755 source3/script/tests/test_net_cred_change.sh + +diff --git a/source3/script/tests/test_net_cred_change.sh b/source3/script/tests/test_net_cred_change.sh +new file mode 100755 +index 0000000..9013d07 +--- /dev/null ++++ b/source3/script/tests/test_net_cred_change.sh +@@ -0,0 +1,16 @@ ++#!/bin/sh ++ ++if [ $# -lt 1 ]; then ++cat < +Date: Mon, 23 Dec 2013 17:12:39 +1300 +Subject: [PATCH 139/249] selftest: add rodc and other env tests for wbinfo + +Pair-programmed-with: Andrew Bartlett +Signed-off-by: Garming Sam +Reviewed-by: Stefan Metzmacher + +Autobuild-User(master): Stefan Metzmacher +Autobuild-Date(master): Mon Dec 23 17:17:39 CET 2013 on sn-devel-104 +(cherry picked from commit 819e1f561df5074ae21db77c6558b34f4b0e1351) +--- + source4/selftest/tests.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py +index e738d1d9..c3a33c7 100755 +--- a/source4/selftest/tests.py ++++ b/source4/selftest/tests.py +@@ -309,8 +309,8 @@ plantestsuite("samba4.blackbox.locktest(dc)", "dc", [os.path.join(samba4srcdir, + plantestsuite("samba4.blackbox.masktest", "dc", [os.path.join(samba4srcdir, "torture/tests/test_masktest.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$DOMAIN', '$PREFIX']) + plantestsuite("samba4.blackbox.gentest(dc)", "dc", [os.path.join(samba4srcdir, "torture/tests/test_gentest.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$DOMAIN', "$PREFIX"]) + plantestsuite("samba4.blackbox.rfc2307_mapping(dc:local)", "dc:local", [os.path.join(samba4srcdir, "../nsswitch/tests/test_rfc2307_mapping.sh"), '$DOMAIN', '$USERNAME', '$PASSWORD', "$SERVER", "$UID_RFC2307TEST", "$GID_RFC2307TEST", configuration]) +-plantestsuite("samba4.blackbox.wbinfo(dc:local)", "dc:local", [os.path.join(samba4srcdir, "../nsswitch/tests/test_wbinfo.sh"), '$DOMAIN', '$USERNAME', '$PASSWORD', "dc"]) +-plantestsuite("samba4.blackbox.wbinfo(s4member:local)", "s4member:local", [os.path.join(samba4srcdir, "../nsswitch/tests/test_wbinfo.sh"), '$DOMAIN', '$DC_USERNAME', '$DC_PASSWORD', "s4member"]) ++for env in ["dc", "s4member", "rodc", "promoted_dc"]: ++ plantestsuite("samba4.blackbox.wbinfo(%s:local)" % env, "%s:local" % env, [os.path.join(samba4srcdir, "../nsswitch/tests/test_wbinfo.sh"), '$DOMAIN', '$DC_USERNAME', '$DC_PASSWORD', env]) + plantestsuite("samba4.blackbox.chgdcpass", "chgdcpass", [os.path.join(bbdir, "test_chgdcpass.sh"), '$SERVER', "CHGDCPASS\$", '$REALM', '$DOMAIN', '$PREFIX', "aes256-cts-hmac-sha1-96", '$SELFTEST_PREFIX/chgdcpass', smbclient4]) + plantestsuite("samba4.blackbox.samba_upgradedns(chgdcpass:local)", "chgdcpass:local", [os.path.join(bbdir, "test_samba_upgradedns.sh"), '$SERVER', '$REALM', '$PREFIX', '$SELFTEST_PREFIX/chgdcpass']) + plantestsuite_loadlist("samba4.rpc.echo against NetBIOS alias", "dc", [valgrindify(smbtorture4), "$LISTOPT", 'ncacn_np:$NETBIOSALIAS', '-U$DOMAIN/$USERNAME%$PASSWORD', 'rpc.echo']) +-- +1.9.3 + + +From 689deff949e8ce9b6aa900e7b0c714d5a025d516 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 17 Dec 2013 19:35:37 +0100 +Subject: [PATCH 140/249] libcli/auth: set the return_authenticator->timestamp + = 0 + +This is what windows returns, the value is ignored by the client anyway. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 202bcf9096e53d94b294936d6144ae77f1536b72) +--- + libcli/auth/credentials.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c +index 1f664d3..197db86 100644 +--- a/libcli/auth/credentials.c ++++ b/libcli/auth/credentials.c +@@ -479,7 +479,7 @@ NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState + netlogon_creds_step(creds); + if (netlogon_creds_server_check_internal(creds, &received_authenticator->cred)) { + return_authenticator->cred = creds->server; +- return_authenticator->timestamp = creds->sequence; ++ return_authenticator->timestamp = 0; + return NT_STATUS_OK; + } else { + ZERO_STRUCTP(return_authenticator); +-- +1.9.3 + + +From fe8a979787c9528bb3b403272be3dc6a313bbebd Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 17 Dec 2013 19:40:15 +0100 +Subject: [PATCH 141/249] libcli/auth: remove bogus comment regarding replay + attacks + +creds->sequence (timestamp) is the value that is used to increment the internal +state, it's not a real sequence number. The sequence comes +from adding all timestamps of the whole session. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 636daac3b7b08ccb8845dab060157918d296ef67) +--- + libcli/auth/credentials.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c +index 197db86..afb4a04 100644 +--- a/libcli/auth/credentials.c ++++ b/libcli/auth/credentials.c +@@ -473,8 +473,6 @@ NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState + return NT_STATUS_ACCESS_DENIED; + } + +- /* TODO: this may allow the a replay attack on a non-signed +- connection. Should we check that this is increasing? */ + creds->sequence = received_authenticator->timestamp; + netlogon_creds_step(creds); + if (netlogon_creds_server_check_internal(creds, &received_authenticator->cred)) { +-- +1.9.3 + + +From 1f6a52bb1f756be05e28dc9e16725ac73b005d00 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 17 Dec 2013 19:55:12 +0100 +Subject: [PATCH 142/249] libcli/auth: try to use the current timestamp + creds->sequence + +If the last usage of netlogon_creds_client_authenticator() +is in the past try to use the current timestamp and increment +more than just 2. + +If we use netlogon_creds_client_authenticator() a lot within a +second, we increment keep incrementing by 2. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett + +Autobuild-User(master): Stefan Metzmacher +Autobuild-Date(master): Tue Dec 24 13:18:18 CET 2013 on sn-devel-104 +(cherry picked from commit e6afeae69537f55ed187b28b60ad29b9e237ec6e) +--- + libcli/auth/credentials.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c +index afb4a04..f52538a 100644 +--- a/libcli/auth/credentials.c ++++ b/libcli/auth/credentials.c +@@ -344,7 +344,29 @@ struct netlogon_creds_CredentialState *netlogon_creds_client_init_session_key(TA + void netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState *creds, + struct netr_Authenticator *next) + { ++ uint32_t t32n = (uint32_t)time(NULL); ++ ++ /* ++ * we always increment and ignore an overflow here ++ */ + creds->sequence += 2; ++ ++ if (t32n > creds->sequence) { ++ /* ++ * we may increment more ++ */ ++ creds->sequence = t32n; ++ } else { ++ uint32_t d = creds->sequence - t32n; ++ ++ if (d >= INT32_MAX) { ++ /* ++ * got an overflow of time_t vs. uint32_t ++ */ ++ creds->sequence = t32n; ++ } ++ } ++ + netlogon_creds_step(creds); + + next->cred = creds->client; +-- +1.9.3 + + +From 1cc32f5bf176a6daba93603a5b9aa4fc4fe42479 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 3 Jan 2014 12:56:38 +0100 +Subject: [PATCH 143/249] s4:selftest: run wbinfo tests at the end... + +This avoids flakey crashes in the promoted_dc environment. + +See the examples below, we had up to 50% of the daily build failing... + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett + +https://git.samba.org/autobuild.flakey/2013-12-23-1942/samba.stdout + + [1586/1594 in 1h39m20s] samba4.drs.fsmo.python(promoted_dc) + Testing for schema role transfer from localdc.samba.example.com to PROMOTEDVDC.samba.example.com + FSMO transfer of 'schema' role successful + Testing for schema role transfer from PROMOTEDVDC.samba.example.com to localdc.samba.example.com + ERROR: Failed to initiate transfer of 'schema' role: LDAP error 52 LDAP_UNAVAILABLE - <> + UNEXPECTED(failure): samba4.drs.fsmo.python(promoted_dc).fsmo.DrsFsmoTestCase.test_SchemaMasterTransfer(promoted_dc) + REASON: _StringException: _StringException: Content-Type: text/x-traceback;charset=utf8,language=python + traceback + 380 + +https://git.samba.org/autobuild.flakey/2013-12-24-1546/samba.stdout + + [1583/1594 in 1h36m4s] samba.tests.blackbox.samba_tool_drs + ERROR: Testsuite[samba.tests.blackbox.samba_tool_drs] + REASON: unable to set up environment promoted_dc - exiting + +https://git.samba.org/autobuild.flakey/2013-12-24-1546/samba.stderr + + Unable to convert 1.2.840.86419.1.5.9939 to an attid, and can_change_pfm=false! + Unable to convert governsID on CN=test-class30318,CN=Schema,CN=Configuration,DC=samba,DC=example,DC=com to DRS object - WERR_NOT_FOUND + ../source4/rpc_server/drsuapi/getncchanges.c:1646: DsGetNCChanges 2nd replication on different DN CN=Configuration,DC=samba,DC=example,DC=com CN=Schema,CN=Configuration,DC=samba,DC=example,DC=com (last_dn CN=Schema,CN=Configuration,DC=samba,DC=example,DC=com) + =============================================================== + INTERNAL ERROR: Signal 11 in pid 884274 (4.2.0pre1-DEVELOPERBUILD) + Please read the Trouble-Shooting section of the Samba HOWTO + =============================================================== + smb_panic(): calling panic action [/memdisk/autobuild/fl/b302436/samba/selftest/gdb_backtrace 884274] + [Thread debugging using libthread_db enabled] + 0x00002af6b5c1977e in __libc_waitpid (pid=, + stat_loc=0x7fff67c7709c, options=) + at ../sysdeps/unix/sysv/linux/waitpid.c:32 + 32 ../sysdeps/unix/sysv/linux/waitpid.c: No such file or directory. + in ../sysdeps/unix/sysv/linux/waitpid.c + #0 0x00002af6b5c1977e in __libc_waitpid (pid=, + stat_loc=0x7fff67c7709c, options=) + at ../sysdeps/unix/sysv/linux/waitpid.c:32 + oldtype = + result = + #1 0x00002af6b5baeb39 in do_system (line=) + at ../sysdeps/posix/system.c:149 + __result = -512 + _buffer = {__routine = 0x2af6b5baee90 , + __arg = 0x7fff67c77098, __canceltype = 0, __prev = 0x0} + _avail = 1 + status = + save = + pid = 886733 + sa = {__sigaction_handler = {sa_handler = 0x1, sa_sigaction = 0x1}, + sa_mask = {__val = {65536, 0 }}, sa_flags = 0, + sa_restorer = 0x2af6b5b730f0} + omask = {__val = {7808, 4294967295, 140734934511616, 1, 2195512, 0, + 0, 0, 47239032274944, 47239027992529, 140733193388033, 0, 0, + 47239099003120, 140734934511792, 47239558787328}} + #2 0x00002af6b311821f in smb_panic_default ( + why=0x2af6b312a875 "internal error") at ../lib/util/fault.c:134 + result = 32767 + pidstr = "884274\000\000\001\375\376\320\366*\000\000\260\377\377\377" + cmdstring = "/memdisk/autobuild/fl/b302436/samba/selftest/gdb_backtrace 884274\000\307g\377\177\000\000\001\000\000\000\000\000\000\000\320\301#", '\000' "\240, \017\263\366*\000\000\321\247{\261\366*\000\000\001\000\000\000\005", '\000' "\260, \016\v\321\366*\000\000X\351\017\263\366*\000\000\260q\307g\377\177\000\000\000\361\036\321\366*\000\000\020r\307g\377\177\000\000\240\301z\326\366*\000\000\000Z\304\320\366*\000" + __FUNCTION__ = "smb_panic_default" + #3 0x00002af6b31183b5 in smb_panic (why=0x2af6b312a875 "internal error") + at ../lib/util/fault.c:162 + No locals. + #4 0x00002af6b311809f in fault_report (sig=11) at ../lib/util/fault.c:77 + counter = 1 + __FUNCTION__ = "fault_report" + #5 0x00002af6b31180b4 in sig_fault (sig=11) at ../lib/util/fault.c:88 + No locals. + #6 + No symbol table info available. + #7 0x00002af6cabef930 in replmd_check_urgent_objectclass ( + objectclass_el=0x0, situation=REPL_URGENT_ON_UPDATE) + at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:205 + i = 2 + j = 0 + #8 0x00002af6cabf29b6 in replmd_update_rpmd (module=0x2af6b17f2c20, + schema=0x2af6d05e5570, req=0x2af6d05e8ad0, rename_attrs=0x0, + msg=0x2af6d11ef100, seq_num=0x2af6d0c315b8, t=1387895162, + is_urgent=0x7fff67c778bf, rodc=0x7fff67c778be) + at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:1432 + omd_value = 0x7fff67c77810 + ndr_err = 3508465920 + omd = {version = 1741125552, reserved = 32767, ctr = {ctr1 = { + count = 3008684740, reserved = 10998, array = 0x7fff67c777b0}}} + i = 10998 + now = 130323687620000000 + our_invocation_id = 0x2af6d1796390 + ret = 0 + attrs = 0x7fff67c77750 + attrs1 = {0x2af6cabff775 "replPropertyMetaData", 0x2af6cabffc8b "*", + 0x0} + attrs2 = {0x2af6cabff76a "uSNChanged", 0x2af6cabffa98 "objectClass", + 0x2af6cabffc8d "instanceType", 0x0} + res = 0x2af6d10b0eb0 + ldb = 0x2af6b17f2470 + objectclass_el = 0x0 + situation = REPL_URGENT_ON_UPDATE + rmd_is_provided = false + __FUNCTION__ = "replmd_update_rpmd" + #9 0x00002af6cabf5a06 in replmd_modify (module=0x2af6b17f2c20, + req=0x2af6d05e8ad0) + at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:2455 + msds_intid_struct = 0x2af6d05e8ad0 + ldb = 0x2af6b17f2470 + ac = 0x2af6d0c31580 + down_req = 0x2af6d0e6a100 + msg = 0x2af6d11ef100 + t = 1387895162 + ret = 1741125936 + is_urgent = false + rodc = false + functional_level = 3 + guid_blob = 0x0 + sd_propagation_control = 0x0 + #10 0x00002af6bf69f94d in dsdb_module_modify (module=0x2af6b17f2c20, + message=0x2af6d1183fe0, dsdb_flags=4194304, parent=0x2af6ce6ea980) + at ../source4/dsdb/samdb/ldb_modules/util.c:460 + ops = 0x2af6cae06b40 + mod_req = 0x2af6d05e8ad0 + ret = 0 + ldb = 0x2af6b17f2470 + tmp_ctx = 0x2af6d0ed62f0 + res = 0x2af6d0e6a100 + __FUNCTION__ = "dsdb_module_modify" + #11 0x00002af6cabf7ebc in replmd_delete_internals (module=0x2af6b17f2c20, + req=0x2af6ce6ea980, re_delete=true) + at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:3309 + ret = 0 + retb = true + disallow_move_on_delete = false + old_dn = 0x2af6d6a2a010 + new_dn = 0x2af6d0794a90 + rdn_name = 0x2af6d0885c10 "CN" + rdn_value = 0x2af6d10d7368 + new_rdn_value = 0x2af6d0c45a00 + guid = {time_low = 48, time_mid = 0, time_hi_and_version = 0, + clock_seq = "\200\251", node = "n\316\366*\000"} + ldb = 0x2af6b17f2470 + schema = 0x2af6d05e5570 + msg = 0x2af6d1183fe0 + old_msg = 0x2af6d1902800 + el = 0x2af6d0874900 + tmp_ctx = 0x2af6d0b77560 + res = 0x2af6d0d57980 + parent_res = 0x30 + preserved_attrs = {0x2af6cac00fe1 "nTSecurityDescriptor", + 0x2af6cac055c3 "attributeID", 0x2af6cac055cf "attributeSyntax", + 0x2af6cac055df "dNReferenceUpdate", 0x2af6cac055f1 "dNSHostName", + 0x2af6cac055fd "flatName", 0x2af6cac05606 "governsID", + 0x2af6cac05610 "groupType", 0x2af6cabffc8d "instanceType", + 0x2af6cac0561a "lDAPDisplayName", + 0x2af6cac0562a "legacyExchangeDN", 0x2af6cabfe94d "isDeleted", + 0x2af6cabfe957 "isRecycled", 0x2af6cac020f8 "lastKnownParent", + 0x2af6cac021e8 "msDS-LastKnownRDN", + 0x2af6cac0563b "mS-DS-CreatorSID", 0x2af6cac0564c "mSMQOwnerID", + 0x2af6cac05658 "nCName", 0x2af6cabffa98 "objectClass", + 0x2af6cac0565f "distinguishedName", 0x2af6cabff5b5 "objectGUID", + 0x2af6cac05671 "objectSid", 0x2af6cac0567b "oMSyntax", + 0x2af6cac05684 "proxiedObjectName", 0x2af6cac014d8 "name", + 0x2af6cabff775 "replPropertyMetaData", + 0x2af6cac05696 "sAMAccountName", + 0x2af6cac056a5 "securityIdentifier", 0x2af6cac056b8 "sIDHistory", + 0x2af6cac056c3 "subClassOf", 0x2af6cac01ba8 "systemFlags", + 0x2af6cac056ce "trustPartner", 0x2af6cac056db "trustDirection", + 0x2af6cac056ea "trustType", 0x2af6cac056f4 "trustAttributes", + 0x2af6cabfe9b8 "userAccountControl", 0x2af6cabff76a "uSNChanged", + 0x2af6cabff75f "uSNCreated", 0x2af6cabff747 "whenCreated", + 0x2af6cabff753 "whenChanged", 0x0} + i = 12 + el_count = 1 + deletion_state = OBJECT_TOMBSTONE + next_deletion_state = OBJECT_TOMBSTONE + __FUNCTION__ = "replmd_delete_internals" + #12 0x00002af6cabfbbe3 in replmd_replicated_apply_isDeleted ( + ar=0x2af6d74c0b40) + at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:4718 + del_req = 0x2af6ce6ea980 + res = 0x2af6d0cdebf0 + tmp_ctx = 0x2af6d0949230 + deleted_objects_dn = 0x2af6d1a49f00 + msg = 0x2af6d0a39620 + ret = 0 + #13 0x00002af6cabf0766 in replmd_op_callback (req=0x2af6d05a21e0, + ares=0x2af6d0d715c0) + at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:526 + ret = 10998 + ac = 0x2af6d74c0b40 + replmd_private = 0x2af6b188c7c0 + modified_partition = 0x2af6d141b670 + partition_ctrl = 0x2af6d1905f40 + partition = 0x2af6ce6bdbe0 + controls = 0x0 + __FUNCTION__ = "replmd_op_callback" + #14 0x00002af6b1df7ca2 in ldb_module_done (req=0x2af6d05a21e0, + ctrls=0x2af6d1629aa0, response=0x0, error=0) + at ../lib/ldb/common/ldb_modules.c:832 + ares = 0x2af6d0d715c0 + #15 0x00002af6cabf896b in replmd_op_possible_conflict_callback ( + req=0x2af6d05a21e0, ares=0x2af6b1883eb0, + callback=0x2af6cabf0334 ) + at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:3606 + conflict_dn = 0x2af6cac03470 + ar = 0x2af6d74c0b40 + res = 0x2af6b354f89b + attrs = {0x2af6cabff775 "replPropertyMetaData", + 0x2af6cabff5b5 "objectGUID", 0x0} + ret = -682882240 + omd_value = 0x7fff67c77e20 + omd = {version = 1741127104, reserved = 32767, ctr = {ctr1 = { + count = 0, reserved = 0, array = 0x28}}} + rmd = 0x2af6d74c0ae0 + ndr_err = 10998 + rename_incoming_record = false + rodc = false + rmd_name = 0x7fff67c77e10 + omd_name = 0x2af6d74c0b40 + msg = 0x2af6b1883e50 + __FUNCTION__ = "replmd_op_possible_conflict_callback" + #16 0x00002af6cabf93fb in replmd_op_add_callback (req=0x2af6d05a21e0, + ares=0x2af6b1883eb0) + at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:3802 + ar = 0x2af6d74c0b40 + #17 0x00002af6b1df7ca2 in ldb_module_done (req=0x2af6d05a21e0, + ctrls=0x2af6d1629aa0, response=0x0, error=0) + at ../lib/ldb/common/ldb_modules.c:832 + ares = 0x2af6b1883eb0 + #18 0x00002af6ca3c8b6a in partition_req_callback (req=0x2af6d087a1e0, + ares=0x2af6d05a1fa0) at ../source4/dsdb/samdb/ldb_modules/partition.c:213 + ac = 0x2af6d0949370 + module = 0x2af6cd27bf12 + nreq = 0x2af6d05b67b0 + ret = 0 + partition_ctrl = 0x2af6d0d71740 + #19 0x00002af6cd2752ab in ltdb_request_done (ctx=0x2af6d1cd7ed0, error=0) + at ../lib/ldb/ldb_tdb/ldb_tdb.c:1280 + ldb = 0x2af6b17f2470 + req = 0x2af6d087a1e0 + ares = 0x2af6d05a1fa0 + #20 0x00002af6cd275597 in ltdb_callback (ev=0x2af6b17ef8c0, + te=0x2af6d17f75d0, t=..., private_data=0x2af6d1cd7ed0) + at ../lib/ldb/ldb_tdb/ldb_tdb.c:1390 + ctx = 0x2af6d1cd7ed0 + ret = 0 + #21 0x00002af6b3343259 in tevent_common_loop_timer_delay (ev=0x2af6b17ef8c0) + at ../lib/tevent/tevent_timed.c:341 + current_time = {tv_sec = 0, tv_usec = 0} + te = 0x2af6d17f75d0 + #22 0x00002af6b334558a in epoll_event_loop_once (ev=0x2af6b17ef8c0, + location=0x2af6b1e1eef8 "../lib/ldb/common/ldb.c:621") + at ../lib/tevent/tevent_epoll.c:912 + epoll_ev = 0x2af6b17efb00 + tval = {tv_sec = 47239056876603, tv_usec = 47239028210096} + panic_triggered = false + #23 0x00002af6b3342363 in std_event_loop_once (ev=0x2af6b17ef8c0, + location=0x2af6b1e1eef8 "../lib/ldb/common/ldb.c:621") + at ../lib/tevent/tevent_standard.c:112 + glue_ptr = 0x2af6b17ef9b0 + glue = 0x2af6b17ef9b0 + ret = 10998 + #24 0x00002af6b333c799 in _tevent_loop_once (ev=0x2af6b17ef8c0, + location=0x2af6b1e1eef8 "../lib/ldb/common/ldb.c:621") + at ../lib/tevent/tevent.c:530 + ret = 0 + nesting_stack_ptr = 0x0 + #25 0x00002af6b1e154c4 in ldb_wait (handle=0x2af6d67624c0, type=LDB_WAIT_ALL) + at ../lib/ldb/common/ldb.c:621 + ev = 0x2af6b17ef8c0 + ret = 0 + #26 0x00002af6b1e1786b in ldb_extended (ldb=0x2af6b17f2470, + oid=0x2af6b4c4f9ce "1.3.6.1.4.1.7165.4.4.1", data=0x2af6d0e2bc60, + _res=0x7fff67c78240) at ../lib/ldb/common/ldb.c:1506 + req = 0x2af6d0c45a00 + ret = 0 + res = 0x2af6d69238f0 + #27 0x00002af6b4c4a0d6 in dsdb_replicated_objects_commit (ldb=0x2af6b17f2470, + working_schema=0x0, objects=0x2af6d0e2bc60, notify_uSN=0x2af6d14a65f0) + at ../source4/dsdb/repl/replicated_objects.c:773 + werr = {w = 0} + ext_res = 0x0 + cur_schema = 0x0 + new_schema = 0x0 + ret = 0 + seq_num1 = 5554 + seq_num2 = 47239626746464 + used_global_schema = false + tmp_ctx = 0x2af6d03c5860 + __FUNCTION__ = "dsdb_replicated_objects_commit" + #28 0x00002af6c1c6babb in dreplsrv_op_pull_source_apply_changes_trigger ( + req=0x2af6d17daed0, r=0x2af6d17db0d0, ctr_level=6, ctr1=0x0, + ctr6=0x2af6d1b02bb0) at ../source4/dsdb/repl/drepl_out_helpers.c:717 + state = 0x2af6d17db050 + rf1 = {blobsize = 274, consecutive_sync_failures = 0, + last_success = 130323684670000000, + last_attempt = 130323687610000000, result_last_attempt = {w = 0}, + other_info = 0x2af6d0949910, other_info_length = 66, + replica_flags = 112, schedule = '\021' , + reserved = 0, highwatermark = {tmp_highest_usn = 12398, + reserved_usn = 0, highest_usn = 12398}, source_dsa_obj_guid = { + time_low = 984092159, time_mid = 850, + time_hi_and_version = 18870, clock_seq = "\251X", + node = "UF\324\223\205\241"}, source_dsa_invocation_id = { + time_low = 1460694408, time_mid = 52035, + time_hi_and_version = 18738, clock_seq = "\204}", + node = "\264\365\276\372\256\303"}, transport_guid = { + time_low = 0, time_mid = 0, time_hi_and_version = 0, + clock_seq = "\000", node = "\000\000\000\000\000"}} + service = 0x2af6d0ff6b00 + partition = 0x2af6d0b6f220 + drsuapi = 0x2af6d1c8d480 + schema = 0x2af6d05e5570 + working_schema = 0x0 + mapping_ctr = 0x2af6d1b02c10 + object_count = 50 + first_object = 0x2af6d0571800 + linked_attributes_count = 0 + linked_attributes = 0x2af6d5212140 + uptodateness_vector = 0x2af6d1a741c0 + objects = 0x2af6d0e2bc60 + more_data = false + status = {w = 0} + nt_status = {v = 3006553120} + dsdb_repl_flags = 0 + __FUNCTION__ = "dreplsrv_op_pull_source_apply_changes_trigger" + #29 0x00002af6c1c6b3e7 in dreplsrv_op_pull_source_get_changes_done ( + subreq=0x0) at ../source4/dsdb/repl/drepl_out_helpers.c:599 + req = 0x2af6d17daed0 + state = 0x2af6d17db050 + status = {v = 0} + r = 0x2af6d17db0d0 + ctr_level = 6 + ctr1 = 0x0 + ctr6 = 0x2af6d1b02bb0 + extended_ret = DRSUAPI_EXOP_ERR_NONE + #30 0x00002af6b333e2f8 in _tevent_req_notify_callback (req=0x2af6d1a73f70, + location=0x2af6c1c7d5f8 "default/librpc/gen_ndr/ndr_drsuapi_c.c:712") + at ../lib/tevent/tevent_req.c:102 + No locals. + #31 0x00002af6b333e34d in tevent_req_finish (req=0x2af6d1a73f70, + state=TEVENT_REQ_DONE, + location=0x2af6c1c7d5f8 "default/librpc/gen_ndr/ndr_drsuapi_c.c:712") + at ../lib/tevent/tevent_req.c:117 + No locals. + #32 0x00002af6b333e374 in _tevent_req_done (req=0x2af6d1a73f70, + location=0x2af6c1c7d5f8 "default/librpc/gen_ndr/ndr_drsuapi_c.c:712") + at ../lib/tevent/tevent_req.c:123 + No locals. + #33 0x00002af6c1c708df in dcerpc_drsuapi_DsGetNCChanges_r_done ( + subreq=0x2af6d122f4c0) at default/librpc/gen_ndr/ndr_drsuapi_c.c:712 + req = 0x2af6d1a73f70 + status = {v = 0} + #34 0x00002af6b333e2f8 in _tevent_req_notify_callback (req=0x2af6d122f4c0, + location=0x2af6b575b688 "../librpc/rpc/binding_handle.c:517") + at ../lib/tevent/tevent_req.c:102 + No locals. + #35 0x00002af6b333e34d in tevent_req_finish (req=0x2af6d122f4c0, + state=TEVENT_REQ_DONE, + location=0x2af6b575b688 "../librpc/rpc/binding_handle.c:517") + at ../lib/tevent/tevent_req.c:117 + No locals. + #36 0x00002af6b333e374 in _tevent_req_done (req=0x2af6d122f4c0, + location=0x2af6b575b688 "../librpc/rpc/binding_handle.c:517") + at ../lib/tevent/tevent_req.c:123 + No locals. + #37 0x00002af6b5757ede in dcerpc_binding_handle_call_done (subreq=0x0) + at ../librpc/rpc/binding_handle.c:517 + req = 0x2af6d122f4c0 + state = 0x2af6d122f640 + h = 0x2af6d0959d10 + error = {v = 0} + out_flags = 0 + ndr_err = NDR_ERR_SUCCESS + #38 0x00002af6b333e2f8 in _tevent_req_notify_callback (req=0x2af6d522f7a0, + location=0x2af6b575b1d0 "../librpc/rpc/binding_handle.c:188") + at ../lib/tevent/tevent_req.c:102 + No locals. + #39 0x00002af6b333e34d in tevent_req_finish (req=0x2af6d522f7a0, + state=TEVENT_REQ_DONE, + location=0x2af6b575b1d0 "../librpc/rpc/binding_handle.c:188") + at ../lib/tevent/tevent_req.c:117 + No locals. + #40 0x00002af6b333e374 in _tevent_req_done (req=0x2af6d522f7a0, + location=0x2af6b575b1d0 "../librpc/rpc/binding_handle.c:188") + at ../lib/tevent/tevent_req.c:123 + No locals. + #41 0x00002af6b5757398 in dcerpc_binding_handle_raw_call_done (subreq=0x0) + at ../librpc/rpc/binding_handle.c:188 + req = 0x2af6d522f7a0 + state = 0x2af6d522f920 + error = {v = 0} + #42 0x00002af6b333e2f8 in _tevent_req_notify_callback (req=0x2af6d0712430, + location=0x2af6b44b8810 "../source4/librpc/rpc/dcerpc.c:322") + at ../lib/tevent/tevent_req.c:102 + No locals. + #43 0x00002af6b333e34d in tevent_req_finish (req=0x2af6d0712430, + state=TEVENT_REQ_DONE, + location=0x2af6b44b8810 "../source4/librpc/rpc/dcerpc.c:322") + at ../lib/tevent/tevent_req.c:117 + No locals. + #44 0x00002af6b333e472 in tevent_req_trigger (ev=0x2af6b17ef8c0, + im=0x2af6d0712500, private_data=0x2af6d0712430) + at ../lib/tevent/tevent_req.c:174 + req = 0x2af6d0712430 + #45 0x00002af6b333d6d4 in tevent_common_loop_immediate (ev=0x2af6b17ef8c0) + at ../lib/tevent/tevent_immediate.c:135 + im = 0x2af6d0712500 + handler = 0x2af6b333e423 + private_data = 0x2af6d0712430 + #46 0x00002af6b3345570 in epoll_event_loop_once (ev=0x2af6b17ef8c0, + location=0x2af6b15a7b9f "../source4/smbd/server.c:503") + at ../lib/tevent/tevent_epoll.c:907 + epoll_ev = 0x2af6b17efb00 + tval = {tv_sec = 47239056876603, tv_usec = 47239028210096} + panic_triggered = false + #47 0x00002af6b3342363 in std_event_loop_once (ev=0x2af6b17ef8c0, + location=0x2af6b15a7b9f "../source4/smbd/server.c:503") + at ../lib/tevent/tevent_standard.c:112 + glue_ptr = 0x2af6b17ef9b0 + glue = 0x2af6b17ef9b0 + ret = 10998 + #48 0x00002af6b333c799 in _tevent_loop_once (ev=0x2af6b17ef8c0, + location=0x2af6b15a7b9f "../source4/smbd/server.c:503") + at ../lib/tevent/tevent.c:530 + ret = 0 + nesting_stack_ptr = 0x0 + #49 0x00002af6b333ca11 in tevent_common_loop_wait (ev=0x2af6b17ef8c0, + location=0x2af6b15a7b9f "../source4/smbd/server.c:503") + at ../lib/tevent/tevent.c:634 + ret = 0 + #50 0x00002af6b3342405 in std_event_loop_wait (ev=0x2af6b17ef8c0, + location=0x2af6b15a7b9f "../source4/smbd/server.c:503") + at ../lib/tevent/tevent_standard.c:138 + glue_ptr = 0x2af6b17ef9b0 + glue = 0x2af6b17ef9b0 + ret = 10998 + #51 0x00002af6b333cadc in _tevent_loop_wait (ev=0x2af6b17ef8c0, + location=0x2af6b15a7b9f "../source4/smbd/server.c:503") + at ../lib/tevent/tevent.c:653 + No locals. + #52 0x00002af6b15a37bc in binary_smbd_main ( + binary_name=0x2af6b15a737b "samba", argc=6, argv=0x7fff67c78de8) + at ../source4/smbd/server.c:503 + opt_daemon = false + opt_interactive = true + opt = -1 + pc = 0x2af6b17d5040 + static_init = {0x2af6b2ac7d8c , + 0x2af6b2aca9e7 , 0} + shared_init = 0x2af6b18143b0 + event_ctx = 0x2af6b17ef8c0 + stdin_event_flags = 1 + status = {v = 0} + model = 0x2af6b17d5b90 "single" + max_runtime = 7500 + +Autobuild-User(master): Andrew Bartlett +Autobuild-Date(master): Mon Jan 6 01:16:13 CET 2014 on sn-devel-104 +(cherry picked from commit 056008df62cb66090b3e30cb09c0edacfbdb5720) +--- + source4/selftest/tests.py | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py +index c3a33c7..9567a8e 100755 +--- a/source4/selftest/tests.py ++++ b/source4/selftest/tests.py +@@ -309,8 +309,6 @@ plantestsuite("samba4.blackbox.locktest(dc)", "dc", [os.path.join(samba4srcdir, + plantestsuite("samba4.blackbox.masktest", "dc", [os.path.join(samba4srcdir, "torture/tests/test_masktest.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$DOMAIN', '$PREFIX']) + plantestsuite("samba4.blackbox.gentest(dc)", "dc", [os.path.join(samba4srcdir, "torture/tests/test_gentest.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$DOMAIN', "$PREFIX"]) + plantestsuite("samba4.blackbox.rfc2307_mapping(dc:local)", "dc:local", [os.path.join(samba4srcdir, "../nsswitch/tests/test_rfc2307_mapping.sh"), '$DOMAIN', '$USERNAME', '$PASSWORD', "$SERVER", "$UID_RFC2307TEST", "$GID_RFC2307TEST", configuration]) +-for env in ["dc", "s4member", "rodc", "promoted_dc"]: +- plantestsuite("samba4.blackbox.wbinfo(%s:local)" % env, "%s:local" % env, [os.path.join(samba4srcdir, "../nsswitch/tests/test_wbinfo.sh"), '$DOMAIN', '$DC_USERNAME', '$DC_PASSWORD', env]) + plantestsuite("samba4.blackbox.chgdcpass", "chgdcpass", [os.path.join(bbdir, "test_chgdcpass.sh"), '$SERVER', "CHGDCPASS\$", '$REALM', '$DOMAIN', '$PREFIX', "aes256-cts-hmac-sha1-96", '$SELFTEST_PREFIX/chgdcpass', smbclient4]) + plantestsuite("samba4.blackbox.samba_upgradedns(chgdcpass:local)", "chgdcpass:local", [os.path.join(bbdir, "test_samba_upgradedns.sh"), '$SERVER', '$REALM', '$PREFIX', '$SELFTEST_PREFIX/chgdcpass']) + plantestsuite_loadlist("samba4.rpc.echo against NetBIOS alias", "dc", [valgrindify(smbtorture4), "$LISTOPT", 'ncacn_np:$NETBIOSALIAS', '-U$DOMAIN/$USERNAME%$PASSWORD', 'rpc.echo']) +@@ -502,6 +500,10 @@ for env in ['vampire_dc', 'promoted_dc']: + extra_args=['-U$DOMAIN/$DC_USERNAME%$DC_PASSWORD']) + + plantestsuite("samba4.blackbox.samba_tool_demote(%s)" % env, env, [os.path.join(samba4srcdir, "utils/tests/test_demote.sh"), '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$DOMAIN', '$DC_SERVER', '$PREFIX/%s' % env, smbclient4]) ++ ++for env in ["dc", "s4member", "rodc", "promoted_dc"]: ++ plantestsuite("samba4.blackbox.wbinfo(%s:local)" % env, "%s:local" % env, [os.path.join(samba4srcdir, "../nsswitch/tests/test_wbinfo.sh"), '$DOMAIN', '$DC_USERNAME', '$DC_PASSWORD', env]) ++ + # TODO: Verifying the databases really should be a part of the + # environment teardown. + # check the databases are all OK. PLEASE LEAVE THIS AS THE LAST TEST +-- +1.9.3 + + +From 3e44e7485dbfea37cb84034c4d13c96059bd9687 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 3 Jan 2014 08:35:27 +0100 +Subject: [PATCH 144/249] s4:librpc: always try to negotiate + DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN + +If the gensec backend supports it there's no reason not sign the header. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 7db1dc13b0149441a2beebca65b75f6e11af13a3) +--- + librpc/rpc/binding.c | 1 - + librpc/rpc/rpc_common.h | 5 ++++- + source4/librpc/rpc/dcerpc.c | 12 ++---------- + source4/librpc/rpc/dcerpc_auth.c | 14 ++++++++++---- + 4 files changed, 16 insertions(+), 16 deletions(-) + +diff --git a/librpc/rpc/binding.c b/librpc/rpc/binding.c +index 49651e8..52122cf 100644 +--- a/librpc/rpc/binding.c ++++ b/librpc/rpc/binding.c +@@ -88,7 +88,6 @@ static const struct { + {"padcheck", DCERPC_DEBUG_PAD_CHECK}, + {"bigendian", DCERPC_PUSH_BIGENDIAN}, + {"smb2", DCERPC_SMB2}, +- {"hdrsign", DCERPC_HEADER_SIGNING}, + {"ndr64", DCERPC_NDR64}, + {"localaddress", DCERPC_LOCALADDRESS} + }; +diff --git a/librpc/rpc/rpc_common.h b/librpc/rpc/rpc_common.h +index 978229e..93d3bb4 100644 +--- a/librpc/rpc/rpc_common.h ++++ b/librpc/rpc/rpc_common.h +@@ -98,7 +98,7 @@ struct dcerpc_binding { + /* this triggers the DCERPC_PFC_FLAG_CONC_MPX flag in the bind request */ + #define DCERPC_CONCURRENT_MULTIPLEX (1<<19) + +-/* this triggers the DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN flag in the bind request */ ++/* this indicates DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN flag was negotiated */ + #define DCERPC_HEADER_SIGNING (1<<20) + + /* use NDR64 transport */ +@@ -113,6 +113,9 @@ struct dcerpc_binding { + /* use aes schannel with hmac-sh256 session key */ + #define DCERPC_SCHANNEL_AES (1<<24) + ++/* this triggers the DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN flag in the bind request */ ++#define DCERPC_PROPOSE_HEADER_SIGNING (1<<25) ++ + /* The following definitions come from ../librpc/rpc/dcerpc_error.c */ + + const char *dcerpc_errstr(TALLOC_CTX *mem_ctx, uint32_t fault_code); +diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c +index 56b821e..2f6c8dd 100644 +--- a/source4/librpc/rpc/dcerpc.c ++++ b/source4/librpc/rpc/dcerpc.c +@@ -1162,7 +1162,7 @@ struct tevent_req *dcerpc_bind_send(TALLOC_CTX *mem_ctx, + pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX; + } + +- if (p->binding->flags & DCERPC_HEADER_SIGNING) { ++ if (p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) { + pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; + } + +@@ -1304,7 +1304,7 @@ static void dcerpc_bind_recv_handler(struct rpc_request *subreq, + conn->flags |= DCERPC_CONCURRENT_MULTIPLEX; + } + +- if ((state->p->binding->flags & DCERPC_HEADER_SIGNING) && ++ if ((conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) && + (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) { + conn->flags |= DCERPC_HEADER_SIGNING; + } +@@ -1352,10 +1352,6 @@ NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p, + pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX; + } + +- if (p->binding->flags & DCERPC_HEADER_SIGNING) { +- pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; +- } +- + /* construct the NDR form of the packet */ + status = ncacn_push_auth(&blob, mem_ctx, + &pkt, +@@ -2046,10 +2042,6 @@ struct tevent_req *dcerpc_alter_context_send(TALLOC_CTX *mem_ctx, + pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX; + } + +- if (p->binding->flags & DCERPC_HEADER_SIGNING) { +- pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; +- } +- + pkt.u.alter.max_xmit_frag = 5840; + pkt.u.alter.max_recv_frag = 5840; + pkt.u.alter.assoc_group_id = p->binding->assoc_group_id; +diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c +index d5e5620..9a5d04d 100644 +--- a/source4/librpc/rpc/dcerpc_auth.c ++++ b/source4/librpc/rpc/dcerpc_auth.c +@@ -173,10 +173,6 @@ static void bind_auth_next_step(struct composite_context *c) + + if (!composite_is_ok(c)) return; + +- if (state->pipe->conn->flags & DCERPC_HEADER_SIGNING) { +- gensec_want_feature(sec->generic_state, GENSEC_FEATURE_SIGN_PKT_HEADER); +- } +- + if (state->credentials.length == 0) { + composite_done(c); + return; +@@ -234,6 +230,12 @@ static void bind_auth_recv_bindreply(struct tevent_req *subreq) + TALLOC_FREE(subreq); + if (!composite_is_ok(c)) return; + ++ if (state->pipe->conn->flags & DCERPC_HEADER_SIGNING) { ++ struct dcecli_security *sec = &state->pipe->conn->security_state; ++ ++ gensec_want_feature(sec->generic_state, GENSEC_FEATURE_SIGN_PKT_HEADER); ++ } ++ + if (!state->more_processing) { + /* The first gensec_update has not requested a second run, so + * we're done here. */ +@@ -395,6 +397,10 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx, + + sec->auth_info->credentials = state->credentials; + ++ if (gensec_have_feature(sec->generic_state, GENSEC_FEATURE_SIGN_PKT_HEADER)) { ++ state->pipe->conn->flags |= DCERPC_PROPOSE_HEADER_SIGNING; ++ } ++ + /* The first request always is a dcerpc_bind. The subsequent ones + * depend on gensec results */ + subreq = dcerpc_bind_send(state, p->conn->event_ctx, p, +-- +1.9.3 + + +From 6bdc135a63647fbbc31c7b2e673396231541641d Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 3 Jan 2014 08:39:12 +0100 +Subject: [PATCH 145/249] s4:rpc_server: support + DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN by default + +If the gensec backend supports it there's no reason to disable it. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 661fe3cf890b91f8750872b0f5a09da536f76ae2) +--- + source4/rpc_server/dcerpc_server.c | 6 ------ + source4/rpc_server/dcesrv_auth.c | 37 ++++++++++++++++++++++++++++++++----- + 2 files changed, 32 insertions(+), 11 deletions(-) + +diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c +index ad53685..3b35703 100644 +--- a/source4/rpc_server/dcerpc_server.c ++++ b/source4/rpc_server/dcerpc_server.c +@@ -610,12 +610,6 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call) + call->conn->cli_max_recv_frag = MIN(0x2000, call->pkt.u.bind.max_recv_frag); + } + +- if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) && +- lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","header signing", false)) { +- call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_HEADER_SIGNING; +- extra_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; +- } +- + /* handle any authentication that is being requested */ + if (!dcesrv_auth_bind(call)) { + talloc_free(call->context); +diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c +index c891cc6..152715b 100644 +--- a/source4/rpc_server/dcesrv_auth.c ++++ b/source4/rpc_server/dcesrv_auth.c +@@ -92,10 +92,6 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call) + return false; + } + +- if (call->conn->state_flags & DCESRV_CALL_STATE_FLAG_HEADER_SIGNING) { +- gensec_want_feature(auth->gensec_security, GENSEC_FEATURE_SIGN_PKT_HEADER); +- } +- + return true; + } + +@@ -107,11 +103,20 @@ NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packe + { + struct dcesrv_connection *dce_conn = call->conn; + NTSTATUS status; ++ bool want_header_signing = false; + + if (!call->conn->auth_state.gensec_security) { + return NT_STATUS_OK; + } + ++ if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) { ++ want_header_signing = true; ++ } ++ ++ if (!lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","header signing", true)) { ++ want_header_signing = false; ++ } ++ + status = gensec_update(dce_conn->auth_state.gensec_security, + call, call->event_ctx, + dce_conn->auth_state.auth_info->credentials, +@@ -126,9 +131,17 @@ NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packe + return status; + } + +- if (dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_HEADER_SIGNING) { ++ if (!gensec_have_feature(dce_conn->auth_state.gensec_security, ++ GENSEC_FEATURE_SIGN_PKT_HEADER)) ++ { ++ want_header_signing = false; ++ } ++ ++ if (want_header_signing) { + gensec_want_feature(dce_conn->auth_state.gensec_security, + GENSEC_FEATURE_SIGN_PKT_HEADER); ++ call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_HEADER_SIGNING; ++ pkt->pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; + } + + /* Now that we are authenticated, go back to the generic session key... */ +@@ -137,6 +150,20 @@ NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packe + } else if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + dce_conn->auth_state.auth_info->auth_pad_length = 0; + dce_conn->auth_state.auth_info->auth_reserved = 0; ++ ++ if (!gensec_have_feature(dce_conn->auth_state.gensec_security, ++ GENSEC_FEATURE_SIGN_PKT_HEADER)) ++ { ++ want_header_signing = false; ++ } ++ ++ if (want_header_signing) { ++ gensec_want_feature(dce_conn->auth_state.gensec_security, ++ GENSEC_FEATURE_SIGN_PKT_HEADER); ++ call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_HEADER_SIGNING; ++ pkt->pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; ++ } ++ + return NT_STATUS_OK; + } else { + DEBUG(4, ("GENSEC mech rejected the incoming authentication at bind_ack: %s\n", +-- +1.9.3 + + +From 868676160bb3bcfb4145a5c4b47fbb513c0bfac4 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 31 Dec 2013 09:53:55 +0100 +Subject: [PATCH 146/249] auth/ntlmssp: GENSEC_FEATURE_SIGN_PKT_HEADER is + always supported + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 64fc015a85f9b5ed74f3dabe05dbdff185093278) +--- + auth/ntlmssp/gensec_ntlmssp.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/auth/ntlmssp/gensec_ntlmssp.c b/auth/ntlmssp/gensec_ntlmssp.c +index 654c0e3..5672589 100644 +--- a/auth/ntlmssp/gensec_ntlmssp.c ++++ b/auth/ntlmssp/gensec_ntlmssp.c +@@ -102,6 +102,10 @@ bool gensec_ntlmssp_have_feature(struct gensec_security *gensec_security, + return true; + } + } ++ if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) { ++ return true; ++ } ++ + return false; + } + +-- +1.9.3 + + +From e486316c74d3781413e66e451b51737fc194bdc2 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 31 Dec 2013 09:54:54 +0100 +Subject: [PATCH 147/249] s4:auth/gensec_gssapi: handle + GENSEC_FEATURE_SIGN_PKT_HEADER in have_feature() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 14f6c41754960d73f46aca1bade2266b7e934d03) +--- + source4/auth/gensec/gensec_gssapi.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c +index 63a53bf..ffdefcf 100644 +--- a/source4/auth/gensec/gensec_gssapi.c ++++ b/source4/auth/gensec/gensec_gssapi.c +@@ -1275,6 +1275,18 @@ static bool gensec_gssapi_have_feature(struct gensec_security *gensec_security, + if (feature & GENSEC_FEATURE_ASYNC_REPLIES) { + return true; + } ++ if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) { ++ if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { ++ /* TODO: implement this using gss_wrap_iov() */ ++ return false; ++ } ++ ++ if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { ++ return true; ++ } ++ ++ return false; ++ } + return false; + } + +-- +1.9.3 + + +From fa8d0a7726240f8fc6648424d9724bcd65949bfd Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 3 Jan 2014 15:30:46 +0100 +Subject: [PATCH 148/249] s4:gensec_gssapi: make sure + gensec_gssapi_[un]seal_packet() rejects header signing + +If header signing is requested we should error out instead of +silently ignoring it, our peer would hopefully reject it, +but we should also do that. + +TODO: we should implement header signing using gss_wrap_iov(). + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 54b5b3067f5b7a0eb6dd9f1326c903f9fe4a5592) +--- + source4/auth/gensec/gensec_gssapi.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c +index ffdefcf..b8f007d 100644 +--- a/source4/auth/gensec/gensec_gssapi.c ++++ b/source4/auth/gensec/gensec_gssapi.c +@@ -1028,6 +1028,12 @@ static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_securit + int conf_state; + ssize_t sig_length; + ++ if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) { ++ DEBUG(1, ("gensec_gssapi_seal_packet: " ++ "GENSEC_FEATURE_SIGN_PKT_HEADER not supported\n")); ++ return NT_STATUS_ACCESS_DENIED; ++ } ++ + input_token.length = length; + input_token.value = data; + +@@ -1082,6 +1088,12 @@ static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_secur + + dump_data_pw("gensec_gssapi_unseal_packet: sig\n", sig->data, sig->length); + ++ if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) { ++ DEBUG(1, ("gensec_gssapi_unseal_packet: " ++ "GENSEC_FEATURE_SIGN_PKT_HEADER not supported\n")); ++ return NT_STATUS_ACCESS_DENIED; ++ } ++ + in = data_blob_talloc(gensec_security, NULL, sig->length + length); + + memcpy(in.data, sig->data, sig->length); +-- +1.9.3 + + +From 2b1f62e3d99047e2981dcdd32c6820346917dc04 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 31 Dec 2013 09:42:36 +0100 +Subject: [PATCH 149/249] auth/gensec: move libcli/auth/schannel_sign.c into + schannel.c + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 616cd009955b1722e6749019e2c1cac8bbb94e52) +--- + auth/gensec/schannel.c | 380 ++++++++++++++++++++++++++++++++++++++++ + libcli/auth/schannel_proto.h | 14 -- + libcli/auth/schannel_sign.c | 404 ------------------------------------------- + libcli/auth/wscript_build | 2 +- + 4 files changed, 381 insertions(+), 419 deletions(-) + delete mode 100644 libcli/auth/schannel_sign.c + +diff --git a/auth/gensec/schannel.c b/auth/gensec/schannel.c +index eb2e100..c60ab4f 100644 +--- a/auth/gensec/schannel.c ++++ b/auth/gensec/schannel.c +@@ -31,6 +31,386 @@ + #include "librpc/gen_ndr/dcerpc.h" + #include "param/param.h" + #include "auth/gensec/gensec_toplevel_proto.h" ++#include "lib/crypto/crypto.h" ++ ++struct schannel_state { ++ uint64_t seq_num; ++ bool initiator; ++ struct netlogon_creds_CredentialState *creds; ++}; ++ ++#define SETUP_SEQNUM(state, buf, initiator) do { \ ++ uint8_t *_buf = buf; \ ++ uint32_t _seq_num_low = (state)->seq_num & UINT32_MAX; \ ++ uint32_t _seq_num_high = (state)->seq_num >> 32; \ ++ if (initiator) { \ ++ _seq_num_high |= 0x80000000; \ ++ } \ ++ RSIVAL(_buf, 0, _seq_num_low); \ ++ RSIVAL(_buf, 4, _seq_num_high); \ ++} while(0) ++ ++static struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_CredentialState *creds, ++ bool initiator) ++{ ++ struct schannel_state *state; ++ ++ state = talloc(mem_ctx, struct schannel_state); ++ if (state == NULL) { ++ return NULL; ++ } ++ ++ state->initiator = initiator; ++ state->seq_num = 0; ++ state->creds = netlogon_creds_copy(state, creds); ++ if (state->creds == NULL) { ++ talloc_free(state); ++ return NULL; ++ } ++ ++ return state; ++} ++ ++static void netsec_offset_and_sizes(struct schannel_state *state, ++ bool do_seal, ++ uint32_t *_min_sig_size, ++ uint32_t *_used_sig_size, ++ uint32_t *_checksum_length, ++ uint32_t *_confounder_ofs) ++{ ++ uint32_t min_sig_size; ++ uint32_t used_sig_size; ++ uint32_t checksum_length; ++ uint32_t confounder_ofs; ++ ++ if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { ++ min_sig_size = 48; ++ used_sig_size = 56; ++ /* ++ * Note: windows has a bug here and uses the old values... ++ * ++ * checksum_length = 32; ++ * confounder_ofs = 48; ++ */ ++ checksum_length = 8; ++ confounder_ofs = 24; ++ } else { ++ min_sig_size = 24; ++ used_sig_size = 32; ++ checksum_length = 8; ++ confounder_ofs = 24; ++ } ++ ++ if (do_seal) { ++ min_sig_size += 8; ++ } ++ ++ if (_min_sig_size) { ++ *_min_sig_size = min_sig_size; ++ } ++ ++ if (_used_sig_size) { ++ *_used_sig_size = used_sig_size; ++ } ++ ++ if (_checksum_length) { ++ *_checksum_length = checksum_length; ++ } ++ ++ if (_confounder_ofs) { ++ *_confounder_ofs = confounder_ofs; ++ } ++} ++ ++/******************************************************************* ++ Encode or Decode the sequence number (which is symmetric) ++ ********************************************************************/ ++static void netsec_do_seq_num(struct schannel_state *state, ++ const uint8_t *checksum, ++ uint32_t checksum_length, ++ uint8_t seq_num[8]) ++{ ++ if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { ++ AES_KEY key; ++ uint8_t iv[AES_BLOCK_SIZE]; ++ ++ AES_set_encrypt_key(state->creds->session_key, 128, &key); ++ ZERO_STRUCT(iv); ++ memcpy(iv+0, checksum, 8); ++ memcpy(iv+8, checksum, 8); ++ ++ aes_cfb8_encrypt(seq_num, seq_num, 8, &key, iv, AES_ENCRYPT); ++ } else { ++ static const uint8_t zeros[4]; ++ uint8_t sequence_key[16]; ++ uint8_t digest1[16]; ++ ++ hmac_md5(state->creds->session_key, zeros, sizeof(zeros), digest1); ++ hmac_md5(digest1, checksum, checksum_length, sequence_key); ++ arcfour_crypt(seq_num, sequence_key, 8); ++ } ++ ++ state->seq_num++; ++} ++ ++static void netsec_do_seal(struct schannel_state *state, ++ const uint8_t seq_num[8], ++ uint8_t confounder[8], ++ uint8_t *data, uint32_t length, ++ bool forward) ++{ ++ if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { ++ AES_KEY key; ++ uint8_t iv[AES_BLOCK_SIZE]; ++ uint8_t sess_kf0[16]; ++ int i; ++ ++ for (i = 0; i < 16; i++) { ++ sess_kf0[i] = state->creds->session_key[i] ^ 0xf0; ++ } ++ ++ AES_set_encrypt_key(sess_kf0, 128, &key); ++ ZERO_STRUCT(iv); ++ memcpy(iv+0, seq_num, 8); ++ memcpy(iv+8, seq_num, 8); ++ ++ if (forward) { ++ aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_ENCRYPT); ++ aes_cfb8_encrypt(data, data, length, &key, iv, AES_ENCRYPT); ++ } else { ++ aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_DECRYPT); ++ aes_cfb8_encrypt(data, data, length, &key, iv, AES_DECRYPT); ++ } ++ } else { ++ uint8_t sealing_key[16]; ++ static const uint8_t zeros[4]; ++ uint8_t digest2[16]; ++ uint8_t sess_kf0[16]; ++ int i; ++ ++ for (i = 0; i < 16; i++) { ++ sess_kf0[i] = state->creds->session_key[i] ^ 0xf0; ++ } ++ ++ hmac_md5(sess_kf0, zeros, 4, digest2); ++ hmac_md5(digest2, seq_num, 8, sealing_key); ++ ++ arcfour_crypt(confounder, sealing_key, 8); ++ arcfour_crypt(data, sealing_key, length); ++ } ++} ++ ++/******************************************************************* ++ Create a digest over the entire packet (including the data), and ++ MD5 it with the session key. ++ ********************************************************************/ ++static void netsec_do_sign(struct schannel_state *state, ++ const uint8_t *confounder, ++ const uint8_t *data, size_t length, ++ uint8_t header[8], ++ uint8_t *checksum) ++{ ++ if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { ++ struct HMACSHA256Context ctx; ++ ++ hmac_sha256_init(state->creds->session_key, ++ sizeof(state->creds->session_key), ++ &ctx); ++ ++ if (confounder) { ++ SSVAL(header, 0, NL_SIGN_HMAC_SHA256); ++ SSVAL(header, 2, NL_SEAL_AES128); ++ SSVAL(header, 4, 0xFFFF); ++ SSVAL(header, 6, 0x0000); ++ ++ hmac_sha256_update(header, 8, &ctx); ++ hmac_sha256_update(confounder, 8, &ctx); ++ } else { ++ SSVAL(header, 0, NL_SIGN_HMAC_SHA256); ++ SSVAL(header, 2, NL_SEAL_NONE); ++ SSVAL(header, 4, 0xFFFF); ++ SSVAL(header, 6, 0x0000); ++ ++ hmac_sha256_update(header, 8, &ctx); ++ } ++ ++ hmac_sha256_update(data, length, &ctx); ++ ++ hmac_sha256_final(checksum, &ctx); ++ } else { ++ uint8_t packet_digest[16]; ++ static const uint8_t zeros[4]; ++ MD5_CTX ctx; ++ ++ MD5Init(&ctx); ++ MD5Update(&ctx, zeros, 4); ++ if (confounder) { ++ SSVAL(header, 0, NL_SIGN_HMAC_MD5); ++ SSVAL(header, 2, NL_SEAL_RC4); ++ SSVAL(header, 4, 0xFFFF); ++ SSVAL(header, 6, 0x0000); ++ ++ MD5Update(&ctx, header, 8); ++ MD5Update(&ctx, confounder, 8); ++ } else { ++ SSVAL(header, 0, NL_SIGN_HMAC_MD5); ++ SSVAL(header, 2, NL_SEAL_NONE); ++ SSVAL(header, 4, 0xFFFF); ++ SSVAL(header, 6, 0x0000); ++ ++ MD5Update(&ctx, header, 8); ++ } ++ MD5Update(&ctx, data, length); ++ MD5Final(packet_digest, &ctx); ++ ++ hmac_md5(state->creds->session_key, ++ packet_digest, sizeof(packet_digest), ++ checksum); ++ } ++} ++ ++static NTSTATUS netsec_incoming_packet(struct schannel_state *state, ++ bool do_unseal, ++ uint8_t *data, size_t length, ++ const DATA_BLOB *sig) ++{ ++ uint32_t min_sig_size = 0; ++ uint8_t header[8]; ++ uint8_t checksum[32]; ++ uint32_t checksum_length = sizeof(checksum_length); ++ uint8_t _confounder[8]; ++ uint8_t *confounder = NULL; ++ uint32_t confounder_ofs = 0; ++ uint8_t seq_num[8]; ++ int ret; ++ ++ netsec_offset_and_sizes(state, ++ do_unseal, ++ &min_sig_size, ++ NULL, ++ &checksum_length, ++ &confounder_ofs); ++ ++ if (sig->length < min_sig_size) { ++ return NT_STATUS_ACCESS_DENIED; ++ } ++ ++ if (do_unseal) { ++ confounder = _confounder; ++ memcpy(confounder, sig->data+confounder_ofs, 8); ++ } else { ++ confounder = NULL; ++ } ++ ++ SETUP_SEQNUM(state, seq_num, !state->initiator); ++ ++ if (do_unseal) { ++ netsec_do_seal(state, seq_num, ++ confounder, ++ data, length, ++ false); ++ } ++ ++ netsec_do_sign(state, confounder, ++ data, length, ++ header, checksum); ++ ++ ret = memcmp(checksum, sig->data+16, checksum_length); ++ if (ret != 0) { ++ dump_data_pw("calc digest:", checksum, checksum_length); ++ dump_data_pw("wire digest:", sig->data+16, checksum_length); ++ return NT_STATUS_ACCESS_DENIED; ++ } ++ ++ netsec_do_seq_num(state, checksum, checksum_length, seq_num); ++ ++ ret = memcmp(seq_num, sig->data+8, 8); ++ if (ret != 0) { ++ dump_data_pw("calc seq num:", seq_num, 8); ++ dump_data_pw("wire seq num:", sig->data+8, 8); ++ return NT_STATUS_ACCESS_DENIED; ++ } ++ ++ return NT_STATUS_OK; ++} ++ ++static uint32_t netsec_outgoing_sig_size(struct schannel_state *state) ++{ ++ uint32_t sig_size = 0; ++ ++ netsec_offset_and_sizes(state, ++ true, ++ NULL, ++ &sig_size, ++ NULL, ++ NULL); ++ ++ return sig_size; ++} ++ ++static NTSTATUS netsec_outgoing_packet(struct schannel_state *state, ++ TALLOC_CTX *mem_ctx, ++ bool do_seal, ++ uint8_t *data, size_t length, ++ DATA_BLOB *sig) ++{ ++ uint32_t min_sig_size = 0; ++ uint32_t used_sig_size = 0; ++ uint8_t header[8]; ++ uint8_t checksum[32]; ++ uint32_t checksum_length = sizeof(checksum_length); ++ uint8_t _confounder[8]; ++ uint8_t *confounder = NULL; ++ uint32_t confounder_ofs = 0; ++ uint8_t seq_num[8]; ++ ++ netsec_offset_and_sizes(state, ++ do_seal, ++ &min_sig_size, ++ &used_sig_size, ++ &checksum_length, ++ &confounder_ofs); ++ ++ SETUP_SEQNUM(state, seq_num, state->initiator); ++ ++ if (do_seal) { ++ confounder = _confounder; ++ generate_random_buffer(confounder, 8); ++ } else { ++ confounder = NULL; ++ } ++ ++ netsec_do_sign(state, confounder, ++ data, length, ++ header, checksum); ++ ++ if (do_seal) { ++ netsec_do_seal(state, seq_num, ++ confounder, ++ data, length, ++ true); ++ } ++ ++ netsec_do_seq_num(state, checksum, checksum_length, seq_num); ++ ++ (*sig) = data_blob_talloc_zero(mem_ctx, used_sig_size); ++ ++ memcpy(sig->data, header, 8); ++ memcpy(sig->data+8, seq_num, 8); ++ memcpy(sig->data+16, checksum, checksum_length); ++ ++ if (confounder) { ++ memcpy(sig->data+confounder_ofs, confounder, 8); ++ } ++ ++ dump_data_pw("signature:", sig->data+ 0, 8); ++ dump_data_pw("seq_num :", sig->data+ 8, 8); ++ dump_data_pw("digest :", sig->data+16, checksum_length); ++ dump_data_pw("confound :", sig->data+confounder_ofs, 8); ++ ++ return NT_STATUS_OK; ++} + + _PUBLIC_ NTSTATUS gensec_schannel_init(void); + +diff --git a/libcli/auth/schannel_proto.h b/libcli/auth/schannel_proto.h +index da76559..bce37c8 100644 +--- a/libcli/auth/schannel_proto.h ++++ b/libcli/auth/schannel_proto.h +@@ -28,18 +28,4 @@ struct schannel_state; + struct db_context *open_schannel_session_store(TALLOC_CTX *mem_ctx, + struct loadparm_context *lp_ctx); + +-struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, +- struct netlogon_creds_CredentialState *creds, +- bool initiator); +-NTSTATUS netsec_incoming_packet(struct schannel_state *state, +- bool do_unseal, +- uint8_t *data, size_t length, +- const DATA_BLOB *sig); +-uint32_t netsec_outgoing_sig_size(struct schannel_state *state); +-NTSTATUS netsec_outgoing_packet(struct schannel_state *state, +- TALLOC_CTX *mem_ctx, +- bool do_seal, +- uint8_t *data, size_t length, +- DATA_BLOB *sig); +- + #endif +diff --git a/libcli/auth/schannel_sign.c b/libcli/auth/schannel_sign.c +deleted file mode 100644 +index 9502cba..0000000 +--- a/libcli/auth/schannel_sign.c ++++ /dev/null +@@ -1,404 +0,0 @@ +-/* +- Unix SMB/CIFS implementation. +- +- schannel library code +- +- Copyright (C) Andrew Tridgell 2004 +- Copyright (C) Andrew Bartlett 2005 +- +- 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 . +-*/ +- +-#include "includes.h" +-#include "../libcli/auth/schannel.h" +-#include "../lib/crypto/crypto.h" +- +-struct schannel_state { +- uint64_t seq_num; +- bool initiator; +- struct netlogon_creds_CredentialState *creds; +-}; +- +-#define SETUP_SEQNUM(state, buf, initiator) do { \ +- uint8_t *_buf = buf; \ +- uint32_t _seq_num_low = (state)->seq_num & UINT32_MAX; \ +- uint32_t _seq_num_high = (state)->seq_num >> 32; \ +- if (initiator) { \ +- _seq_num_high |= 0x80000000; \ +- } \ +- RSIVAL(_buf, 0, _seq_num_low); \ +- RSIVAL(_buf, 4, _seq_num_high); \ +-} while(0) +- +-struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, +- struct netlogon_creds_CredentialState *creds, +- bool initiator) +-{ +- struct schannel_state *state; +- +- state = talloc(mem_ctx, struct schannel_state); +- if (state == NULL) { +- return NULL; +- } +- +- state->initiator = initiator; +- state->seq_num = 0; +- state->creds = netlogon_creds_copy(state, creds); +- if (state->creds == NULL) { +- talloc_free(state); +- return NULL; +- } +- +- return state; +-} +- +-static void netsec_offset_and_sizes(struct schannel_state *state, +- bool do_seal, +- uint32_t *_min_sig_size, +- uint32_t *_used_sig_size, +- uint32_t *_checksum_length, +- uint32_t *_confounder_ofs) +-{ +- uint32_t min_sig_size; +- uint32_t used_sig_size; +- uint32_t checksum_length; +- uint32_t confounder_ofs; +- +- if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { +- min_sig_size = 48; +- used_sig_size = 56; +- /* +- * Note: windows has a bug here and uses the old values... +- * +- * checksum_length = 32; +- * confounder_ofs = 48; +- */ +- checksum_length = 8; +- confounder_ofs = 24; +- } else { +- min_sig_size = 24; +- used_sig_size = 32; +- checksum_length = 8; +- confounder_ofs = 24; +- } +- +- if (do_seal) { +- min_sig_size += 8; +- } +- +- if (_min_sig_size) { +- *_min_sig_size = min_sig_size; +- } +- +- if (_used_sig_size) { +- *_used_sig_size = used_sig_size; +- } +- +- if (_checksum_length) { +- *_checksum_length = checksum_length; +- } +- +- if (_confounder_ofs) { +- *_confounder_ofs = confounder_ofs; +- } +-} +- +-/******************************************************************* +- Encode or Decode the sequence number (which is symmetric) +- ********************************************************************/ +-static void netsec_do_seq_num(struct schannel_state *state, +- const uint8_t *checksum, +- uint32_t checksum_length, +- uint8_t seq_num[8]) +-{ +- if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { +- AES_KEY key; +- uint8_t iv[AES_BLOCK_SIZE]; +- +- AES_set_encrypt_key(state->creds->session_key, 128, &key); +- ZERO_STRUCT(iv); +- memcpy(iv+0, checksum, 8); +- memcpy(iv+8, checksum, 8); +- +- aes_cfb8_encrypt(seq_num, seq_num, 8, &key, iv, AES_ENCRYPT); +- } else { +- static const uint8_t zeros[4]; +- uint8_t sequence_key[16]; +- uint8_t digest1[16]; +- +- hmac_md5(state->creds->session_key, zeros, sizeof(zeros), digest1); +- hmac_md5(digest1, checksum, checksum_length, sequence_key); +- arcfour_crypt(seq_num, sequence_key, 8); +- } +- +- state->seq_num++; +-} +- +-static void netsec_do_seal(struct schannel_state *state, +- const uint8_t seq_num[8], +- uint8_t confounder[8], +- uint8_t *data, uint32_t length, +- bool forward) +-{ +- if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { +- AES_KEY key; +- uint8_t iv[AES_BLOCK_SIZE]; +- uint8_t sess_kf0[16]; +- int i; +- +- for (i = 0; i < 16; i++) { +- sess_kf0[i] = state->creds->session_key[i] ^ 0xf0; +- } +- +- AES_set_encrypt_key(sess_kf0, 128, &key); +- ZERO_STRUCT(iv); +- memcpy(iv+0, seq_num, 8); +- memcpy(iv+8, seq_num, 8); +- +- if (forward) { +- aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_ENCRYPT); +- aes_cfb8_encrypt(data, data, length, &key, iv, AES_ENCRYPT); +- } else { +- aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_DECRYPT); +- aes_cfb8_encrypt(data, data, length, &key, iv, AES_DECRYPT); +- } +- } else { +- uint8_t sealing_key[16]; +- static const uint8_t zeros[4]; +- uint8_t digest2[16]; +- uint8_t sess_kf0[16]; +- int i; +- +- for (i = 0; i < 16; i++) { +- sess_kf0[i] = state->creds->session_key[i] ^ 0xf0; +- } +- +- hmac_md5(sess_kf0, zeros, 4, digest2); +- hmac_md5(digest2, seq_num, 8, sealing_key); +- +- arcfour_crypt(confounder, sealing_key, 8); +- arcfour_crypt(data, sealing_key, length); +- } +-} +- +-/******************************************************************* +- Create a digest over the entire packet (including the data), and +- MD5 it with the session key. +- ********************************************************************/ +-static void netsec_do_sign(struct schannel_state *state, +- const uint8_t *confounder, +- const uint8_t *data, size_t length, +- uint8_t header[8], +- uint8_t *checksum) +-{ +- if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { +- struct HMACSHA256Context ctx; +- +- hmac_sha256_init(state->creds->session_key, +- sizeof(state->creds->session_key), +- &ctx); +- +- if (confounder) { +- SSVAL(header, 0, NL_SIGN_HMAC_SHA256); +- SSVAL(header, 2, NL_SEAL_AES128); +- SSVAL(header, 4, 0xFFFF); +- SSVAL(header, 6, 0x0000); +- +- hmac_sha256_update(header, 8, &ctx); +- hmac_sha256_update(confounder, 8, &ctx); +- } else { +- SSVAL(header, 0, NL_SIGN_HMAC_SHA256); +- SSVAL(header, 2, NL_SEAL_NONE); +- SSVAL(header, 4, 0xFFFF); +- SSVAL(header, 6, 0x0000); +- +- hmac_sha256_update(header, 8, &ctx); +- } +- +- hmac_sha256_update(data, length, &ctx); +- +- hmac_sha256_final(checksum, &ctx); +- } else { +- uint8_t packet_digest[16]; +- static const uint8_t zeros[4]; +- MD5_CTX ctx; +- +- MD5Init(&ctx); +- MD5Update(&ctx, zeros, 4); +- if (confounder) { +- SSVAL(header, 0, NL_SIGN_HMAC_MD5); +- SSVAL(header, 2, NL_SEAL_RC4); +- SSVAL(header, 4, 0xFFFF); +- SSVAL(header, 6, 0x0000); +- +- MD5Update(&ctx, header, 8); +- MD5Update(&ctx, confounder, 8); +- } else { +- SSVAL(header, 0, NL_SIGN_HMAC_MD5); +- SSVAL(header, 2, NL_SEAL_NONE); +- SSVAL(header, 4, 0xFFFF); +- SSVAL(header, 6, 0x0000); +- +- MD5Update(&ctx, header, 8); +- } +- MD5Update(&ctx, data, length); +- MD5Final(packet_digest, &ctx); +- +- hmac_md5(state->creds->session_key, +- packet_digest, sizeof(packet_digest), +- checksum); +- } +-} +- +-NTSTATUS netsec_incoming_packet(struct schannel_state *state, +- bool do_unseal, +- uint8_t *data, size_t length, +- const DATA_BLOB *sig) +-{ +- uint32_t min_sig_size = 0; +- uint8_t header[8]; +- uint8_t checksum[32]; +- uint32_t checksum_length = sizeof(checksum_length); +- uint8_t _confounder[8]; +- uint8_t *confounder = NULL; +- uint32_t confounder_ofs = 0; +- uint8_t seq_num[8]; +- int ret; +- +- netsec_offset_and_sizes(state, +- do_unseal, +- &min_sig_size, +- NULL, +- &checksum_length, +- &confounder_ofs); +- +- if (sig->length < min_sig_size) { +- return NT_STATUS_ACCESS_DENIED; +- } +- +- if (do_unseal) { +- confounder = _confounder; +- memcpy(confounder, sig->data+confounder_ofs, 8); +- } else { +- confounder = NULL; +- } +- +- SETUP_SEQNUM(state, seq_num, !state->initiator); +- +- if (do_unseal) { +- netsec_do_seal(state, seq_num, +- confounder, +- data, length, +- false); +- } +- +- netsec_do_sign(state, confounder, +- data, length, +- header, checksum); +- +- ret = memcmp(checksum, sig->data+16, checksum_length); +- if (ret != 0) { +- dump_data_pw("calc digest:", checksum, checksum_length); +- dump_data_pw("wire digest:", sig->data+16, checksum_length); +- return NT_STATUS_ACCESS_DENIED; +- } +- +- netsec_do_seq_num(state, checksum, checksum_length, seq_num); +- +- ret = memcmp(seq_num, sig->data+8, 8); +- if (ret != 0) { +- dump_data_pw("calc seq num:", seq_num, 8); +- dump_data_pw("wire seq num:", sig->data+8, 8); +- return NT_STATUS_ACCESS_DENIED; +- } +- +- return NT_STATUS_OK; +-} +- +-uint32_t netsec_outgoing_sig_size(struct schannel_state *state) +-{ +- uint32_t sig_size = 0; +- +- netsec_offset_and_sizes(state, +- true, +- NULL, +- &sig_size, +- NULL, +- NULL); +- +- return sig_size; +-} +- +-NTSTATUS netsec_outgoing_packet(struct schannel_state *state, +- TALLOC_CTX *mem_ctx, +- bool do_seal, +- uint8_t *data, size_t length, +- DATA_BLOB *sig) +-{ +- uint32_t min_sig_size = 0; +- uint32_t used_sig_size = 0; +- uint8_t header[8]; +- uint8_t checksum[32]; +- uint32_t checksum_length = sizeof(checksum_length); +- uint8_t _confounder[8]; +- uint8_t *confounder = NULL; +- uint32_t confounder_ofs = 0; +- uint8_t seq_num[8]; +- +- netsec_offset_and_sizes(state, +- do_seal, +- &min_sig_size, +- &used_sig_size, +- &checksum_length, +- &confounder_ofs); +- +- SETUP_SEQNUM(state, seq_num, state->initiator); +- +- if (do_seal) { +- confounder = _confounder; +- generate_random_buffer(confounder, 8); +- } else { +- confounder = NULL; +- } +- +- netsec_do_sign(state, confounder, +- data, length, +- header, checksum); +- +- if (do_seal) { +- netsec_do_seal(state, seq_num, +- confounder, +- data, length, +- true); +- } +- +- netsec_do_seq_num(state, checksum, checksum_length, seq_num); +- +- (*sig) = data_blob_talloc_zero(mem_ctx, used_sig_size); +- +- memcpy(sig->data, header, 8); +- memcpy(sig->data+8, seq_num, 8); +- memcpy(sig->data+16, checksum, checksum_length); +- +- if (confounder) { +- memcpy(sig->data+confounder_ofs, confounder, 8); +- } +- +- dump_data_pw("signature:", sig->data+ 0, 8); +- dump_data_pw("seq_num :", sig->data+ 8, 8); +- dump_data_pw("digest :", sig->data+16, checksum_length); +- dump_data_pw("confound :", sig->data+confounder_ofs, 8); +- +- return NT_STATUS_OK; +-} +diff --git a/libcli/auth/wscript_build b/libcli/auth/wscript_build +index df23058..ca2be2d 100755 +--- a/libcli/auth/wscript_build ++++ b/libcli/auth/wscript_build +@@ -24,7 +24,7 @@ bld.SAMBA_SUBSYSTEM('LIBCLI_AUTH', + + + bld.SAMBA_SUBSYSTEM('COMMON_SCHANNEL', +- source='schannel_state_tdb.c schannel_sign.c', ++ source='schannel_state_tdb.c', + deps='dbwrap util_tdb samba-hostconfig NDR_NETLOGON' + ) + +-- +1.9.3 + + +From 307627065568a259eb9e94953b872bf723477be6 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 31 Dec 2013 10:11:18 +0100 +Subject: [PATCH 150/249] auth/gensec: implement GENSEC_FEATURE_SIGN_PKT_HEADER + in schannel.c + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 03006d0e4471465f071517097145806fbe46fdba) +--- + auth/gensec/schannel.c | 56 +++++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 46 insertions(+), 10 deletions(-) + +diff --git a/auth/gensec/schannel.c b/auth/gensec/schannel.c +index c60ab4f..3d30e83 100644 +--- a/auth/gensec/schannel.c ++++ b/auth/gensec/schannel.c +@@ -34,6 +34,7 @@ + #include "lib/crypto/crypto.h" + + struct schannel_state { ++ struct gensec_security *gensec; + uint64_t seq_num; + bool initiator; + struct netlogon_creds_CredentialState *creds; +@@ -50,17 +51,19 @@ struct schannel_state { + RSIVAL(_buf, 4, _seq_num_high); \ + } while(0) + +-static struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, ++static struct schannel_state *netsec_create_state( ++ struct gensec_security *gensec, + struct netlogon_creds_CredentialState *creds, + bool initiator) + { + struct schannel_state *state; + +- state = talloc(mem_ctx, struct schannel_state); ++ state = talloc(gensec, struct schannel_state); + if (state == NULL) { + return NULL; + } + ++ state->gensec = gensec; + state->initiator = initiator; + state->seq_num = 0; + state->creds = netlogon_creds_copy(state, creds); +@@ -69,6 +72,8 @@ static struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, + return NULL; + } + ++ gensec->private_data = state; ++ + return state; + } + +@@ -273,6 +278,7 @@ static void netsec_do_sign(struct schannel_state *state, + static NTSTATUS netsec_incoming_packet(struct schannel_state *state, + bool do_unseal, + uint8_t *data, size_t length, ++ const uint8_t *whole_pdu, size_t pdu_length, + const DATA_BLOB *sig) + { + uint32_t min_sig_size = 0; +@@ -284,6 +290,8 @@ static NTSTATUS netsec_incoming_packet(struct schannel_state *state, + uint32_t confounder_ofs = 0; + uint8_t seq_num[8]; + int ret; ++ const uint8_t *sign_data = NULL; ++ size_t sign_length = 0; + + netsec_offset_and_sizes(state, + do_unseal, +@@ -312,8 +320,16 @@ static NTSTATUS netsec_incoming_packet(struct schannel_state *state, + false); + } + ++ if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) { ++ sign_data = whole_pdu; ++ sign_length = pdu_length; ++ } else { ++ sign_data = data; ++ sign_length = length; ++ } ++ + netsec_do_sign(state, confounder, +- data, length, ++ sign_data, sign_length, + header, checksum); + + ret = memcmp(checksum, sig->data+16, checksum_length); +@@ -353,6 +369,7 @@ static NTSTATUS netsec_outgoing_packet(struct schannel_state *state, + TALLOC_CTX *mem_ctx, + bool do_seal, + uint8_t *data, size_t length, ++ const uint8_t *whole_pdu, size_t pdu_length, + DATA_BLOB *sig) + { + uint32_t min_sig_size = 0; +@@ -364,6 +381,8 @@ static NTSTATUS netsec_outgoing_packet(struct schannel_state *state, + uint8_t *confounder = NULL; + uint32_t confounder_ofs = 0; + uint8_t seq_num[8]; ++ const uint8_t *sign_data = NULL; ++ size_t sign_length = 0; + + netsec_offset_and_sizes(state, + do_seal, +@@ -381,8 +400,16 @@ static NTSTATUS netsec_outgoing_packet(struct schannel_state *state, + confounder = NULL; + } + ++ if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) { ++ sign_data = whole_pdu; ++ sign_length = pdu_length; ++ } else { ++ sign_data = data; ++ sign_length = length; ++ } ++ + netsec_do_sign(state, confounder, +- data, length, ++ sign_data, sign_length, + header, checksum); + + if (do_seal) { +@@ -457,7 +484,6 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ + if (state == NULL) { + return NT_STATUS_NO_MEMORY; + } +- gensec_security->private_data = state; + + bind_schannel.MessageType = NL_NEGOTIATE_REQUEST; + #if 0 +@@ -553,7 +579,6 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ + if (state == NULL) { + return NT_STATUS_NO_MEMORY; + } +- gensec_security->private_data = state; + + bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE; + bind_schannel_ack.Flags = 0; +@@ -608,6 +633,9 @@ static bool schannel_have_feature(struct gensec_security *gensec_security, + if (feature & GENSEC_FEATURE_DCE_STYLE) { + return true; + } ++ if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) { ++ return true; ++ } + return false; + } + +@@ -625,7 +653,9 @@ static NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security, + + return netsec_incoming_packet(state, true, + discard_const_p(uint8_t, data), +- length, sig); ++ length, ++ whole_pdu, pdu_length, ++ sig); + } + + /* +@@ -642,7 +672,9 @@ static NTSTATUS schannel_check_packet(struct gensec_security *gensec_security, + + return netsec_incoming_packet(state, false, + discard_const_p(uint8_t, data), +- length, sig); ++ length, ++ whole_pdu, pdu_length, ++ sig); + } + /* + seal a packet +@@ -658,7 +690,9 @@ static NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security, + struct schannel_state); + + return netsec_outgoing_packet(state, mem_ctx, true, +- data, length, sig); ++ data, length, ++ whole_pdu, pdu_length, ++ sig); + } + + /* +@@ -676,7 +710,9 @@ static NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security, + + return netsec_outgoing_packet(state, mem_ctx, false, + discard_const_p(uint8_t, data), +- length, sig); ++ length, ++ whole_pdu, pdu_length, ++ sig); + } + + static const struct gensec_security_ops gensec_schannel_security_ops = { +-- +1.9.3 + + +From 5b457559dfaeaf8f3d9227a93e5b75e0e7464c23 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sun, 5 Jan 2014 06:16:03 +0100 +Subject: [PATCH 151/249] s3:rpc_client: talloc_zero pipe_auth_data + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 5b39a351a8ceb3bec04236ceb4b2fe10651958a9) +--- + source3/rpc_client/cli_pipe.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index a343997..7d1e347 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -2101,7 +2101,7 @@ NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx, + { + struct pipe_auth_data *result; + +- result = talloc(mem_ctx, struct pipe_auth_data); ++ result = talloc_zero(mem_ctx, struct pipe_auth_data); + if (result == NULL) { + return NT_STATUS_NO_MEMORY; + } +@@ -2125,7 +2125,7 @@ NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx, + { + struct pipe_auth_data *result; + +- result = talloc(mem_ctx, struct pipe_auth_data); ++ result = talloc_zero(mem_ctx, struct pipe_auth_data); + if (result == NULL) { + return NT_STATUS_NO_MEMORY; + } +@@ -2160,7 +2160,7 @@ static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx, + struct pipe_auth_data *result; + NTSTATUS status; + +- result = talloc(mem_ctx, struct pipe_auth_data); ++ result = talloc_zero(mem_ctx, struct pipe_auth_data); + if (result == NULL) { + return NT_STATUS_NO_MEMORY; + } +-- +1.9.3 + + +From dd35874efea280b91ccaadf14a9a18e8a9017ea4 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sun, 5 Jan 2014 06:31:44 +0100 +Subject: [PATCH 152/249] s3:rpc_client: make rpc_api_pipe_req_send/recv static + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 946e29dbc148d40fadbee81d4d530a36c0f2f1e6) +--- + source3/rpc_client/cli_pipe.c | 4 ++-- + source3/rpc_client/cli_pipe.h | 10 ---------- + 2 files changed, 2 insertions(+), 12 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 7d1e347..3d12454 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -1153,7 +1153,7 @@ static void rpc_api_pipe_req_done(struct tevent_req *subreq); + static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, + bool *is_last_frag); + +-struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, ++static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct rpc_pipe_client *cli, + uint8_t op_num, +@@ -1366,7 +1366,7 @@ static void rpc_api_pipe_req_done(struct tevent_req *subreq) + tevent_req_done(req); + } + +-NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, ++static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + DATA_BLOB *reply_pdu) + { + struct rpc_api_pipe_req_state *state = tevent_req_data( +diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h +index ab99373..826f9bf 100644 +--- a/source3/rpc_client/cli_pipe.h ++++ b/source3/rpc_client/cli_pipe.h +@@ -27,16 +27,6 @@ + + /* The following definitions come from rpc_client/cli_pipe.c */ + +-struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, +- struct tevent_context *ev, +- struct rpc_pipe_client *cli, +- uint8_t op_num, +- DATA_BLOB *req_data); +- +-NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, +- TALLOC_CTX *mem_ctx, +- DATA_BLOB *reply_pdu); +- + struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct rpc_pipe_client *cli, +-- +1.9.3 + + +From 9ea586bbac52bf17e6a1147420bfc9648e697706 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sun, 5 Jan 2014 07:56:20 +0100 +Subject: [PATCH 153/249] s3:rpc_client: add some const to + rpc_api_pipe_req_send() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 4d3376e919b5c33f272b3a584d8172729a7468e0) +--- + source3/rpc_client/cli_pipe.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 3d12454..6b7fee2 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -1142,7 +1142,7 @@ struct rpc_api_pipe_req_state { + struct rpc_pipe_client *cli; + uint8_t op_num; + uint32_t call_id; +- DATA_BLOB *req_data; ++ const DATA_BLOB *req_data; + uint32_t req_data_sent; + DATA_BLOB rpc_out; + DATA_BLOB reply_pdu; +@@ -1157,7 +1157,7 @@ static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct rpc_pipe_client *cli, + uint8_t op_num, +- DATA_BLOB *req_data) ++ const DATA_BLOB *req_data) + { + struct tevent_req *req, *subreq; + struct rpc_api_pipe_req_state *state; +-- +1.9.3 + + +From cc6303171f06ae26bce9d54013a63a6296563dd7 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sun, 5 Jan 2014 08:26:15 +0100 +Subject: [PATCH 154/249] s3:rpc_client: handle DCERPC_AUTH_TYPE_SCHANNEL as + any other gensec backend + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit f7bf7e705e704d2f1702e42a8e400baff9521066) +--- + source3/rpc_client/cli_pipe.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 6b7fee2..b142774 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -1627,11 +1627,11 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) + + case DCERPC_AUTH_TYPE_NONE: + case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM: +- case DCERPC_AUTH_TYPE_SCHANNEL: + /* Bind complete. */ + tevent_req_done(req); + return; + ++ case DCERPC_AUTH_TYPE_SCHANNEL: + case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_SPNEGO: + case DCERPC_AUTH_TYPE_KRB5: +@@ -1666,11 +1666,11 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) + + case DCERPC_AUTH_TYPE_NONE: + case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM: +- case DCERPC_AUTH_TYPE_SCHANNEL: + /* Bind complete. */ + tevent_req_done(req); + return; + ++ case DCERPC_AUTH_TYPE_SCHANNEL: + case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_KRB5: + case DCERPC_AUTH_TYPE_SPNEGO: +-- +1.9.3 + + +From 044ca24f9d8a3bf57d6981c89e6dcc5e4477059d Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 3 Jan 2014 22:41:33 +0100 +Subject: [PATCH 155/249] s3:rpc_client: implement + DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 61bdbc23cd09a594a63f49ff8626934c85a8e51a) +--- + source3/librpc/rpc/dcerpc.h | 4 +++- + source3/rpc_client/cli_pipe.c | 44 +++++++++++++++++++++++++++++++++++++------ + 2 files changed, 41 insertions(+), 7 deletions(-) + +diff --git a/source3/librpc/rpc/dcerpc.h b/source3/librpc/rpc/dcerpc.h +index b18b7ba..aaf8d68 100644 +--- a/source3/librpc/rpc/dcerpc.h ++++ b/source3/librpc/rpc/dcerpc.h +@@ -39,7 +39,9 @@ struct NL_AUTH_MESSAGE; + struct pipe_auth_data { + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; +- ++ bool client_hdr_signing; ++ bool hdr_signing; ++ + void *auth_ctx; + + /* Only the client code uses these 3 for now */ +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index b142774..1cab580 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -1002,16 +1002,31 @@ static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + + static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, +- DATA_BLOB *auth_token) ++ DATA_BLOB *auth_token, ++ bool *client_hdr_signing) + { + struct gensec_security *gensec_security; + DATA_BLOB null_blob = data_blob_null; ++ NTSTATUS status; + + gensec_security = talloc_get_type_abort(cli->auth->auth_ctx, + struct gensec_security); + + DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n")); +- return gensec_update(gensec_security, mem_ctx, NULL, null_blob, auth_token); ++ status = gensec_update(gensec_security, mem_ctx, NULL, null_blob, auth_token); ++ ++ if (!NT_STATUS_IS_OK(status) && ++ !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) ++ { ++ return status; ++ } ++ ++ if (client_hdr_signing != NULL) { ++ *client_hdr_signing = gensec_have_feature(gensec_security, ++ GENSEC_FEATURE_SIGN_PKT_HEADER); ++ } ++ ++ return status; + } + + /******************************************************************* +@@ -1024,17 +1039,23 @@ static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx, + const struct ndr_syntax_id *abstract, + const struct ndr_syntax_id *transfer, + const DATA_BLOB *auth_info, ++ bool client_hdr_signing, + DATA_BLOB *blob) + { + uint16 auth_len = auth_info->length; + NTSTATUS status; + union dcerpc_payload u; + struct dcerpc_ctx_list ctx_list; ++ uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; + + if (auth_len) { + auth_len -= DCERPC_AUTH_TRAILER_LENGTH; + } + ++ if (client_hdr_signing) { ++ pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; ++ } ++ + ctx_list.context_id = 0; + ctx_list.num_transfer_syntaxes = 1; + ctx_list.abstract_syntax = *abstract; +@@ -1048,9 +1069,7 @@ static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx, + u.bind.auth_info = *auth_info; + + status = dcerpc_push_ncacn_packet(mem_ctx, +- ptype, +- DCERPC_PFC_FLAG_FIRST | +- DCERPC_PFC_FLAG_LAST, ++ ptype, pfc_flags, + auth_len, + rpc_call_id, + &u, +@@ -1084,7 +1103,9 @@ static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx, + case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_KRB5: + case DCERPC_AUTH_TYPE_SPNEGO: +- ret = create_generic_auth_rpc_bind_req(cli, mem_ctx, &auth_token); ++ ret = create_generic_auth_rpc_bind_req(cli, mem_ctx, ++ &auth_token, ++ &auth->client_hdr_signing); + + if (!NT_STATUS_IS_OK(ret) && + !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) { +@@ -1126,6 +1147,7 @@ static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx, + abstract, + transfer, + &auth_info, ++ auth->client_hdr_signing, + rpc_out); + return ret; + } +@@ -1507,6 +1529,7 @@ static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx, + abstract, + transfer, + &auth_info, ++ false, /* client_hdr_signing */ + rpc_out); + data_blob_free(&auth_info); + return status; +@@ -1676,6 +1699,15 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) + case DCERPC_AUTH_TYPE_SPNEGO: + gensec_security = talloc_get_type_abort(pauth->auth_ctx, + struct gensec_security); ++ ++ if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) { ++ if (pauth->client_hdr_signing) { ++ pauth->hdr_signing = true; ++ gensec_want_feature(gensec_security, ++ GENSEC_FEATURE_SIGN_PKT_HEADER); ++ } ++ } ++ + status = gensec_update(gensec_security, state, NULL, + auth.credentials, &auth_token); + if (NT_STATUS_EQUAL(status, +-- +1.9.3 + + +From 472b11d1b0fdbb1ca61e64979e4b5fd7dc1756a5 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 3 Jan 2014 22:56:03 +0100 +Subject: [PATCH 156/249] s3:rpc_server: add support for + DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN + +If the backend supports it there's no reason to avoid it. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 523d616268af5f94e11c863f9acdebabace80608) +--- + source3/rpc_server/srv_pipe.c | 25 ++++++++++++++++++++++--- + 1 file changed, 22 insertions(+), 3 deletions(-) + +diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c +index 5f834fb..f572819 100644 +--- a/source3/rpc_server/srv_pipe.c ++++ b/source3/rpc_server/srv_pipe.c +@@ -42,6 +42,7 @@ + #include "rpc_server/rpc_contexts.h" + #include "lib/param/param.h" + #include "librpc/ndr/ndr_table.h" ++#include "auth/gensec/gensec.h" + + #undef DBGC_CLASS + #define DBGC_CLASS DBGC_RPC_SRV +@@ -418,10 +419,11 @@ bool is_known_pipename(const char *pipename, struct ndr_syntax_id *syntax) + *******************************************************************/ + + static bool pipe_auth_generic_bind(struct pipes_struct *p, +- TALLOC_CTX *mem_ctx, ++ struct ncacn_packet *pkt, + struct dcerpc_auth *auth_info, + DATA_BLOB *response) + { ++ TALLOC_CTX *mem_ctx = pkt; + struct gensec_security *gensec_security = NULL; + NTSTATUS status; + +@@ -444,6 +446,17 @@ static bool pipe_auth_generic_bind(struct pipes_struct *p, + p->auth.auth_ctx = gensec_security; + p->auth.auth_type = auth_info->auth_type; + ++ if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) { ++ p->auth.client_hdr_signing = true; ++ p->auth.hdr_signing = gensec_have_feature(gensec_security, ++ GENSEC_FEATURE_SIGN_PKT_HEADER); ++ } ++ ++ if (p->auth.hdr_signing) { ++ gensec_want_feature(gensec_security, ++ GENSEC_FEATURE_SIGN_PKT_HEADER); ++ } ++ + return true; + } + +@@ -548,6 +561,7 @@ static bool api_pipe_bind_req(struct pipes_struct *p, + unsigned int auth_type = DCERPC_AUTH_TYPE_NONE; + NTSTATUS status; + struct ndr_syntax_id id; ++ uint8_t pfc_flags = 0; + union dcerpc_payload u; + struct dcerpc_ack_ctx bind_ack_ctx; + DATA_BLOB auth_resp = data_blob_null; +@@ -792,10 +806,15 @@ static bool api_pipe_bind_req(struct pipes_struct *p, + * header and are never sending more than one PDU here. + */ + ++ pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; ++ ++ if (p->auth.hdr_signing) { ++ pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; ++ } ++ + status = dcerpc_push_ncacn_packet(p->mem_ctx, + DCERPC_PKT_BIND_ACK, +- DCERPC_PFC_FLAG_FIRST | +- DCERPC_PFC_FLAG_LAST, ++ pfc_flags, + auth_resp.length, + pkt->call_id, + &u, +-- +1.9.3 + + +From 4e6bea89ffcca074e0320b98e65485f348a469a5 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 3 Jan 2014 09:25:23 +0100 +Subject: [PATCH 157/249] librpc/ndr: add + LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES + +This lets ndr_pull_subcontext_end() make sure that all +subcontext bytes are consumed otherwise it returns NDR_ERR_UNREAD_BYTES. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit b62308ed994e9734dfd934d230531010d9e7cefa) +--- + librpc/idl/idl_types.h | 2 ++ + librpc/ndr/libndr.h | 6 ++++++ + librpc/ndr/ndr.c | 20 ++++++++++++++++++++ + 3 files changed, 28 insertions(+) + +diff --git a/librpc/idl/idl_types.h b/librpc/idl/idl_types.h +index c50efac..838c219 100644 +--- a/librpc/idl/idl_types.h ++++ b/librpc/idl/idl_types.h +@@ -53,3 +53,5 @@ + + #define NDR_RELATIVE_REVERSE LIBNDR_FLAG_RELATIVE_REVERSE + #define NDR_NO_RELATIVE_REVERSE LIBNDR_FLAG_NO_RELATIVE_REVERSE ++ ++#define NDR_SUBCONTEXT_NO_UNREAD_BYTES LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES +diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h +index a950519..8070c3c 100644 +--- a/librpc/ndr/libndr.h ++++ b/librpc/ndr/libndr.h +@@ -123,6 +123,12 @@ struct ndr_print { + #define LIBNDR_FLAG_STR_RAW8 (1<<13) + #define LIBNDR_STRING_FLAGS (0x7FFC) + ++/* ++ * This lets ndr_pull_subcontext_end() return ++ * NDR_ERR_UNREAD_BYTES. ++ */ ++#define LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES (1<<17) ++ + /* set if relative pointers should *not* be marshalled in reverse order */ + #define LIBNDR_FLAG_NO_RELATIVE_REVERSE (1<<18) + +diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c +index e86cf2f..15a7f12 100644 +--- a/librpc/ndr/ndr.c ++++ b/librpc/ndr/ndr.c +@@ -638,6 +638,8 @@ _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_end(struct ndr_pull *ndr, + ssize_t size_is) + { + uint32_t advance; ++ uint32_t highest_ofs; ++ + if (size_is >= 0) { + advance = size_is; + } else if (header_size > 0) { +@@ -645,6 +647,24 @@ _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_end(struct ndr_pull *ndr, + } else { + advance = subndr->offset; + } ++ ++ if (subndr->offset > ndr->relative_highest_offset) { ++ highest_ofs = subndr->offset; ++ } else { ++ highest_ofs = subndr->relative_highest_offset; ++ } ++ if (!(subndr->flags & LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES)) { ++ /* ++ * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified ++ */ ++ highest_ofs = advance; ++ } ++ if (highest_ofs < advance) { ++ return ndr_pull_error(subndr, NDR_ERR_UNREAD_BYTES, ++ "not all bytes consumed ofs[%u] advance[%u]", ++ highest_ofs, advance); ++ } ++ + NDR_CHECK(ndr_pull_advance(ndr, advance)); + return NDR_ERR_SUCCESS; + } +-- +1.9.3 + + +From 5960d93d9cddca327ad8d24a41c64421ac6bb561 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 3 Jan 2014 15:06:23 +0100 +Subject: [PATCH 158/249] dcerpc.idl: add documentation references + +To [C706 - DCE 1.1: Remote Procedure Call] and [MS-RPCE]. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 66c39420e29e7c257d9cdc5d04c061472bbefd19) +--- + librpc/idl/dcerpc.idl | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/librpc/idl/dcerpc.idl b/librpc/idl/dcerpc.idl +index 86f22a4..23cac89 100644 +--- a/librpc/idl/dcerpc.idl ++++ b/librpc/idl/dcerpc.idl +@@ -5,8 +5,17 @@ + but given that pidl can handle it nicely it simplifies things a lot + to do it this way + +- see http://www.opengroup.org/onlinepubs/9629399/chap12.htm for packet +- layouts ++ See [C706 - DCE 1.1: Remote Procedure Call] for the OpenGroup ++ DCERPC specification: ++ http://pubs.opengroup.org/onlinepubs/9629399/toc.htm ++ ++ See C706 - Chapter 12: RPC PDU Encodings for packet layouts: ++ http://www.opengroup.org/onlinepubs/9629399/chap12.htm ++ ++ See also [MS-RPCE] for the Microsoft ++ "Remote Procedure Call Protocol Extensions". ++ http://msdn.microsoft.com/en-us/library/cc243560.aspx ++ + */ + import "misc.idl"; + +-- +1.9.3 + + +From 812cb7e6010b39fb752cf85026fd8d8a5dccbb39 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 2 Jan 2014 11:18:38 +0100 +Subject: [PATCH 159/249] dcerpc.idl: add dcerpc_sec_verification_trailer + +See [MS-RPCE] 2.2.2.13 Verification Trailer for details. + +Pair-Programmed-With: Gregor Beck + +Signed-off-by: Gregor Beck +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit c0dc2fb7e1dadcef35a132040448cb27ff1d5bfa) +--- + librpc/idl/dcerpc.idl | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ + librpc/ndr/ndr_dcerpc.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ + librpc/wscript_build | 2 +- + 3 files changed, 134 insertions(+), 1 deletion(-) + create mode 100644 librpc/ndr/ndr_dcerpc.c + +diff --git a/librpc/idl/dcerpc.idl b/librpc/idl/dcerpc.idl +index 23cac89..8e9be0e 100644 +--- a/librpc/idl/dcerpc.idl ++++ b/librpc/idl/dcerpc.idl +@@ -19,6 +19,8 @@ + */ + import "misc.idl"; + ++cpp_quote("extern const uint8_t DCERPC_SEC_VT_MAGIC[8];") ++ + interface dcerpc + { + typedef struct { +@@ -514,4 +516,69 @@ interface dcerpc + uint8 serial_low; + [switch_is(ptype)] dcerpc_payload u; + } ncadg_packet; ++ ++ typedef [bitmap16bit] bitmap { ++ DCERPC_SEC_VT_COMMAND_ENUM = 0x3FFF, ++ DCERPC_SEC_VT_COMMAND_END = 0x4000, ++ DCERPC_SEC_VT_MUST_PROCESS = 0x8000 ++ } dcerpc_sec_vt_command; ++ ++ typedef [enum16bit] enum { ++ DCERPC_SEC_VT_COMMAND_BITMASK1 = 0x0001, ++ DCERPC_SEC_VT_COMMAND_PCONTEXT = 0x0002, ++ DCERPC_SEC_VT_COMMAND_HEADER2 = 0x0003 ++ } dcerpc_sec_vt_command_enum; ++ ++ typedef [bitmap32bit] bitmap { ++ DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING = 0x00000001 ++ } dcerpc_sec_vt_bitmask1; ++ ++ typedef struct { ++ ndr_syntax_id abstract_syntax; ++ ndr_syntax_id transfer_syntax; ++ } dcerpc_sec_vt_pcontext; ++ ++ typedef struct { ++ dcerpc_pkt_type ptype; /* Packet type */ ++ [value(0)] uint8 reserved1; ++ [value(0)] uint16 reserved2; ++ uint8 drep[4]; /* NDR data representation */ ++ uint32 call_id; /* Call identifier */ ++ uint16 context_id; ++ uint16 opnum; ++ } dcerpc_sec_vt_header2; ++ ++ typedef [switch_type(dcerpc_sec_vt_command_enum),nodiscriminant] union { ++ [case(DCERPC_SEC_VT_COMMAND_BITMASK1)] dcerpc_sec_vt_bitmask1 bitmask1; ++ [case(DCERPC_SEC_VT_COMMAND_PCONTEXT)] dcerpc_sec_vt_pcontext pcontext; ++ [case(DCERPC_SEC_VT_COMMAND_HEADER2)] dcerpc_sec_vt_header2 header2; ++ [default,flag(NDR_REMAINING)] DATA_BLOB _unknown; ++ } dcerpc_sec_vt_union; ++ ++ typedef struct { ++ dcerpc_sec_vt_command command; ++ [switch_is(command & DCERPC_SEC_VT_COMMAND_ENUM)] ++ [subcontext(2),flag(NDR_SUBCONTEXT_NO_UNREAD_BYTES)] ++ dcerpc_sec_vt_union u; ++ } dcerpc_sec_vt; ++ ++ typedef [public,nopush,nopull] struct { ++ uint16 count; ++ } dcerpc_sec_vt_count; ++ ++ /* ++ * We assume that the whole verification trailer fits into ++ * the last 1024 bytes after the stub data. ++ * ++ * There're currently only 3 commands defined and each should ++ * only be used once. ++ */ ++ const uint16 DCERPC_SEC_VT_MAX_SIZE = 1024; ++ ++ typedef [public,flag(NDR_PAHEX)] struct { ++ [flag(NDR_ALIGN4)] DATA_BLOB _pad; ++ [value(DCERPC_SEC_VT_MAGIC)] uint8 magic[8]; ++ dcerpc_sec_vt_count count; ++ dcerpc_sec_vt commands[count.count]; ++ } dcerpc_sec_verification_trailer; + } +diff --git a/librpc/ndr/ndr_dcerpc.c b/librpc/ndr/ndr_dcerpc.c +new file mode 100644 +index 0000000..88a7f38 +--- /dev/null ++++ b/librpc/ndr/ndr_dcerpc.c +@@ -0,0 +1,66 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ Manually parsed structures found in the DCERPC protocol ++ ++ Copyright (C) Stefan Metzmacher 2014 ++ Copyright (C) Gregor Beck 2014 ++ ++ 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 . ++*/ ++ ++#include "includes.h" ++#include "bin/default/librpc/gen_ndr/ndr_dcerpc.h" ++ ++#include "librpc/gen_ndr/ndr_misc.h" ++ ++const uint8_t DCERPC_SEC_VT_MAGIC[] = {0x8a,0xe3,0x13,0x71,0x02,0xf4,0x36,0x71}; ++ ++_PUBLIC_ enum ndr_err_code ndr_push_dcerpc_sec_vt_count(struct ndr_push *ndr, int ndr_flags, const struct dcerpc_sec_vt_count *r) ++{ ++ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); ++ /* nothing */ ++ return NDR_ERR_SUCCESS; ++} ++ ++_PUBLIC_ enum ndr_err_code ndr_pull_dcerpc_sec_vt_count(struct ndr_pull *ndr, int ndr_flags, struct dcerpc_sec_vt_count *r) ++{ ++ uint32_t _saved_ofs = ndr->offset; ++ ++ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); ++ ++ if (!(ndr_flags & NDR_SCALARS)) { ++ return NDR_ERR_SUCCESS; ++ } ++ ++ r->count = 0; ++ ++ while (true) { ++ uint16_t command; ++ uint16_t length; ++ ++ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &command)); ++ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &length)); ++ NDR_CHECK(ndr_pull_advance(ndr, length)); ++ ++ r->count += 1; ++ ++ if (command & DCERPC_SEC_VT_COMMAND_END) { ++ break; ++ } ++ } ++ ++ ndr->offset = _saved_ofs; ++ return NDR_ERR_SUCCESS; ++} +diff --git a/librpc/wscript_build b/librpc/wscript_build +index 2017a29..a5cf687 100644 +--- a/librpc/wscript_build ++++ b/librpc/wscript_build +@@ -301,7 +301,7 @@ bld.SAMBA_SUBSYSTEM('NDR_FSRVP', + ) + + bld.SAMBA_SUBSYSTEM('NDR_DCERPC', +- source='gen_ndr/ndr_dcerpc.c', ++ source='gen_ndr/ndr_dcerpc.c ndr/ndr_dcerpc.c', + public_deps='ndr', + public_headers='gen_ndr/ndr_dcerpc.h gen_ndr/dcerpc.h', + header_path= [ ('*gen_ndr*', 'gen_ndr') ], +-- +1.9.3 + + +From 3480b809bd9426ce6b976b9965a54de32d246a66 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sun, 5 Jan 2014 07:57:51 +0100 +Subject: [PATCH 160/249] s3:rpc_client: fill alloc_hint with the remaining + data not the total data. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit f0532fe0cd69aeb161088ca990d376f119102e61) +--- + source3/rpc_client/cli_pipe.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 1cab580..5edd897 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -1277,7 +1277,7 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, + + ZERO_STRUCT(u.request); + +- u.request.alloc_hint = state->req_data->length; ++ u.request.alloc_hint = data_left; + u.request.context_id = 0; + u.request.opnum = state->op_num; + +-- +1.9.3 + + +From bd675cd6e4848bee8798dacf1768556de48f3112 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sun, 5 Jan 2014 08:12:45 +0100 +Subject: [PATCH 161/249] s3:rpc_client: send a dcerpc_sec_verification_trailer + if needed + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett + +Autobuild-User(master): Stefan Metzmacher +Autobuild-Date(master): Tue Jan 7 02:24:42 CET 2014 on sn-devel-104 +(cherry picked from commit 6ab9164c74e0ad57bdde8abb568953026b644e27) +--- + source3/librpc/rpc/dcerpc.h | 1 + + source3/rpc_client/cli_pipe.c | 202 ++++++++++++++++++++++++++++++++++++++-- + source3/rpc_client/rpc_client.h | 1 + + 3 files changed, 194 insertions(+), 10 deletions(-) + +diff --git a/source3/librpc/rpc/dcerpc.h b/source3/librpc/rpc/dcerpc.h +index aaf8d68..9d0f861 100644 +--- a/source3/librpc/rpc/dcerpc.h ++++ b/source3/librpc/rpc/dcerpc.h +@@ -41,6 +41,7 @@ struct pipe_auth_data { + enum dcerpc_AuthLevel auth_level; + bool client_hdr_signing; + bool hdr_signing; ++ bool verified_bitmask1; + + void *auth_ctx; + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 5edd897..a45023f 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -1166,12 +1166,17 @@ struct rpc_api_pipe_req_state { + uint32_t call_id; + const DATA_BLOB *req_data; + uint32_t req_data_sent; ++ DATA_BLOB req_trailer; ++ uint32_t req_trailer_sent; ++ bool verify_bitmask1; ++ bool verify_pcontext; + DATA_BLOB rpc_out; + DATA_BLOB reply_pdu; + }; + + static void rpc_api_pipe_req_write_done(struct tevent_req *subreq); + static void rpc_api_pipe_req_done(struct tevent_req *subreq); ++static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state); + static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, + bool *is_last_frag); + +@@ -1207,6 +1212,11 @@ static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, + goto post_status; + } + ++ status = prepare_verification_trailer(state); ++ if (!NT_STATUS_IS_OK(status)) { ++ goto post_status; ++ } ++ + status = prepare_next_frag(state, &is_last_frag); + if (!NT_STATUS_IS_OK(status)) { + goto post_status; +@@ -1241,25 +1251,164 @@ static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, + return NULL; + } + ++static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state) ++{ ++ struct pipe_auth_data *a = state->cli->auth; ++ struct dcerpc_sec_verification_trailer *t; ++ struct dcerpc_sec_vt *c = NULL; ++ struct ndr_push *ndr = NULL; ++ enum ndr_err_code ndr_err; ++ size_t align = 0; ++ size_t pad = 0; ++ ++ if (a == NULL) { ++ return NT_STATUS_OK; ++ } ++ ++ if (a->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) { ++ return NT_STATUS_OK; ++ } ++ ++ t = talloc_zero(state, struct dcerpc_sec_verification_trailer); ++ if (t == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ if (!a->verified_bitmask1) { ++ t->commands = talloc_realloc(t, t->commands, ++ struct dcerpc_sec_vt, ++ t->count.count + 1); ++ if (t->commands == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ c = &t->commands[t->count.count++]; ++ ZERO_STRUCTP(c); ++ ++ c->command = DCERPC_SEC_VT_COMMAND_BITMASK1; ++ if (a->client_hdr_signing) { ++ c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING; ++ } ++ state->verify_bitmask1 = true; ++ } ++ ++ if (!state->cli->verified_pcontext) { ++ t->commands = talloc_realloc(t, t->commands, ++ struct dcerpc_sec_vt, ++ t->count.count + 1); ++ if (t->commands == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ c = &t->commands[t->count.count++]; ++ ZERO_STRUCTP(c); ++ ++ c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT; ++ c->u.pcontext.abstract_syntax = state->cli->abstract_syntax; ++ c->u.pcontext.transfer_syntax = state->cli->transfer_syntax; ++ ++ state->verify_pcontext = true; ++ } ++ ++ if (!a->hdr_signing) { ++ t->commands = talloc_realloc(t, t->commands, ++ struct dcerpc_sec_vt, ++ t->count.count + 1); ++ if (t->commands == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ c = &t->commands[t->count.count++]; ++ ZERO_STRUCTP(c); ++ ++ c->command = DCERPC_SEC_VT_COMMAND_HEADER2; ++ c->u.header2.ptype = DCERPC_PKT_REQUEST; ++ c->u.header2.drep[0] = DCERPC_DREP_LE; ++ c->u.header2.drep[1] = 0; ++ c->u.header2.drep[2] = 0; ++ c->u.header2.drep[3] = 0; ++ c->u.header2.call_id = state->call_id; ++ c->u.header2.context_id = 0; ++ c->u.header2.opnum = state->op_num; ++ } ++ ++ if (t->count.count == 0) { ++ TALLOC_FREE(t); ++ return NT_STATUS_OK; ++ } ++ ++ c = &t->commands[t->count.count - 1]; ++ c->command |= DCERPC_SEC_VT_COMMAND_END; ++ ++ if (DEBUGLEVEL >= 10) { ++ NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t); ++ } ++ ++ ndr = ndr_push_init_ctx(state); ++ if (ndr == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr, ++ NDR_SCALARS | NDR_BUFFERS, ++ t); ++ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ++ return ndr_map_error2ntstatus(ndr_err); ++ } ++ state->req_trailer = ndr_push_blob(ndr); ++ ++ align = state->req_data->length & 0x3; ++ if (align > 0) { ++ pad = 4 - align; ++ } ++ if (pad > 0) { ++ bool ok; ++ uint8_t *p; ++ const uint8_t zeros[4] = { 0, }; ++ ++ ok = data_blob_append(ndr, &state->req_trailer, zeros, pad); ++ if (!ok) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ /* move the padding to the start */ ++ p = state->req_trailer.data; ++ memmove(p + pad, p, state->req_trailer.length - pad); ++ memset(p, 0, pad); ++ } ++ ++ return NT_STATUS_OK; ++} ++ + static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, + bool *is_last_frag) + { +- size_t data_sent_thistime; + size_t auth_len; + size_t frag_len; + uint8_t flags = 0; + size_t pad_len; + size_t data_left; ++ size_t data_thistime; ++ size_t trailer_left; ++ size_t trailer_thistime = 0; ++ size_t total_left; ++ size_t total_thistime; + NTSTATUS status; ++ bool ok; + union dcerpc_payload u; + + data_left = state->req_data->length - state->req_data_sent; ++ trailer_left = state->req_trailer.length - state->req_trailer_sent; ++ total_left = data_left + trailer_left; ++ if ((total_left < data_left) || (total_left < trailer_left)) { ++ /* ++ * overflow ++ */ ++ return NT_STATUS_INVALID_PARAMETER_MIX; ++ } + + status = dcerpc_guess_sizes(state->cli->auth, +- DCERPC_REQUEST_LENGTH, data_left, ++ DCERPC_REQUEST_LENGTH, total_left, + state->cli->max_xmit_frag, + CLIENT_NDR_PADDING_SIZE, +- &data_sent_thistime, ++ &total_thistime, + &frag_len, &auth_len, &pad_len); + if (!NT_STATUS_IS_OK(status)) { + return status; +@@ -1269,15 +1418,20 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, + flags = DCERPC_PFC_FLAG_FIRST; + } + +- if (data_sent_thistime == data_left) { ++ if (total_thistime == total_left) { + flags |= DCERPC_PFC_FLAG_LAST; + } + ++ data_thistime = MIN(total_thistime, data_left); ++ if (data_thistime < total_thistime) { ++ trailer_thistime = total_thistime - data_thistime; ++ } ++ + data_blob_free(&state->rpc_out); + + ZERO_STRUCT(u.request); + +- u.request.alloc_hint = data_left; ++ u.request.alloc_hint = total_left; + u.request.context_id = 0; + u.request.opnum = state->op_num; + +@@ -1297,11 +1451,26 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, + * at this stage */ + dcerpc_set_frag_length(&state->rpc_out, frag_len); + +- /* Copy in the data. */ +- if (!data_blob_append(NULL, &state->rpc_out, ++ if (data_thistime > 0) { ++ /* Copy in the data. */ ++ ok = data_blob_append(NULL, &state->rpc_out, + state->req_data->data + state->req_data_sent, +- data_sent_thistime)) { +- return NT_STATUS_NO_MEMORY; ++ data_thistime); ++ if (!ok) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ state->req_data_sent += data_thistime; ++ } ++ ++ if (trailer_thistime > 0) { ++ /* Copy in the verification trailer. */ ++ ok = data_blob_append(NULL, &state->rpc_out, ++ state->req_trailer.data + state->req_trailer_sent, ++ trailer_thistime); ++ if (!ok) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ state->req_trailer_sent += trailer_thistime; + } + + switch (state->cli->auth->auth_level) { +@@ -1321,7 +1490,6 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, + return NT_STATUS_INVALID_PARAMETER; + } + +- state->req_data_sent += data_sent_thistime; + *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0); + + return status; +@@ -1385,6 +1553,20 @@ static void rpc_api_pipe_req_done(struct tevent_req *subreq) + tevent_req_nterror(req, status); + return; + } ++ ++ if (state->cli->auth == NULL) { ++ tevent_req_done(req); ++ return; ++ } ++ ++ if (state->verify_bitmask1) { ++ state->cli->auth->verified_bitmask1 = true; ++ } ++ ++ if (state->verify_pcontext) { ++ state->cli->verified_pcontext = true; ++ } ++ + tevent_req_done(req); + } + +diff --git a/source3/rpc_client/rpc_client.h b/source3/rpc_client/rpc_client.h +index 6561b28..8024f01 100644 +--- a/source3/rpc_client/rpc_client.h ++++ b/source3/rpc_client/rpc_client.h +@@ -39,6 +39,7 @@ struct rpc_pipe_client { + + struct ndr_syntax_id abstract_syntax; + struct ndr_syntax_id transfer_syntax; ++ bool verified_pcontext; + + char *desthost; + char *srv_name_slash; +-- +1.9.3 + + +From 3df8f8c1dda254a85e4fa02b74d23a4802bc595c Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 18 Apr 2013 19:16:42 +0200 +Subject: [PATCH 162/249] libcli/auth: add netlogon_creds_cli* infrastructure + +This provides an abstraction to hide netlogon_creds_CredentialState, +which is stored in a node local tdb. + +Where the global state (netlogon_creds_CredentialState) between client and +server was only kept in memory (on the client side), we now use +the abstracted netlogon_creds_cli_context. + +We now use a node specific computer name in order to establish +individual netlogon sessions per node. + +If the caller wants to use some netlogon calls with credential chain +(struct netr_Authenticator), netlogon_creds_cli_lock*() is used +to get the current netlogon_creds_CredentialState in a g_lock'ed +fashion, a talloc_free() will release the lock. + +The locking is needed as there might be more than one process +(multiple winbindd child, cmdline tools) which want to talk +to a specific domain controller. The usage of netlogon_creds_CredentialState +needs to be serialized as it uses sequence numbers. + +LogonSamLogonEx doesn't use the credential chain, but for some operations +it needs the global session in order to de/encrypt individual fields. +It uses the lockless netlogon_creds_cli_get() and netlogon_creds_cli_validate() +functions, which just make sure the session hasn't changed between +get and validate. + +This is prepares the proper fix for a large number of bugs: +https://bugzilla.samba.org/show_bug.cgi?id=6563 +https://bugzilla.samba.org/show_bug.cgi?id=7944 +https://bugzilla.samba.org/show_bug.cgi?id=7945 +https://bugzilla.samba.org/show_bug.cgi?id=7568 +https://bugzilla.samba.org/show_bug.cgi?id=8599 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 6e6d9f9f12284ed06a21cc02080e436b7326065f) +--- + libcli/auth/netlogon_creds_cli.c | 2596 ++++++++++++++++++++++++++++++++++++++ + libcli/auth/netlogon_creds_cli.h | 138 ++ + libcli/auth/wscript_build | 4 + + 3 files changed, 2738 insertions(+) + create mode 100644 libcli/auth/netlogon_creds_cli.c + create mode 100644 libcli/auth/netlogon_creds_cli.h + +diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c +new file mode 100644 +index 0000000..75d6b2c +--- /dev/null ++++ b/libcli/auth/netlogon_creds_cli.c +@@ -0,0 +1,2596 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ module to store/fetch session keys for the schannel client ++ ++ Copyright (C) Stefan Metzmacher 2013 ++ ++ 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 . ++*/ ++ ++#include "includes.h" ++#include "system/filesys.h" ++#include ++#include "lib/util/tevent_ntstatus.h" ++#include "lib/dbwrap/dbwrap.h" ++#include "lib/dbwrap/dbwrap_rbt.h" ++#include "lib/util/util_tdb.h" ++#include "libcli/security/security.h" ++#include "../lib/param/param.h" ++#include "../libcli/auth/schannel.h" ++#include "../librpc/gen_ndr/ndr_schannel.h" ++#include "../librpc/gen_ndr/ndr_netlogon_c.h" ++#include "../librpc/gen_ndr/server_id.h" ++#include "netlogon_creds_cli.h" ++#include "source3/include/messages.h" ++#include "source3/include/g_lock.h" ++ ++struct netlogon_creds_cli_locked_state; ++ ++struct netlogon_creds_cli_context { ++ struct { ++ const char *computer; ++ const char *account; ++ uint32_t proposed_flags; ++ uint32_t required_flags; ++ enum netr_SchannelType type; ++ enum dcerpc_AuthLevel auth_level; ++ } client; ++ ++ struct { ++ const char *computer; ++ const char *netbios_domain; ++ uint32_t cached_flags; ++ bool try_validation6; ++ bool try_logon_ex; ++ bool try_logon_with; ++ } server; ++ ++ struct { ++ const char *key_name; ++ TDB_DATA key_data; ++ struct db_context *ctx; ++ struct g_lock_ctx *g_ctx; ++ struct netlogon_creds_cli_locked_state *locked_state; ++ } db; ++}; ++ ++struct netlogon_creds_cli_locked_state { ++ struct netlogon_creds_cli_context *context; ++ bool is_glocked; ++ struct netlogon_creds_CredentialState *creds; ++}; ++ ++static int netlogon_creds_cli_locked_state_destructor( ++ struct netlogon_creds_cli_locked_state *state) ++{ ++ struct netlogon_creds_cli_context *context = state->context; ++ ++ if (context == NULL) { ++ return 0; ++ } ++ ++ if (context->db.locked_state == state) { ++ context->db.locked_state = NULL; ++ } ++ ++ if (state->is_glocked) { ++ g_lock_unlock(context->db.g_ctx, ++ context->db.key_name); ++ } ++ ++ return 0; ++} ++ ++static NTSTATUS netlogon_creds_cli_context_common( ++ const char *client_computer, ++ const char *client_account, ++ enum netr_SchannelType type, ++ enum dcerpc_AuthLevel auth_level, ++ uint32_t proposed_flags, ++ uint32_t required_flags, ++ const char *server_computer, ++ const char *server_netbios_domain, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_cli_context **_context) ++{ ++ struct netlogon_creds_cli_context *context = NULL; ++ ++ *_context = NULL; ++ ++ context = talloc_zero(mem_ctx, struct netlogon_creds_cli_context); ++ if (context == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ context->client.computer = talloc_strdup(context, client_computer); ++ if (context->client.computer == NULL) { ++ talloc_free(context); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ context->client.account = talloc_strdup(context, client_account); ++ if (context->client.account == NULL) { ++ talloc_free(context); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ context->client.proposed_flags = proposed_flags; ++ context->client.required_flags = required_flags; ++ context->client.type = type; ++ context->client.auth_level = auth_level; ++ ++ context->server.computer = talloc_strdup(context, server_computer); ++ if (context->server.computer == NULL) { ++ talloc_free(context); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ context->server.netbios_domain = talloc_strdup(context, server_netbios_domain); ++ if (context->server.netbios_domain == NULL) { ++ talloc_free(context); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ context->db.key_name = talloc_asprintf(context, "CLI[%s/%s]/SRV[%s/%s]", ++ client_computer, ++ client_account, ++ server_computer, ++ server_netbios_domain); ++ if (context->db.key_name == NULL) { ++ talloc_free(context); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ context->db.key_data = string_term_tdb_data(context->db.key_name); ++ ++ *_context = context; ++ return NT_STATUS_OK; ++} ++ ++static struct db_context *netlogon_creds_cli_global_db; ++ ++NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx) ++{ ++ char *fname; ++ struct db_context *global_db; ++ ++ if (netlogon_creds_cli_global_db != NULL) { ++ return NT_STATUS_OK; ++ } ++ ++ fname = lpcfg_private_db_path(talloc_autofree_context(), lp_ctx, "netlogon_creds_cli"); ++ if (fname == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ global_db = dbwrap_local_open(talloc_autofree_context(), lp_ctx, ++ fname, 0, ++ TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, ++ O_RDWR|O_CREAT, ++ 0600, DBWRAP_LOCK_ORDER_2); ++ if (global_db == NULL) { ++ DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n", ++ fname, strerror(errno))); ++ talloc_free(fname); ++ return NT_STATUS_NO_MEMORY; ++ } ++ TALLOC_FREE(fname); ++ ++ netlogon_creds_cli_global_db = global_db; ++ return NT_STATUS_OK; ++} ++ ++NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, ++ struct messaging_context *msg_ctx, ++ const char *client_account, ++ enum netr_SchannelType type, ++ const char *server_computer, ++ const char *server_netbios_domain, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_cli_context **_context) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ NTSTATUS status; ++ struct netlogon_creds_cli_context *context = NULL; ++ const char *client_computer; ++ uint32_t proposed_flags; ++ uint32_t required_flags = 0; ++ bool reject_md5_servers = false; ++ bool require_strong_key = false; ++ int require_sign_or_seal = true; ++ bool seal_secure_channel = true; ++ enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; ++ bool neutralize_nt4_emulation = false; ++ struct server_id self = { ++ .vnn = NONCLUSTER_VNN, ++ .unique_id = SERVERID_UNIQUE_ID_NOT_TO_VERIFY, ++ }; ++ ++ if (msg_ctx != NULL) { ++ self = messaging_server_id(msg_ctx); ++ } ++ ++ *_context = NULL; ++ ++ if (self.vnn != NONCLUSTER_VNN) { ++ client_computer = talloc_asprintf(frame, ++ "%s_cluster_vnn_%u", ++ lpcfg_netbios_name(lp_ctx), ++ (unsigned)self.vnn); ++ if (client_computer == NULL) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ } else { ++ client_computer = lpcfg_netbios_name(lp_ctx); ++ } ++ ++ /* ++ * allow overwrite per domain ++ * reject md5 servers: ++ */ ++ //TODO: add lpcfp_reject_md5_servers() ++ reject_md5_servers = lpcfg_parm_bool(lp_ctx, NULL, ++ "__default__", ++ "reject md5 servers", ++ reject_md5_servers); ++ reject_md5_servers = lpcfg_parm_bool(lp_ctx, NULL, ++ "reject md5 servers", ++ server_netbios_domain, ++ reject_md5_servers); ++ ++ /* ++ * allow overwrite per domain ++ * require strong key: ++ */ ++ //TODO: add lpcfp_require_strong_key() ++ require_strong_key = lpcfg_parm_bool(lp_ctx, NULL, ++ "__default__", ++ "require strong key", ++ require_strong_key); ++ require_strong_key = lpcfg_parm_bool(lp_ctx, NULL, ++ "require strong key", ++ server_netbios_domain, ++ require_strong_key); ++ ++ /* ++ * allow overwrite per domain ++ * client schannel: ++ */ ++ require_sign_or_seal = lpcfg_client_schannel(lp_ctx); ++ require_sign_or_seal = lpcfg_parm_int(lp_ctx, NULL, ++ "client schannel", ++ server_netbios_domain, ++ require_sign_or_seal); ++ ++ /* ++ * allow overwrite per domain ++ * winbind sealed pipes: ++ */ ++ seal_secure_channel = lpcfg_winbind_sealed_pipes(lp_ctx); ++ seal_secure_channel = lpcfg_parm_bool(lp_ctx, NULL, ++ "winbind sealed pipes", ++ server_netbios_domain, ++ seal_secure_channel); ++ ++ /* ++ * allow overwrite per domain ++ * neutralize nt4 emulation: ++ */ ++ //TODO: add lpcfp_neutralize_nt4_emulation() ++ neutralize_nt4_emulation = lpcfg_parm_bool(lp_ctx, NULL, ++ "__default__", ++ "neutralize nt4 emulation", ++ neutralize_nt4_emulation); ++ neutralize_nt4_emulation = lpcfg_parm_bool(lp_ctx, NULL, ++ "neutralize nt4 emulation", ++ server_netbios_domain, ++ neutralize_nt4_emulation); ++ ++ proposed_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ proposed_flags |= NETLOGON_NEG_SUPPORTS_AES; ++ ++ switch (type) { ++ case SEC_CHAN_WKSTA: ++ if (lpcfg_security(lp_ctx) == SEC_ADS) { ++ /* ++ * AD domains should be secure ++ */ ++ required_flags |= NETLOGON_NEG_PASSWORD_SET2; ++ require_sign_or_seal = true; ++ require_strong_key = true; ++ } ++ break; ++ ++ case SEC_CHAN_DOMAIN: ++ break; ++ ++ case SEC_CHAN_DNS_DOMAIN: ++ /* ++ * AD domains should be secure ++ */ ++ required_flags |= NETLOGON_NEG_PASSWORD_SET2; ++ require_sign_or_seal = true; ++ require_strong_key = true; ++ neutralize_nt4_emulation = true; ++ break; ++ ++ case SEC_CHAN_BDC: ++ required_flags |= NETLOGON_NEG_PASSWORD_SET2; ++ require_sign_or_seal = true; ++ require_strong_key = true; ++ break; ++ ++ case SEC_CHAN_RODC: ++ required_flags |= NETLOGON_NEG_RODC_PASSTHROUGH; ++ required_flags |= NETLOGON_NEG_PASSWORD_SET2; ++ require_sign_or_seal = true; ++ require_strong_key = true; ++ neutralize_nt4_emulation = true; ++ break; ++ ++ default: ++ TALLOC_FREE(frame); ++ return NT_STATUS_INVALID_PARAMETER; ++ } ++ ++ if (neutralize_nt4_emulation) { ++ proposed_flags |= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION; ++ } ++ ++ if (require_sign_or_seal == false) { ++ proposed_flags &= ~NETLOGON_NEG_AUTHENTICATED_RPC; ++ } else { ++ required_flags |= NETLOGON_NEG_ARCFOUR; ++ required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC; ++ } ++ ++ if (reject_md5_servers) { ++ required_flags |= NETLOGON_NEG_ARCFOUR; ++ required_flags |= NETLOGON_NEG_PASSWORD_SET2; ++ required_flags |= NETLOGON_NEG_SUPPORTS_AES; ++ required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC; ++ } ++ ++ if (require_strong_key) { ++ required_flags |= NETLOGON_NEG_ARCFOUR; ++ required_flags |= NETLOGON_NEG_STRONG_KEYS; ++ required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC; ++ } ++ ++ proposed_flags |= required_flags; ++ ++ if (seal_secure_channel) { ++ auth_level = DCERPC_AUTH_LEVEL_PRIVACY; ++ } else { ++ auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; ++ } ++ ++ status = netlogon_creds_cli_context_common(client_computer, ++ client_account, ++ type, ++ auth_level, ++ proposed_flags, ++ required_flags, ++ server_computer, ++ server_netbios_domain, ++ mem_ctx, ++ &context); ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); ++ return status; ++ } ++ ++ if (msg_ctx != NULL) { ++ context->db.g_ctx = g_lock_ctx_init(context, msg_ctx); ++ if (context->db.g_ctx == NULL) { ++ TALLOC_FREE(context); ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ } ++ ++ if (netlogon_creds_cli_global_db != NULL) { ++ context->db.ctx = netlogon_creds_cli_global_db; ++ *_context = context; ++ TALLOC_FREE(frame); ++ return NT_STATUS_OK; ++ } ++ ++ status = netlogon_creds_cli_open_global_db(lp_ctx); ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(context); ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ context->db.ctx = netlogon_creds_cli_global_db; ++ *_context = context; ++ TALLOC_FREE(frame); ++ return NT_STATUS_OK; ++} ++ ++NTSTATUS netlogon_creds_cli_context_tmp(const char *client_computer, ++ const char *client_account, ++ enum netr_SchannelType type, ++ uint32_t proposed_flags, ++ uint32_t required_flags, ++ enum dcerpc_AuthLevel auth_level, ++ const char *server_computer, ++ const char *server_netbios_domain, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_cli_context **_context) ++{ ++ NTSTATUS status; ++ struct netlogon_creds_cli_context *context = NULL; ++ ++ *_context = NULL; ++ ++ status = netlogon_creds_cli_context_common(client_computer, ++ client_account, ++ type, ++ auth_level, ++ proposed_flags, ++ required_flags, ++ server_computer, ++ server_netbios_domain, ++ mem_ctx, ++ &context); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ context->db.ctx = db_open_rbt(context); ++ if (context->db.ctx == NULL) { ++ talloc_free(context); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ *_context = context; ++ return NT_STATUS_OK; ++} ++ ++NTSTATUS netlogon_creds_cli_context_copy( ++ const struct netlogon_creds_cli_context *src, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_cli_context **_dst) ++{ ++ struct netlogon_creds_cli_context *dst; ++ ++ dst = talloc_zero(mem_ctx, struct netlogon_creds_cli_context); ++ if (dst == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ *dst = *src; ++ ++ dst->client.computer = talloc_strdup(dst, src->client.computer); ++ if (dst->client.computer == NULL) { ++ TALLOC_FREE(dst); ++ return NT_STATUS_NO_MEMORY; ++ } ++ dst->client.account = talloc_strdup(dst, src->client.account); ++ if (dst->client.account == NULL) { ++ TALLOC_FREE(dst); ++ return NT_STATUS_NO_MEMORY; ++ } ++ dst->server.computer = talloc_strdup(dst, src->server.computer); ++ if (dst->server.computer == NULL) { ++ TALLOC_FREE(dst); ++ return NT_STATUS_NO_MEMORY; ++ } ++ dst->server.netbios_domain = talloc_strdup(dst, src->server.netbios_domain); ++ if (dst->server.netbios_domain == NULL) { ++ TALLOC_FREE(dst); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ dst->db.key_name = talloc_strdup(dst, src->db.key_name); ++ if (dst->db.key_name == NULL) { ++ TALLOC_FREE(dst); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ dst->db.key_data = string_term_tdb_data(dst->db.key_name); ++ ++ *_dst = dst; ++ return NT_STATUS_OK; ++} ++ ++enum dcerpc_AuthLevel netlogon_creds_cli_auth_level( ++ struct netlogon_creds_cli_context *context) ++{ ++ return context->client.auth_level; ++} ++ ++struct netlogon_creds_cli_fetch_state { ++ TALLOC_CTX *mem_ctx; ++ struct netlogon_creds_CredentialState *creds; ++ uint32_t required_flags; ++ NTSTATUS status; ++}; ++ ++static void netlogon_creds_cli_fetch_parser(TDB_DATA key, TDB_DATA data, ++ void *private_data) ++{ ++ struct netlogon_creds_cli_fetch_state *state = ++ (struct netlogon_creds_cli_fetch_state *)private_data; ++ enum ndr_err_code ndr_err; ++ DATA_BLOB blob; ++ uint32_t tmp_flags; ++ ++ state->creds = talloc_zero(state->mem_ctx, ++ struct netlogon_creds_CredentialState); ++ if (state->creds == NULL) { ++ state->status = NT_STATUS_NO_MEMORY; ++ return; ++ } ++ ++ blob.data = data.dptr; ++ blob.length = data.dsize; ++ ++ ndr_err = ndr_pull_struct_blob(&blob, state->creds, state->creds, ++ (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState); ++ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ++ TALLOC_FREE(state->creds); ++ state->status = ndr_map_error2ntstatus(ndr_err); ++ return; ++ } ++ ++ tmp_flags = state->creds->negotiate_flags; ++ tmp_flags &= state->required_flags; ++ if (tmp_flags != state->required_flags) { ++ TALLOC_FREE(state->creds); ++ state->status = NT_STATUS_DOWNGRADE_DETECTED; ++ return; ++ } ++ ++ state->status = NT_STATUS_OK; ++} ++ ++NTSTATUS netlogon_creds_cli_get(struct netlogon_creds_cli_context *context, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_CredentialState **_creds) ++{ ++ NTSTATUS status; ++ struct netlogon_creds_cli_fetch_state fstate = { ++ .mem_ctx = mem_ctx, ++ .status = NT_STATUS_INTERNAL_ERROR, ++ .required_flags = context->client.required_flags, ++ }; ++ static const struct netr_Credential zero_creds; ++ ++ *_creds = NULL; ++ ++ status = dbwrap_parse_record(context->db.ctx, ++ context->db.key_data, ++ netlogon_creds_cli_fetch_parser, ++ &fstate); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ status = fstate.status; ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ /* ++ * mark it as invalid for step operations. ++ */ ++ fstate.creds->sequence = 0; ++ fstate.creds->seed = zero_creds; ++ fstate.creds->client = zero_creds; ++ fstate.creds->server = zero_creds; ++ ++ if (context->server.cached_flags == fstate.creds->negotiate_flags) { ++ *_creds = fstate.creds; ++ return NT_STATUS_OK; ++ } ++ ++ /* ++ * It is really important to try SamLogonEx here, ++ * because multiple processes can talk to the same ++ * domain controller, without using the credential ++ * chain. ++ * ++ * With a normal SamLogon call, we must keep the ++ * credentials chain updated and intact between all ++ * users of the machine account (which would imply ++ * cross-node communication for every NTLM logon). ++ * ++ * The credentials chain is not per NETLOGON pipe ++ * connection, but globally on the server/client pair ++ * by computer name, while the client is free to use ++ * any computer name. We include the cluster node number ++ * in our computer name in order to avoid cross node ++ * coordination of the credential chain. ++ * ++ * It's also important to use NetlogonValidationSamInfo4 (6), ++ * because it relies on the rpc transport encryption ++ * and avoids using the global netlogon schannel ++ * session key to en/decrypt secret information ++ * like the user_session_key for network logons. ++ * ++ * [MS-APDS] 3.1.5.2 NTLM Network Logon ++ * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and ++ * NETLOGON_NEG_AUTHENTICATED_RPC set together ++ * are the indication that the server supports ++ * NetlogonValidationSamInfo4 (6). And it must only ++ * be used if "SealSecureChannel" is used. ++ * ++ * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY ++ * check is done in netlogon_creds_cli_LogonSamLogon*(). ++ */ ++ context->server.cached_flags = fstate.creds->negotiate_flags; ++ context->server.try_validation6 = true; ++ context->server.try_logon_ex = true; ++ context->server.try_logon_with = true; ++ ++ if (!(context->server.cached_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { ++ context->server.try_validation6 = false; ++ context->server.try_logon_ex = false; ++ } ++ if (!(context->server.cached_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) { ++ context->server.try_validation6 = false; ++ } ++ ++ *_creds = fstate.creds; ++ return NT_STATUS_OK; ++} ++ ++bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context *context, ++ const struct netlogon_creds_CredentialState *creds1) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct netlogon_creds_CredentialState *creds2; ++ DATA_BLOB blob1; ++ DATA_BLOB blob2; ++ NTSTATUS status; ++ enum ndr_err_code ndr_err; ++ int cmp; ++ ++ status = netlogon_creds_cli_get(context, frame, &creds2); ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); ++ return false; ++ } ++ ++ ndr_err = ndr_push_struct_blob(&blob1, frame, creds1, ++ (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState); ++ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ++ TALLOC_FREE(frame); ++ return false; ++ } ++ ++ ndr_err = ndr_push_struct_blob(&blob2, frame, creds2, ++ (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState); ++ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ++ TALLOC_FREE(frame); ++ return false; ++ } ++ ++ if (blob1.length != blob2.length) { ++ TALLOC_FREE(frame); ++ return false; ++ } ++ ++ cmp = memcmp(blob1.data, blob2.data, blob1.length); ++ if (cmp != 0) { ++ TALLOC_FREE(frame); ++ return false; ++ } ++ ++ TALLOC_FREE(frame); ++ return true; ++} ++ ++NTSTATUS netlogon_creds_cli_store(struct netlogon_creds_cli_context *context, ++ struct netlogon_creds_CredentialState **_creds) ++{ ++ struct netlogon_creds_CredentialState *creds = *_creds; ++ NTSTATUS status; ++ enum ndr_err_code ndr_err; ++ DATA_BLOB blob; ++ TDB_DATA data; ++ ++ *_creds = NULL; ++ ++ if (context->db.locked_state == NULL) { ++ /* ++ * this was not the result of netlogon_creds_cli_lock*() ++ */ ++ TALLOC_FREE(creds); ++ return NT_STATUS_INVALID_PAGE_PROTECTION; ++ } ++ ++ if (context->db.locked_state->creds != creds) { ++ /* ++ * this was not the result of netlogon_creds_cli_lock*() ++ */ ++ TALLOC_FREE(creds); ++ return NT_STATUS_INVALID_PAGE_PROTECTION; ++ } ++ ++ ndr_err = ndr_push_struct_blob(&blob, creds, creds, ++ (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState); ++ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ++ TALLOC_FREE(creds); ++ status = ndr_map_error2ntstatus(ndr_err); ++ return status; ++ } ++ ++ data.dptr = blob.data; ++ data.dsize = blob.length; ++ ++ status = dbwrap_store(context->db.ctx, ++ context->db.key_data, ++ data, TDB_REPLACE); ++ TALLOC_FREE(creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ return NT_STATUS_OK; ++} ++ ++NTSTATUS netlogon_creds_cli_delete(struct netlogon_creds_cli_context *context, ++ struct netlogon_creds_CredentialState **_creds) ++{ ++ struct netlogon_creds_CredentialState *creds = *_creds; ++ NTSTATUS status; ++ ++ *_creds = NULL; ++ ++ if (context->db.locked_state == NULL) { ++ /* ++ * this was not the result of netlogon_creds_cli_lock*() ++ */ ++ TALLOC_FREE(creds); ++ return NT_STATUS_INVALID_PAGE_PROTECTION; ++ } ++ ++ if (context->db.locked_state->creds != creds) { ++ /* ++ * this was not the result of netlogon_creds_cli_lock*() ++ */ ++ TALLOC_FREE(creds); ++ return NT_STATUS_INVALID_PAGE_PROTECTION; ++ } ++ ++ status = dbwrap_delete(context->db.ctx, ++ context->db.key_data); ++ TALLOC_FREE(creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ return NT_STATUS_OK; ++} ++ ++struct netlogon_creds_cli_lock_state { ++ struct netlogon_creds_cli_locked_state *locked_state; ++ struct netlogon_creds_CredentialState *creds; ++}; ++ ++static void netlogon_creds_cli_lock_done(struct tevent_req *subreq); ++static void netlogon_creds_cli_lock_fetch(struct tevent_req *req); ++ ++struct tevent_req *netlogon_creds_cli_lock_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct netlogon_creds_cli_context *context) ++{ ++ struct tevent_req *req; ++ struct netlogon_creds_cli_lock_state *state; ++ struct netlogon_creds_cli_locked_state *locked_state; ++ struct tevent_req *subreq; ++ ++ req = tevent_req_create(mem_ctx, &state, ++ struct netlogon_creds_cli_lock_state); ++ if (req == NULL) { ++ return NULL; ++ } ++ ++ if (context->db.locked_state != NULL) { ++ tevent_req_nterror(req, NT_STATUS_LOCK_NOT_GRANTED); ++ return tevent_req_post(req, ev); ++ } ++ ++ locked_state = talloc_zero(state, struct netlogon_creds_cli_locked_state); ++ if (tevent_req_nomem(locked_state, req)) { ++ return tevent_req_post(req, ev); ++ } ++ talloc_set_destructor(locked_state, ++ netlogon_creds_cli_locked_state_destructor); ++ locked_state->context = context; ++ ++ context->db.locked_state = locked_state; ++ state->locked_state = locked_state; ++ ++ if (context->db.g_ctx == NULL) { ++ netlogon_creds_cli_lock_fetch(req); ++ if (!tevent_req_is_in_progress(req)) { ++ return tevent_req_post(req, ev); ++ } ++ ++ return req; ++ } ++ ++ subreq = g_lock_lock_send(state, ev, ++ context->db.g_ctx, ++ context->db.key_name, ++ G_LOCK_WRITE); ++ if (tevent_req_nomem(subreq, req)) { ++ return tevent_req_post(req, ev); ++ } ++ tevent_req_set_callback(subreq, netlogon_creds_cli_lock_done, req); ++ ++ return req; ++} ++ ++static void netlogon_creds_cli_lock_done(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = ++ tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct netlogon_creds_cli_lock_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_lock_state); ++ NTSTATUS status; ++ ++ status = g_lock_lock_recv(subreq); ++ TALLOC_FREE(subreq); ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ state->locked_state->is_glocked = true; ++ ++ netlogon_creds_cli_lock_fetch(req); ++} ++ ++static void netlogon_creds_cli_lock_fetch(struct tevent_req *req) ++{ ++ struct netlogon_creds_cli_lock_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_lock_state); ++ struct netlogon_creds_cli_context *context = state->locked_state->context; ++ struct netlogon_creds_cli_fetch_state fstate = { ++ .status = NT_STATUS_INTERNAL_ERROR, ++ .required_flags = context->client.required_flags, ++ }; ++ NTSTATUS status; ++ ++ fstate.mem_ctx = state; ++ status = dbwrap_parse_record(context->db.ctx, ++ context->db.key_data, ++ netlogon_creds_cli_fetch_parser, ++ &fstate); ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ status = fstate.status; ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ ++ if (context->server.cached_flags == fstate.creds->negotiate_flags) { ++ state->creds = fstate.creds; ++ tevent_req_done(req); ++ return; ++ } ++ ++ context->server.cached_flags = fstate.creds->negotiate_flags; ++ context->server.try_validation6 = true; ++ context->server.try_logon_ex = true; ++ context->server.try_logon_with = true; ++ ++ if (!(context->server.cached_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { ++ context->server.try_validation6 = false; ++ context->server.try_logon_ex = false; ++ } ++ if (!(context->server.cached_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) { ++ context->server.try_validation6 = false; ++ } ++ ++ state->creds = fstate.creds; ++ tevent_req_done(req); ++ return; ++} ++ ++NTSTATUS netlogon_creds_cli_lock_recv(struct tevent_req *req, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_CredentialState **creds) ++{ ++ struct netlogon_creds_cli_lock_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_lock_state); ++ NTSTATUS status; ++ ++ if (tevent_req_is_nterror(req, &status)) { ++ tevent_req_received(req); ++ return status; ++ } ++ ++ talloc_steal(state->creds, state->locked_state); ++ state->locked_state->creds = state->creds; ++ *creds = talloc_move(mem_ctx, &state->creds); ++ tevent_req_received(req); ++ return NT_STATUS_OK; ++} ++ ++NTSTATUS netlogon_creds_cli_lock(struct netlogon_creds_cli_context *context, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_CredentialState **creds) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct tevent_context *ev; ++ struct tevent_req *req; ++ NTSTATUS status = NT_STATUS_NO_MEMORY; ++ ++ ev = samba_tevent_context_init(frame); ++ if (ev == NULL) { ++ goto fail; ++ } ++ req = netlogon_creds_cli_lock_send(frame, ev, context); ++ if (req == NULL) { ++ goto fail; ++ } ++ if (!tevent_req_poll_ntstatus(req, ev, &status)) { ++ goto fail; ++ } ++ status = netlogon_creds_cli_lock_recv(req, mem_ctx, creds); ++ fail: ++ TALLOC_FREE(frame); ++ return status; ++} ++ ++struct netlogon_creds_cli_auth_state { ++ struct tevent_context *ev; ++ struct netlogon_creds_cli_context *context; ++ struct dcerpc_binding_handle *binding_handle; ++ struct samr_Password current_nt_hash; ++ struct samr_Password previous_nt_hash; ++ struct samr_Password used_nt_hash; ++ char *srv_name_slash; ++ uint32_t current_flags; ++ struct netr_Credential client_challenge; ++ struct netr_Credential server_challenge; ++ struct netlogon_creds_CredentialState *creds; ++ struct netr_Credential client_credential; ++ struct netr_Credential server_credential; ++ uint32_t rid; ++ bool try_auth3; ++ bool try_auth2; ++ bool require_auth2; ++ bool try_previous_nt_hash; ++ struct netlogon_creds_cli_locked_state *locked_state; ++}; ++ ++static void netlogon_creds_cli_auth_locked(struct tevent_req *subreq); ++static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req); ++ ++struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b, ++ struct samr_Password current_nt_hash, ++ const struct samr_Password *previous_nt_hash) ++{ ++ struct tevent_req *req; ++ struct netlogon_creds_cli_auth_state *state; ++ struct netlogon_creds_cli_locked_state *locked_state; ++ NTSTATUS status; ++ ++ req = tevent_req_create(mem_ctx, &state, ++ struct netlogon_creds_cli_auth_state); ++ if (req == NULL) { ++ return NULL; ++ } ++ ++ state->ev = ev; ++ state->context = context; ++ state->binding_handle = b; ++ state->current_nt_hash = current_nt_hash; ++ if (previous_nt_hash != NULL) { ++ state->previous_nt_hash = *previous_nt_hash; ++ state->try_previous_nt_hash = true; ++ } ++ ++ if (context->db.locked_state != NULL) { ++ tevent_req_nterror(req, NT_STATUS_LOCK_NOT_GRANTED); ++ return tevent_req_post(req, ev); ++ } ++ ++ locked_state = talloc_zero(state, struct netlogon_creds_cli_locked_state); ++ if (tevent_req_nomem(locked_state, req)) { ++ return tevent_req_post(req, ev); ++ } ++ talloc_set_destructor(locked_state, ++ netlogon_creds_cli_locked_state_destructor); ++ locked_state->context = context; ++ ++ context->db.locked_state = locked_state; ++ state->locked_state = locked_state; ++ ++ state->srv_name_slash = talloc_asprintf(state, "\\\\%s", ++ context->server.computer); ++ if (tevent_req_nomem(state->srv_name_slash, req)) { ++ return tevent_req_post(req, ev); ++ } ++ ++ state->try_auth3 = true; ++ state->try_auth2 = true; ++ ++ if (context->client.required_flags != 0) { ++ state->require_auth2 = true; ++ } ++ ++ state->used_nt_hash = state->current_nt_hash; ++ state->current_flags = context->client.proposed_flags; ++ ++ if (context->db.g_ctx != NULL) { ++ struct tevent_req *subreq; ++ ++ subreq = g_lock_lock_send(state, ev, ++ context->db.g_ctx, ++ context->db.key_name, ++ G_LOCK_WRITE); ++ if (tevent_req_nomem(subreq, req)) { ++ return tevent_req_post(req, ev); ++ } ++ tevent_req_set_callback(subreq, ++ netlogon_creds_cli_auth_locked, ++ req); ++ ++ return req; ++ } ++ ++ status = dbwrap_delete(state->context->db.ctx, ++ state->context->db.key_data); ++ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { ++ status = NT_STATUS_OK; ++ } ++ if (tevent_req_nterror(req, status)) { ++ return tevent_req_post(req, ev); ++ } ++ ++ netlogon_creds_cli_auth_challenge_start(req); ++ if (!tevent_req_is_in_progress(req)) { ++ return tevent_req_post(req, ev); ++ } ++ ++ return req; ++} ++ ++static void netlogon_creds_cli_auth_locked(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = ++ tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct netlogon_creds_cli_auth_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_auth_state); ++ NTSTATUS status; ++ ++ status = g_lock_lock_recv(subreq); ++ TALLOC_FREE(subreq); ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ state->locked_state->is_glocked = true; ++ ++ status = dbwrap_delete(state->context->db.ctx, ++ state->context->db.key_data); ++ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { ++ status = NT_STATUS_OK; ++ } ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ ++ netlogon_creds_cli_auth_challenge_start(req); ++} ++ ++static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq); ++ ++static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req) ++{ ++ struct netlogon_creds_cli_auth_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_auth_state); ++ struct tevent_req *subreq; ++ ++ TALLOC_FREE(state->creds); ++ ++ generate_random_buffer(state->client_challenge.data, ++ sizeof(state->client_challenge.data)); ++ ++ subreq = dcerpc_netr_ServerReqChallenge_send(state, state->ev, ++ state->binding_handle, ++ state->srv_name_slash, ++ state->context->client.computer, ++ &state->client_challenge, ++ &state->server_challenge); ++ if (tevent_req_nomem(subreq, req)) { ++ return; ++ } ++ tevent_req_set_callback(subreq, ++ netlogon_creds_cli_auth_challenge_done, ++ req); ++} ++ ++static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq); ++ ++static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = ++ tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct netlogon_creds_cli_auth_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_auth_state); ++ NTSTATUS status; ++ NTSTATUS result; ++ ++ status = dcerpc_netr_ServerReqChallenge_recv(subreq, state, &result); ++ TALLOC_FREE(subreq); ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ if (tevent_req_nterror(req, result)) { ++ return; ++ } ++ ++ if (!state->try_auth3 && !state->try_auth2) { ++ state->current_flags = 0; ++ } ++ ++ /* Calculate the session key and client credentials */ ++ ++ state->creds = netlogon_creds_client_init(state, ++ state->context->client.account, ++ state->context->client.computer, ++ state->context->client.type, ++ &state->client_challenge, ++ &state->server_challenge, ++ &state->used_nt_hash, ++ &state->client_credential, ++ state->current_flags); ++ if (tevent_req_nomem(state->creds, req)) { ++ return; ++ } ++ ++ if (state->try_auth3) { ++ subreq = dcerpc_netr_ServerAuthenticate3_send(state, state->ev, ++ state->binding_handle, ++ state->srv_name_slash, ++ state->context->client.account, ++ state->context->client.type, ++ state->context->client.computer, ++ &state->client_credential, ++ &state->server_credential, ++ &state->creds->negotiate_flags, ++ &state->rid); ++ if (tevent_req_nomem(subreq, req)) { ++ return; ++ } ++ } else if (state->try_auth2) { ++ state->rid = 0; ++ ++ subreq = dcerpc_netr_ServerAuthenticate2_send(state, state->ev, ++ state->binding_handle, ++ state->srv_name_slash, ++ state->context->client.account, ++ state->context->client.type, ++ state->context->client.computer, ++ &state->client_credential, ++ &state->server_credential, ++ &state->creds->negotiate_flags); ++ if (tevent_req_nomem(subreq, req)) { ++ return; ++ } ++ } else { ++ state->rid = 0; ++ ++ subreq = dcerpc_netr_ServerAuthenticate_send(state, state->ev, ++ state->binding_handle, ++ state->srv_name_slash, ++ state->context->client.account, ++ state->context->client.type, ++ state->context->client.computer, ++ &state->client_credential, ++ &state->server_credential); ++ if (tevent_req_nomem(subreq, req)) { ++ return; ++ } ++ } ++ tevent_req_set_callback(subreq, ++ netlogon_creds_cli_auth_srvauth_done, ++ req); ++} ++ ++static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = ++ tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct netlogon_creds_cli_auth_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_auth_state); ++ NTSTATUS status; ++ NTSTATUS result; ++ bool ok; ++ enum ndr_err_code ndr_err; ++ DATA_BLOB blob; ++ TDB_DATA data; ++ uint32_t tmp_flags; ++ ++ if (state->try_auth3) { ++ status = dcerpc_netr_ServerAuthenticate3_recv(subreq, state, ++ &result); ++ TALLOC_FREE(subreq); ++ if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { ++ state->try_auth3 = false; ++ netlogon_creds_cli_auth_challenge_start(req); ++ return; ++ } ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ } else if (state->try_auth2) { ++ status = dcerpc_netr_ServerAuthenticate2_recv(subreq, state, ++ &result); ++ TALLOC_FREE(subreq); ++ if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { ++ state->try_auth2 = false; ++ if (state->require_auth2) { ++ status = NT_STATUS_DOWNGRADE_DETECTED; ++ tevent_req_nterror(req, status); ++ return; ++ } ++ netlogon_creds_cli_auth_challenge_start(req); ++ return; ++ } ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ } else { ++ status = dcerpc_netr_ServerAuthenticate_recv(subreq, state, ++ &result); ++ TALLOC_FREE(subreq); ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ } ++ ++ if (!NT_STATUS_IS_OK(result) && ++ !NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) ++ { ++ tevent_req_nterror(req, result); ++ return; ++ } ++ ++ tmp_flags = state->creds->negotiate_flags; ++ tmp_flags &= state->context->client.required_flags; ++ if (tmp_flags != state->context->client.required_flags) { ++ if (NT_STATUS_IS_OK(result)) { ++ tevent_req_nterror(req, NT_STATUS_DOWNGRADE_DETECTED); ++ return; ++ } ++ tevent_req_nterror(req, result); ++ return; ++ } ++ ++ if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) { ++ ++ tmp_flags = state->context->client.proposed_flags; ++ if ((state->current_flags == tmp_flags) && ++ (state->creds->negotiate_flags != tmp_flags)) ++ { ++ /* ++ * lets retry with the negotiated flags ++ */ ++ state->current_flags = state->creds->negotiate_flags; ++ netlogon_creds_cli_auth_challenge_start(req); ++ return; ++ } ++ ++ if (!state->try_previous_nt_hash) { ++ /* ++ * we already retried, giving up... ++ */ ++ tevent_req_nterror(req, result); ++ return; ++ } ++ ++ /* ++ * lets retry with the old nt hash. ++ */ ++ state->try_previous_nt_hash = false; ++ state->used_nt_hash = state->previous_nt_hash; ++ state->current_flags = state->context->client.proposed_flags; ++ netlogon_creds_cli_auth_challenge_start(req); ++ return; ++ } ++ ++ ok = netlogon_creds_client_check(state->creds, ++ &state->server_credential); ++ if (!ok) { ++ tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); ++ return; ++ } ++ ++ ndr_err = ndr_push_struct_blob(&blob, state, state->creds, ++ (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState); ++ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ++ status = ndr_map_error2ntstatus(ndr_err); ++ tevent_req_nterror(req, status); ++ return; ++ } ++ ++ data.dptr = blob.data; ++ data.dsize = blob.length; ++ ++ status = dbwrap_store(state->context->db.ctx, ++ state->context->db.key_data, ++ data, TDB_REPLACE); ++ TALLOC_FREE(state->locked_state); ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ ++ tevent_req_done(req); ++} ++ ++NTSTATUS netlogon_creds_cli_auth_recv(struct tevent_req *req) ++{ ++ NTSTATUS status; ++ ++ if (tevent_req_is_nterror(req, &status)) { ++ tevent_req_received(req); ++ return status; ++ } ++ ++ tevent_req_received(req); ++ return NT_STATUS_OK; ++} ++ ++NTSTATUS netlogon_creds_cli_auth(struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b, ++ struct samr_Password current_nt_hash, ++ const struct samr_Password *previous_nt_hash) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct tevent_context *ev; ++ struct tevent_req *req; ++ NTSTATUS status = NT_STATUS_NO_MEMORY; ++ ++ ev = samba_tevent_context_init(frame); ++ if (ev == NULL) { ++ goto fail; ++ } ++ req = netlogon_creds_cli_auth_send(frame, ev, context, b, ++ current_nt_hash, ++ previous_nt_hash); ++ if (req == NULL) { ++ goto fail; ++ } ++ if (!tevent_req_poll_ntstatus(req, ev, &status)) { ++ goto fail; ++ } ++ status = netlogon_creds_cli_auth_recv(req); ++ fail: ++ TALLOC_FREE(frame); ++ return status; ++} ++ ++struct netlogon_creds_cli_check_state { ++ struct tevent_context *ev; ++ struct netlogon_creds_cli_context *context; ++ struct dcerpc_binding_handle *binding_handle; ++ ++ char *srv_name_slash; ++ ++ union netr_Capabilities caps; ++ ++ struct netlogon_creds_CredentialState *creds; ++ struct netlogon_creds_CredentialState tmp_creds; ++ struct netr_Authenticator req_auth; ++ struct netr_Authenticator rep_auth; ++}; ++ ++static void netlogon_creds_cli_check_cleanup(struct tevent_req *req, ++ NTSTATUS status); ++static void netlogon_creds_cli_check_locked(struct tevent_req *subreq); ++ ++struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b) ++{ ++ struct tevent_req *req; ++ struct netlogon_creds_cli_check_state *state; ++ struct tevent_req *subreq; ++ enum dcerpc_AuthType auth_type; ++ enum dcerpc_AuthLevel auth_level; ++ ++ req = tevent_req_create(mem_ctx, &state, ++ struct netlogon_creds_cli_check_state); ++ if (req == NULL) { ++ return NULL; ++ } ++ ++ state->ev = ev; ++ state->context = context; ++ state->binding_handle = b; ++ ++ state->srv_name_slash = talloc_asprintf(state, "\\\\%s", ++ context->server.computer); ++ if (tevent_req_nomem(state->srv_name_slash, req)) { ++ return tevent_req_post(req, ev); ++ } ++ ++ dcerpc_binding_handle_auth_info(state->binding_handle, ++ &auth_type, &auth_level); ++ ++ if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { ++ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); ++ return tevent_req_post(req, ev); ++ } ++ ++ switch (auth_level) { ++ case DCERPC_AUTH_LEVEL_INTEGRITY: ++ case DCERPC_AUTH_LEVEL_PRIVACY: ++ break; ++ default: ++ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); ++ return tevent_req_post(req, ev); ++ } ++ ++ subreq = netlogon_creds_cli_lock_send(state, state->ev, ++ state->context); ++ if (tevent_req_nomem(subreq, req)) { ++ return tevent_req_post(req, ev); ++ } ++ ++ tevent_req_set_callback(subreq, ++ netlogon_creds_cli_check_locked, ++ req); ++ ++ return req; ++} ++ ++static void netlogon_creds_cli_check_cleanup(struct tevent_req *req, ++ NTSTATUS status) ++{ ++ struct netlogon_creds_cli_check_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_check_state); ++ ++ if (state->creds == NULL) { ++ return; ++ } ++ ++ if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) && ++ !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) && ++ !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) && ++ !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) && ++ !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) { ++ TALLOC_FREE(state->creds); ++ return; ++ } ++ ++ netlogon_creds_cli_delete(state->context, &state->creds); ++} ++ ++static void netlogon_creds_cli_check_caps(struct tevent_req *subreq); ++ ++static void netlogon_creds_cli_check_locked(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = ++ tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct netlogon_creds_cli_check_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_check_state); ++ NTSTATUS status; ++ ++ status = netlogon_creds_cli_lock_recv(subreq, state, ++ &state->creds); ++ TALLOC_FREE(subreq); ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ ++ /* ++ * we defer all callbacks in order to cleanup ++ * the database record. ++ */ ++ tevent_req_defer_callback(req, state->ev); ++ ++ state->tmp_creds = *state->creds; ++ netlogon_creds_client_authenticator(&state->tmp_creds, ++ &state->req_auth); ++ ZERO_STRUCT(state->rep_auth); ++ ++ subreq = dcerpc_netr_LogonGetCapabilities_send(state, state->ev, ++ state->binding_handle, ++ state->srv_name_slash, ++ state->context->client.computer, ++ &state->req_auth, ++ &state->rep_auth, ++ 1, ++ &state->caps); ++ if (tevent_req_nomem(subreq, req)) { ++ status = NT_STATUS_NO_MEMORY; ++ netlogon_creds_cli_check_cleanup(req, status); ++ return; ++ } ++ tevent_req_set_callback(subreq, ++ netlogon_creds_cli_check_caps, ++ req); ++} ++ ++static void netlogon_creds_cli_check_caps(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = ++ tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct netlogon_creds_cli_check_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_check_state); ++ NTSTATUS status; ++ NTSTATUS result; ++ bool ok; ++ ++ status = dcerpc_netr_LogonGetCapabilities_recv(subreq, state, ++ &result); ++ TALLOC_FREE(subreq); ++ if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { ++ /* ++ * Note that the negotiated flags are already checked ++ * for our required flags after the ServerAuthenticate3/2 call. ++ */ ++ uint32_t negotiated = state->tmp_creds.negotiate_flags; ++ ++ if (negotiated & NETLOGON_NEG_SUPPORTS_AES) { ++ /* ++ * If we have negotiated NETLOGON_NEG_SUPPORTS_AES ++ * already, we expect this to work! ++ */ ++ status = NT_STATUS_DOWNGRADE_DETECTED; ++ tevent_req_nterror(req, status); ++ netlogon_creds_cli_check_cleanup(req, status); ++ return; ++ } ++ ++ if (negotiated & NETLOGON_NEG_STRONG_KEYS) { ++ /* ++ * If we have negotiated NETLOGON_NEG_STRONG_KEYS ++ * we expect this to work at least as far as the ++ * NOT_SUPPORTED error handled below! ++ * ++ * NT 4.0 and Old Samba servers are not ++ * allowed without "require strong key = no" ++ */ ++ status = NT_STATUS_DOWNGRADE_DETECTED; ++ tevent_req_nterror(req, status); ++ netlogon_creds_cli_check_cleanup(req, status); ++ return; ++ } ++ ++ /* ++ * If we not require NETLOGON_NEG_SUPPORTS_AES or ++ * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore ++ * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE. ++ * ++ * This is needed against NT 4.0 and old Samba servers. ++ * ++ * As we're using DCERPC_AUTH_TYPE_SCHANNEL with ++ * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY ++ * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE ++ * with the next request as the sequence number processing ++ * gets out of sync. ++ */ ++ netlogon_creds_cli_check_cleanup(req, result); ++ tevent_req_done(req); ++ return; ++ } ++ if (tevent_req_nterror(req, status)) { ++ netlogon_creds_cli_check_cleanup(req, status); ++ return; ++ } ++ ++ if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) { ++ /* ++ * Note that the negotiated flags are already checked ++ * for our required flags after the ServerAuthenticate3/2 call. ++ */ ++ uint32_t negotiated = state->tmp_creds.negotiate_flags; ++ ++ if (negotiated & NETLOGON_NEG_SUPPORTS_AES) { ++ /* ++ * If we have negotiated NETLOGON_NEG_SUPPORTS_AES ++ * already, we expect this to work! ++ */ ++ status = NT_STATUS_DOWNGRADE_DETECTED; ++ tevent_req_nterror(req, status); ++ netlogon_creds_cli_check_cleanup(req, status); ++ return; ++ } ++ ++ /* ++ * This is ok, the server does not support ++ * NETLOGON_NEG_SUPPORTS_AES. ++ * ++ * netr_LogonGetCapabilities() was ++ * netr_LogonDummyRoutine1() before ++ * NETLOGON_NEG_SUPPORTS_AES was invented. ++ */ ++ netlogon_creds_cli_check_cleanup(req, result); ++ tevent_req_done(req); ++ return; ++ } ++ ++ ok = netlogon_creds_client_check(&state->tmp_creds, ++ &state->rep_auth.cred); ++ if (!ok) { ++ status = NT_STATUS_ACCESS_DENIED; ++ tevent_req_nterror(req, status); ++ netlogon_creds_cli_check_cleanup(req, status); ++ return; ++ } ++ ++ if (tevent_req_nterror(req, result)) { ++ netlogon_creds_cli_check_cleanup(req, result); ++ return; ++ } ++ ++ if (state->caps.server_capabilities != state->tmp_creds.negotiate_flags) { ++ status = NT_STATUS_DOWNGRADE_DETECTED; ++ tevent_req_nterror(req, status); ++ netlogon_creds_cli_check_cleanup(req, status); ++ return; ++ } ++ ++ /* ++ * This is the key check that makes this check secure. If we ++ * get OK here (rather than NOT_SUPPORTED), then the server ++ * did support AES. If the server only proposed STRONG_KEYS ++ * and not AES, then it should have failed with ++ * NOT_IMPLEMENTED. We always send AES as a client, so the ++ * server should always have returned it. ++ */ ++ if (!(state->caps.server_capabilities & NETLOGON_NEG_SUPPORTS_AES)) { ++ status = NT_STATUS_DOWNGRADE_DETECTED; ++ tevent_req_nterror(req, status); ++ netlogon_creds_cli_check_cleanup(req, status); ++ return; ++ } ++ ++ *state->creds = state->tmp_creds; ++ status = netlogon_creds_cli_store(state->context, ++ &state->creds); ++ netlogon_creds_cli_check_cleanup(req, status); ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ ++ tevent_req_done(req); ++} ++ ++NTSTATUS netlogon_creds_cli_check_recv(struct tevent_req *req) ++{ ++ NTSTATUS status; ++ ++ if (tevent_req_is_nterror(req, &status)) { ++ netlogon_creds_cli_check_cleanup(req, status); ++ tevent_req_received(req); ++ return status; ++ } ++ ++ tevent_req_received(req); ++ return NT_STATUS_OK; ++} ++ ++NTSTATUS netlogon_creds_cli_check(struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct tevent_context *ev; ++ struct tevent_req *req; ++ NTSTATUS status = NT_STATUS_NO_MEMORY; ++ ++ ev = samba_tevent_context_init(frame); ++ if (ev == NULL) { ++ goto fail; ++ } ++ req = netlogon_creds_cli_check_send(frame, ev, context, b); ++ if (req == NULL) { ++ goto fail; ++ } ++ if (!tevent_req_poll_ntstatus(req, ev, &status)) { ++ goto fail; ++ } ++ status = netlogon_creds_cli_check_recv(req); ++ fail: ++ TALLOC_FREE(frame); ++ return status; ++} ++ ++struct netlogon_creds_cli_ServerPasswordSet_state { ++ struct tevent_context *ev; ++ struct netlogon_creds_cli_context *context; ++ struct dcerpc_binding_handle *binding_handle; ++ uint32_t old_timeout; ++ ++ char *srv_name_slash; ++ enum dcerpc_AuthType auth_type; ++ enum dcerpc_AuthLevel auth_level; ++ ++ struct samr_CryptPassword samr_crypt_password; ++ struct netr_CryptPassword netr_crypt_password; ++ struct samr_Password samr_password; ++ ++ struct netlogon_creds_CredentialState *creds; ++ struct netlogon_creds_CredentialState tmp_creds; ++ struct netr_Authenticator req_auth; ++ struct netr_Authenticator rep_auth; ++}; ++ ++static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req, ++ NTSTATUS status); ++static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq); ++ ++struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b, ++ const char *new_password, ++ const uint32_t *new_version) ++{ ++ struct tevent_req *req; ++ struct netlogon_creds_cli_ServerPasswordSet_state *state; ++ struct tevent_req *subreq; ++ bool ok; ++ ++ req = tevent_req_create(mem_ctx, &state, ++ struct netlogon_creds_cli_ServerPasswordSet_state); ++ if (req == NULL) { ++ return NULL; ++ } ++ ++ state->ev = ev; ++ state->context = context; ++ state->binding_handle = b; ++ ++ /* ++ * netr_ServerPasswordSet ++ */ ++ E_md4hash(new_password, state->samr_password.hash); ++ ++ /* ++ * netr_ServerPasswordSet2 ++ */ ++ ok = encode_pw_buffer(state->samr_crypt_password.data, ++ new_password, STR_UNICODE); ++ if (!ok) { ++ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); ++ return tevent_req_post(req, ev); ++ } ++ ++ if (new_version != NULL) { ++ struct NL_PASSWORD_VERSION version; ++ uint32_t len = IVAL(state->samr_crypt_password.data, 512); ++ uint32_t ofs = 512 - len; ++ uint8_t *p; ++ ++ if (ofs < 12) { ++ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); ++ return tevent_req_post(req, ev); ++ } ++ ofs -= 12; ++ ++ version.ReservedField = 0; ++ version.PasswordVersionNumber = *new_version; ++ version.PasswordVersionPresent = ++ NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT; ++ ++ p = state->samr_crypt_password.data + ofs; ++ SIVAL(p, 0, version.ReservedField); ++ SIVAL(p, 4, version.PasswordVersionNumber); ++ SIVAL(p, 8, version.PasswordVersionPresent); ++ } ++ ++ state->srv_name_slash = talloc_asprintf(state, "\\\\%s", ++ context->server.computer); ++ if (tevent_req_nomem(state->srv_name_slash, req)) { ++ return tevent_req_post(req, ev); ++ } ++ ++ dcerpc_binding_handle_auth_info(state->binding_handle, ++ &state->auth_type, ++ &state->auth_level); ++ ++ subreq = netlogon_creds_cli_lock_send(state, state->ev, ++ state->context); ++ if (tevent_req_nomem(subreq, req)) { ++ return tevent_req_post(req, ev); ++ } ++ ++ tevent_req_set_callback(subreq, ++ netlogon_creds_cli_ServerPasswordSet_locked, ++ req); ++ ++ return req; ++} ++ ++static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req, ++ NTSTATUS status) ++{ ++ struct netlogon_creds_cli_ServerPasswordSet_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_ServerPasswordSet_state); ++ ++ if (state->creds == NULL) { ++ return; ++ } ++ ++ dcerpc_binding_handle_set_timeout(state->binding_handle, ++ state->old_timeout); ++ ++ if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) && ++ !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) && ++ !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) && ++ !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) && ++ !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) { ++ TALLOC_FREE(state->creds); ++ return; ++ } ++ ++ netlogon_creds_cli_delete(state->context, &state->creds); ++} ++ ++static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq); ++ ++static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = ++ tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct netlogon_creds_cli_ServerPasswordSet_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_ServerPasswordSet_state); ++ NTSTATUS status; ++ ++ status = netlogon_creds_cli_lock_recv(subreq, state, ++ &state->creds); ++ TALLOC_FREE(subreq); ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ ++ if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { ++ switch (state->auth_level) { ++ case DCERPC_AUTH_LEVEL_INTEGRITY: ++ case DCERPC_AUTH_LEVEL_PRIVACY: ++ break; ++ default: ++ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); ++ return; ++ } ++ } else { ++ uint32_t tmp = state->creds->negotiate_flags; ++ ++ if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) { ++ /* ++ * if DCERPC_AUTH_TYPE_SCHANNEL is supported ++ * it should be used, which means ++ * we had a chance to verify no downgrade ++ * happened. ++ * ++ * This relies on netlogon_creds_cli_check* ++ * being called before, as first request after ++ * the DCERPC bind. ++ */ ++ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); ++ return; ++ } ++ } ++ ++ state->old_timeout = dcerpc_binding_handle_set_timeout( ++ state->binding_handle, 600000); ++ ++ /* ++ * we defer all callbacks in order to cleanup ++ * the database record. ++ */ ++ tevent_req_defer_callback(req, state->ev); ++ ++ state->tmp_creds = *state->creds; ++ netlogon_creds_client_authenticator(&state->tmp_creds, ++ &state->req_auth); ++ ZERO_STRUCT(state->rep_auth); ++ ++ if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) { ++ ++ if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { ++ netlogon_creds_aes_encrypt(&state->tmp_creds, ++ state->samr_crypt_password.data, ++ 516); ++ } else { ++ netlogon_creds_arcfour_crypt(&state->tmp_creds, ++ state->samr_crypt_password.data, ++ 516); ++ } ++ ++ memcpy(state->netr_crypt_password.data, ++ state->samr_crypt_password.data, 512); ++ state->netr_crypt_password.length = ++ IVAL(state->samr_crypt_password.data, 512); ++ ++ subreq = dcerpc_netr_ServerPasswordSet2_send(state, state->ev, ++ state->binding_handle, ++ state->srv_name_slash, ++ state->tmp_creds.account_name, ++ state->tmp_creds.secure_channel_type, ++ state->tmp_creds.computer_name, ++ &state->req_auth, ++ &state->rep_auth, ++ &state->netr_crypt_password); ++ if (tevent_req_nomem(subreq, req)) { ++ status = NT_STATUS_NO_MEMORY; ++ netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); ++ return; ++ } ++ } else { ++ netlogon_creds_des_encrypt(&state->tmp_creds, ++ &state->samr_password); ++ ++ subreq = dcerpc_netr_ServerPasswordSet_send(state, state->ev, ++ state->binding_handle, ++ state->srv_name_slash, ++ state->tmp_creds.account_name, ++ state->tmp_creds.secure_channel_type, ++ state->tmp_creds.computer_name, ++ &state->req_auth, ++ &state->rep_auth, ++ &state->samr_password); ++ if (tevent_req_nomem(subreq, req)) { ++ status = NT_STATUS_NO_MEMORY; ++ netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); ++ return; ++ } ++ } ++ ++ tevent_req_set_callback(subreq, ++ netlogon_creds_cli_ServerPasswordSet_done, ++ req); ++} ++ ++static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = ++ tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct netlogon_creds_cli_ServerPasswordSet_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_ServerPasswordSet_state); ++ NTSTATUS status; ++ NTSTATUS result; ++ bool ok; ++ ++ if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) { ++ status = dcerpc_netr_ServerPasswordSet2_recv(subreq, state, ++ &result); ++ TALLOC_FREE(subreq); ++ if (tevent_req_nterror(req, status)) { ++ netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); ++ return; ++ } ++ } else { ++ status = dcerpc_netr_ServerPasswordSet_recv(subreq, state, ++ &result); ++ TALLOC_FREE(subreq); ++ if (tevent_req_nterror(req, status)) { ++ netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); ++ return; ++ } ++ } ++ ++ ok = netlogon_creds_client_check(&state->tmp_creds, ++ &state->rep_auth.cred); ++ if (!ok) { ++ status = NT_STATUS_ACCESS_DENIED; ++ tevent_req_nterror(req, status); ++ netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); ++ return; ++ } ++ ++ if (tevent_req_nterror(req, result)) { ++ netlogon_creds_cli_ServerPasswordSet_cleanup(req, result); ++ return; ++ } ++ ++ dcerpc_binding_handle_set_timeout(state->binding_handle, ++ state->old_timeout); ++ ++ *state->creds = state->tmp_creds; ++ status = netlogon_creds_cli_store(state->context, ++ &state->creds); ++ if (tevent_req_nterror(req, status)) { ++ netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); ++ return; ++ } ++ ++ tevent_req_done(req); ++} ++ ++NTSTATUS netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req *req) ++{ ++ NTSTATUS status; ++ ++ if (tevent_req_is_nterror(req, &status)) { ++ netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); ++ tevent_req_received(req); ++ return status; ++ } ++ ++ tevent_req_received(req); ++ return NT_STATUS_OK; ++} ++ ++NTSTATUS netlogon_creds_cli_ServerPasswordSet( ++ struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b, ++ const char *new_password, ++ const uint32_t *new_version) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct tevent_context *ev; ++ struct tevent_req *req; ++ NTSTATUS status = NT_STATUS_NO_MEMORY; ++ ++ ev = samba_tevent_context_init(frame); ++ if (ev == NULL) { ++ goto fail; ++ } ++ req = netlogon_creds_cli_ServerPasswordSet_send(frame, ev, context, b, ++ new_password, ++ new_version); ++ if (req == NULL) { ++ goto fail; ++ } ++ if (!tevent_req_poll_ntstatus(req, ev, &status)) { ++ goto fail; ++ } ++ status = netlogon_creds_cli_ServerPasswordSet_recv(req); ++ fail: ++ TALLOC_FREE(frame); ++ return status; ++} ++ ++struct netlogon_creds_cli_LogonSamLogon_state { ++ struct tevent_context *ev; ++ struct netlogon_creds_cli_context *context; ++ struct dcerpc_binding_handle *binding_handle; ++ ++ char *srv_name_slash; ++ ++ enum netr_LogonInfoClass logon_level; ++ const union netr_LogonLevel *const_logon; ++ union netr_LogonLevel *logon; ++ uint32_t flags; ++ ++ uint16_t validation_level; ++ union netr_Validation *validation; ++ uint8_t authoritative; ++ ++ /* ++ * do we need encryption at the application layer? ++ */ ++ bool user_encrypt; ++ bool try_logon_ex; ++ bool try_validation6; ++ ++ /* ++ * the read only credentials before we started the operation ++ */ ++ struct netlogon_creds_CredentialState *ro_creds; ++ ++ struct netlogon_creds_CredentialState *lk_creds; ++ ++ struct netlogon_creds_CredentialState tmp_creds; ++ struct netr_Authenticator req_auth; ++ struct netr_Authenticator rep_auth; ++}; ++ ++static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req); ++static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req, ++ NTSTATUS status); ++ ++struct tevent_req *netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b, ++ enum netr_LogonInfoClass logon_level, ++ const union netr_LogonLevel *logon, ++ uint32_t flags) ++{ ++ struct tevent_req *req; ++ struct netlogon_creds_cli_LogonSamLogon_state *state; ++ ++ req = tevent_req_create(mem_ctx, &state, ++ struct netlogon_creds_cli_LogonSamLogon_state); ++ if (req == NULL) { ++ return NULL; ++ } ++ ++ state->ev = ev; ++ state->context = context; ++ state->binding_handle = b; ++ ++ state->logon_level = logon_level; ++ state->const_logon = logon; ++ state->flags = flags; ++ ++ state->srv_name_slash = talloc_asprintf(state, "\\\\%s", ++ context->server.computer); ++ if (tevent_req_nomem(state->srv_name_slash, req)) { ++ return tevent_req_post(req, ev); ++ } ++ ++ switch (logon_level) { ++ case NetlogonInteractiveInformation: ++ case NetlogonInteractiveTransitiveInformation: ++ case NetlogonServiceInformation: ++ case NetlogonServiceTransitiveInformation: ++ case NetlogonGenericInformation: ++ state->user_encrypt = true; ++ break; ++ ++ case NetlogonNetworkInformation: ++ case NetlogonNetworkTransitiveInformation: ++ break; ++ } ++ ++ state->validation = talloc_zero(state, union netr_Validation); ++ if (tevent_req_nomem(state->validation, req)) { ++ return tevent_req_post(req, ev); ++ } ++ ++ netlogon_creds_cli_LogonSamLogon_start(req); ++ if (!tevent_req_is_in_progress(req)) { ++ return tevent_req_post(req, ev); ++ } ++ ++ /* ++ * we defer all callbacks in order to cleanup ++ * the database record. ++ */ ++ tevent_req_defer_callback(req, state->ev); ++ return req; ++} ++ ++static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req, ++ NTSTATUS status) ++{ ++ struct netlogon_creds_cli_LogonSamLogon_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_LogonSamLogon_state); ++ ++ if (state->lk_creds == NULL) { ++ return; ++ } ++ ++ if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { ++ /* ++ * This is a hack to recover from a bug in old ++ * Samba servers, when LogonSamLogonEx() fails: ++ * ++ * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX. ++ * ++ * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE. ++ * ++ * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE, ++ * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR ++ * If the sign/seal check fails. ++ * ++ * In that case we need to cleanup the netlogon session. ++ * ++ * It's the job of the caller to disconnect the current ++ * connection, if netlogon_creds_cli_LogonSamLogon() ++ * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE. ++ */ ++ if (!state->context->server.try_logon_with) { ++ status = NT_STATUS_NETWORK_ACCESS_DENIED; ++ } ++ } ++ ++ if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) && ++ !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) && ++ !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) && ++ !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) && ++ !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) { ++ TALLOC_FREE(state->lk_creds); ++ return; ++ } ++ ++ netlogon_creds_cli_delete(state->context, &state->lk_creds); ++} ++ ++static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq); ++ ++static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req) ++{ ++ struct netlogon_creds_cli_LogonSamLogon_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_LogonSamLogon_state); ++ struct tevent_req *subreq; ++ NTSTATUS status; ++ enum dcerpc_AuthType auth_type; ++ enum dcerpc_AuthLevel auth_level; ++ ++ TALLOC_FREE(state->ro_creds); ++ TALLOC_FREE(state->logon); ++ ZERO_STRUCTP(state->validation); ++ ++ dcerpc_binding_handle_auth_info(state->binding_handle, ++ &auth_type, &auth_level); ++ ++ state->try_logon_ex = state->context->server.try_logon_ex; ++ state->try_validation6 = state->context->server.try_validation6; ++ ++ if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { ++ state->try_logon_ex = false; ++ } ++ ++ if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) { ++ state->try_validation6 = false; ++ } ++ ++ if (state->try_logon_ex) { ++ if (state->try_validation6) { ++ state->validation_level = 6; ++ } else { ++ state->validation_level = 3; ++ state->user_encrypt = true; ++ } ++ ++ state->logon = netlogon_creds_shallow_copy_logon(state, ++ state->logon_level, ++ state->const_logon); ++ if (tevent_req_nomem(state->logon, req)) { ++ status = NT_STATUS_NO_MEMORY; ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, status); ++ return; ++ } ++ ++ if (state->user_encrypt) { ++ status = netlogon_creds_cli_get(state->context, ++ state, ++ &state->ro_creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ status = NT_STATUS_ACCESS_DENIED; ++ tevent_req_nterror(req, status); ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, status); ++ return; ++ } ++ ++ netlogon_creds_encrypt_samlogon_logon(state->ro_creds, ++ state->logon_level, ++ state->logon); ++ } ++ ++ subreq = dcerpc_netr_LogonSamLogonEx_send(state, state->ev, ++ state->binding_handle, ++ state->srv_name_slash, ++ state->context->client.computer, ++ state->logon_level, ++ state->logon, ++ state->validation_level, ++ state->validation, ++ &state->authoritative, ++ &state->flags); ++ if (tevent_req_nomem(subreq, req)) { ++ status = NT_STATUS_NO_MEMORY; ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, status); ++ return; ++ } ++ tevent_req_set_callback(subreq, ++ netlogon_creds_cli_LogonSamLogon_done, ++ req); ++ return; ++ } ++ ++ if (state->lk_creds == NULL) { ++ subreq = netlogon_creds_cli_lock_send(state, state->ev, ++ state->context); ++ if (tevent_req_nomem(subreq, req)) { ++ status = NT_STATUS_NO_MEMORY; ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, status); ++ return; ++ } ++ tevent_req_set_callback(subreq, ++ netlogon_creds_cli_LogonSamLogon_done, ++ req); ++ return; ++ } ++ ++ state->tmp_creds = *state->lk_creds; ++ netlogon_creds_client_authenticator(&state->tmp_creds, ++ &state->req_auth); ++ ZERO_STRUCT(state->rep_auth); ++ ++ state->logon = netlogon_creds_shallow_copy_logon(state, ++ state->logon_level, ++ state->const_logon); ++ if (tevent_req_nomem(state->logon, req)) { ++ status = NT_STATUS_NO_MEMORY; ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, status); ++ return; ++ } ++ ++ netlogon_creds_encrypt_samlogon_logon(state->ro_creds, ++ state->logon_level, ++ state->logon); ++ ++ state->validation_level = 3; ++ ++ if (state->context->server.try_logon_with) { ++ subreq = dcerpc_netr_LogonSamLogonWithFlags_send(state, state->ev, ++ state->binding_handle, ++ state->srv_name_slash, ++ state->context->client.computer, ++ &state->req_auth, ++ &state->rep_auth, ++ state->logon_level, ++ state->logon, ++ state->validation_level, ++ state->validation, ++ &state->authoritative, ++ &state->flags); ++ if (tevent_req_nomem(subreq, req)) { ++ status = NT_STATUS_NO_MEMORY; ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, status); ++ return; ++ } ++ } else { ++ state->flags = 0; ++ ++ subreq = dcerpc_netr_LogonSamLogon_send(state, state->ev, ++ state->binding_handle, ++ state->srv_name_slash, ++ state->context->client.computer, ++ &state->req_auth, ++ &state->rep_auth, ++ state->logon_level, ++ state->logon, ++ state->validation_level, ++ state->validation, ++ &state->authoritative); ++ if (tevent_req_nomem(subreq, req)) { ++ status = NT_STATUS_NO_MEMORY; ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, status); ++ return; ++ } ++ } ++ ++ tevent_req_set_callback(subreq, ++ netlogon_creds_cli_LogonSamLogon_done, ++ req); ++} ++ ++static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = ++ tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct netlogon_creds_cli_LogonSamLogon_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_LogonSamLogon_state); ++ NTSTATUS status; ++ NTSTATUS result; ++ bool ok; ++ ++ if (state->try_logon_ex) { ++ status = dcerpc_netr_LogonSamLogonEx_recv(subreq, ++ state->validation, ++ &result); ++ TALLOC_FREE(subreq); ++ if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { ++ state->context->server.try_validation6 = false; ++ state->context->server.try_logon_ex = false; ++ netlogon_creds_cli_LogonSamLogon_start(req); ++ return; ++ } ++ if (tevent_req_nterror(req, status)) { ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, status); ++ return; ++ } ++ ++ if ((state->validation_level == 6) && ++ (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS) || ++ NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER) || ++ NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL))) ++ { ++ state->context->server.try_validation6 = false; ++ netlogon_creds_cli_LogonSamLogon_start(req); ++ return; ++ } ++ ++ if (tevent_req_nterror(req, result)) { ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, result); ++ return; ++ } ++ ++ if (state->ro_creds == NULL) { ++ tevent_req_done(req); ++ return; ++ } ++ ++ ok = netlogon_creds_cli_validate(state->context, state->ro_creds); ++ if (!ok) { ++ /* ++ * We got a race, lets retry with on authenticator ++ * protection. ++ */ ++ TALLOC_FREE(state->ro_creds); ++ state->try_logon_ex = false; ++ netlogon_creds_cli_LogonSamLogon_start(req); ++ return; ++ } ++ ++ netlogon_creds_decrypt_samlogon_validation(state->ro_creds, ++ state->validation_level, ++ state->validation); ++ ++ tevent_req_done(req); ++ return; ++ } ++ ++ if (state->lk_creds == NULL) { ++ status = netlogon_creds_cli_lock_recv(subreq, state, ++ &state->lk_creds); ++ TALLOC_FREE(subreq); ++ if (tevent_req_nterror(req, status)) { ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, status); ++ return; ++ } ++ ++ netlogon_creds_cli_LogonSamLogon_start(req); ++ return; ++ } ++ ++ if (state->context->server.try_logon_with) { ++ status = dcerpc_netr_LogonSamLogonWithFlags_recv(subreq, ++ state->validation, ++ &result); ++ TALLOC_FREE(subreq); ++ if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { ++ state->context->server.try_logon_with = false; ++ netlogon_creds_cli_LogonSamLogon_start(req); ++ return; ++ } ++ if (tevent_req_nterror(req, status)) { ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, status); ++ return; ++ } ++ } else { ++ status = dcerpc_netr_LogonSamLogon_recv(subreq, ++ state->validation, ++ &result); ++ TALLOC_FREE(subreq); ++ if (tevent_req_nterror(req, status)) { ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, status); ++ return; ++ } ++ } ++ ++ ok = netlogon_creds_client_check(&state->tmp_creds, ++ &state->rep_auth.cred); ++ if (!ok) { ++ status = NT_STATUS_ACCESS_DENIED; ++ tevent_req_nterror(req, status); ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, status); ++ return; ++ } ++ ++ *state->lk_creds = state->tmp_creds; ++ status = netlogon_creds_cli_store(state->context, ++ &state->lk_creds); ++ if (tevent_req_nterror(req, status)) { ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, status); ++ return; ++ } ++ ++ if (tevent_req_nterror(req, result)) { ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, result); ++ return; ++ } ++ ++ netlogon_creds_decrypt_samlogon_validation(&state->tmp_creds, ++ state->validation_level, ++ state->validation); ++ ++ tevent_req_done(req); ++} ++ ++NTSTATUS netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req *req, ++ TALLOC_CTX *mem_ctx, ++ uint16_t *validation_level, ++ union netr_Validation **validation, ++ uint8_t *authoritative, ++ uint32_t *flags) ++{ ++ struct netlogon_creds_cli_LogonSamLogon_state *state = ++ tevent_req_data(req, ++ struct netlogon_creds_cli_LogonSamLogon_state); ++ NTSTATUS status; ++ ++ /* authoritative is also returned on error */ ++ *authoritative = state->authoritative; ++ ++ if (tevent_req_is_nterror(req, &status)) { ++ netlogon_creds_cli_LogonSamLogon_cleanup(req, status); ++ tevent_req_received(req); ++ return status; ++ } ++ ++ *validation_level = state->validation_level; ++ *validation = talloc_move(mem_ctx, &state->validation); ++ *flags = state->flags; ++ ++ tevent_req_received(req); ++ return NT_STATUS_OK; ++} ++ ++NTSTATUS netlogon_creds_cli_LogonSamLogon( ++ struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b, ++ enum netr_LogonInfoClass logon_level, ++ const union netr_LogonLevel *logon, ++ TALLOC_CTX *mem_ctx, ++ uint16_t *validation_level, ++ union netr_Validation **validation, ++ uint8_t *authoritative, ++ uint32_t *flags) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct tevent_context *ev; ++ struct tevent_req *req; ++ NTSTATUS status = NT_STATUS_NO_MEMORY; ++ ++ ev = samba_tevent_context_init(frame); ++ if (ev == NULL) { ++ goto fail; ++ } ++ req = netlogon_creds_cli_LogonSamLogon_send(frame, ev, context, b, ++ logon_level, logon, ++ *flags); ++ if (req == NULL) { ++ goto fail; ++ } ++ if (!tevent_req_poll_ntstatus(req, ev, &status)) { ++ goto fail; ++ } ++ status = netlogon_creds_cli_LogonSamLogon_recv(req, mem_ctx, ++ validation_level, ++ validation, ++ authoritative, ++ flags); ++ fail: ++ TALLOC_FREE(frame); ++ return status; ++} +diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h +new file mode 100644 +index 0000000..f8f2bef +--- /dev/null ++++ b/libcli/auth/netlogon_creds_cli.h +@@ -0,0 +1,138 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ module to store/fetch session keys for the schannel client ++ ++ Copyright (C) Stefan Metzmacher 2013 ++ ++ 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 . ++*/ ++ ++#ifndef NETLOGON_CREDS_CLI_H ++#define NETLOGON_CREDS_CLI_H ++ ++#include "librpc/gen_ndr/dcerpc.h" ++#include "librpc/gen_ndr/schannel.h" ++ ++struct netlogon_creds_cli_context; ++struct messaging_context; ++struct dcerpc_binding_handle; ++ ++NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx); ++ ++NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, ++ struct messaging_context *msg_ctx, ++ const char *client_account, ++ enum netr_SchannelType type, ++ const char *server_computer, ++ const char *server_netbios_domain, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_cli_context **_context); ++NTSTATUS netlogon_creds_cli_context_tmp(const char *client_computer, ++ const char *client_account, ++ enum netr_SchannelType type, ++ enum dcerpc_AuthLevel auth_level, ++ uint32_t proposed_flags, ++ uint32_t required_flags, ++ const char *server_computer, ++ const char *server_netbios_domain, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_cli_context **_context); ++NTSTATUS netlogon_creds_cli_context_copy( ++ const struct netlogon_creds_cli_context *src, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_cli_context **_dst); ++ ++enum dcerpc_AuthLevel netlogon_creds_cli_auth_level( ++ struct netlogon_creds_cli_context *context); ++ ++NTSTATUS netlogon_creds_cli_get(struct netlogon_creds_cli_context *context, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_CredentialState **_creds); ++bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context *context, ++ const struct netlogon_creds_CredentialState *creds1); ++ ++NTSTATUS netlogon_creds_cli_store(struct netlogon_creds_cli_context *context, ++ struct netlogon_creds_CredentialState **_creds); ++NTSTATUS netlogon_creds_cli_delete(struct netlogon_creds_cli_context *context, ++ struct netlogon_creds_CredentialState **_creds); ++ ++struct tevent_req *netlogon_creds_cli_lock_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct netlogon_creds_cli_context *context); ++NTSTATUS netlogon_creds_cli_lock_recv(struct tevent_req *req, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_CredentialState **creds); ++NTSTATUS netlogon_creds_cli_lock(struct netlogon_creds_cli_context *context, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_CredentialState **creds); ++ ++struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b, ++ struct samr_Password current_nt_hash, ++ const struct samr_Password *previous_nt_hash); ++NTSTATUS netlogon_creds_cli_auth_recv(struct tevent_req *req); ++NTSTATUS netlogon_creds_cli_auth(struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b, ++ struct samr_Password current_nt_hash, ++ const struct samr_Password *previous_nt_hash); ++ ++struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b); ++NTSTATUS netlogon_creds_cli_check_recv(struct tevent_req *req); ++NTSTATUS netlogon_creds_cli_check(struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b); ++ ++struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b, ++ const char *new_password, ++ const uint32_t *new_version); ++NTSTATUS netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req *req); ++NTSTATUS netlogon_creds_cli_ServerPasswordSet( ++ struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b, ++ const char *new_password, ++ const uint32_t *new_version); ++ ++struct tevent_req *netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b, ++ enum netr_LogonInfoClass logon_level, ++ const union netr_LogonLevel *logon, ++ uint32_t flags); ++NTSTATUS netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req *req, ++ TALLOC_CTX *mem_ctx, ++ uint16_t *validation_level, ++ union netr_Validation **validation, ++ uint8_t *authoritative, ++ uint32_t *flags); ++NTSTATUS netlogon_creds_cli_LogonSamLogon( ++ struct netlogon_creds_cli_context *context, ++ struct dcerpc_binding_handle *b, ++ enum netr_LogonInfoClass logon_level, ++ const union netr_LogonLevel *logon, ++ TALLOC_CTX *mem_ctx, ++ uint16_t *validation_level, ++ union netr_Validation **validation, ++ uint8_t *authoritative, ++ uint32_t *flags); ++ ++#endif /* NETLOGON_CREDS_CLI_H */ +diff --git a/libcli/auth/wscript_build b/libcli/auth/wscript_build +index ca2be2d..51eb293 100755 +--- a/libcli/auth/wscript_build ++++ b/libcli/auth/wscript_build +@@ -28,6 +28,10 @@ bld.SAMBA_SUBSYSTEM('COMMON_SCHANNEL', + deps='dbwrap util_tdb samba-hostconfig NDR_NETLOGON' + ) + ++bld.SAMBA_SUBSYSTEM('NETLOGON_CREDS_CLI', ++ source='netlogon_creds_cli.c', ++ deps='dbwrap util_tdb tevent-util samba-hostconfig RPC_NDR_NETLOGON NDR_NETLOGON' ++ ) + + bld.SAMBA_SUBSYSTEM('PAM_ERRORS', + source='pam_errors.c', +-- +1.9.3 + + +From e4a4e18ea7f9a9742de16e477917da6ae11ac42e Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 13 Dec 2013 17:31:45 +0100 +Subject: [PATCH 163/249] libcli/auth: use unique key_name values in + netlogon_creds_cli_context_common() + +Until all callers are fixed to pass the same 'server_computer' +value, we try to calculate a server_netbios_name and use this +as unique identifier for a specific domain controller. + +Otherwise winbind would use 'hostname.example.com' +while 'net rpc testjoin' would use 'HOSTNAME', +which leads to 2 records in netlogon_creds_cli.tdb +for the same domain controller. + +Once all callers are fixed we can think about reverting this +commit. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit dc96b1ddccfe8eb1a631355f9471ee0b620d682c) +--- + libcli/auth/netlogon_creds_cli.c | 58 +++++++++++++++++++++++++++++++++------- + 1 file changed, 48 insertions(+), 10 deletions(-) + +diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c +index 75d6b2c..a872b31 100644 +--- a/libcli/auth/netlogon_creds_cli.c ++++ b/libcli/auth/netlogon_creds_cli.c +@@ -106,23 +106,30 @@ static NTSTATUS netlogon_creds_cli_context_common( + struct netlogon_creds_cli_context **_context) + { + struct netlogon_creds_cli_context *context = NULL; ++ TALLOC_CTX *frame = talloc_stackframe(); ++ char *_key_name = NULL; ++ char *server_netbios_name = NULL; ++ char *p = NULL; + + *_context = NULL; + + context = talloc_zero(mem_ctx, struct netlogon_creds_cli_context); + if (context == NULL) { ++ TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + context->client.computer = talloc_strdup(context, client_computer); + if (context->client.computer == NULL) { +- talloc_free(context); ++ TALLOC_FREE(context); ++ TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + context->client.account = talloc_strdup(context, client_account); + if (context->client.account == NULL) { +- talloc_free(context); ++ TALLOC_FREE(context); ++ TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + +@@ -133,29 +140,60 @@ static NTSTATUS netlogon_creds_cli_context_common( + + context->server.computer = talloc_strdup(context, server_computer); + if (context->server.computer == NULL) { +- talloc_free(context); ++ TALLOC_FREE(context); ++ TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + context->server.netbios_domain = talloc_strdup(context, server_netbios_domain); + if (context->server.netbios_domain == NULL) { +- talloc_free(context); ++ TALLOC_FREE(context); ++ TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + +- context->db.key_name = talloc_asprintf(context, "CLI[%s/%s]/SRV[%s/%s]", +- client_computer, +- client_account, +- server_computer, +- server_netbios_domain); ++ /* ++ * TODO: ++ * Force the callers to provide a unique ++ * value for server_computer and use this directly. ++ * ++ * For now we have to deal with ++ * "HOSTNAME" vs. "hostname.example.com". ++ */ ++ server_netbios_name = talloc_strdup(frame, server_computer); ++ if (server_netbios_name == NULL) { ++ TALLOC_FREE(context); ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ p = strchr(server_netbios_name, '.'); ++ if (p != NULL) { ++ p[0] = '\0'; ++ } ++ ++ _key_name = talloc_asprintf(frame, "CLI[%s/%s]/SRV[%s/%s]", ++ client_computer, ++ client_account, ++ server_netbios_name, ++ server_netbios_domain); ++ if (_key_name == NULL) { ++ TALLOC_FREE(context); ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ context->db.key_name = talloc_strdup_upper(context, _key_name); + if (context->db.key_name == NULL) { +- talloc_free(context); ++ TALLOC_FREE(context); ++ TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + context->db.key_data = string_term_tdb_data(context->db.key_name); + + *_context = context; ++ TALLOC_FREE(frame); + return NT_STATUS_OK; + } + +-- +1.9.3 + + +From 29bc7cb7a1c0ef62c923ce859cdd07de2846c5f5 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 17 Oct 2013 19:01:28 +0200 +Subject: [PATCH 164/249] s3:param: set Globals.bWinbindSealedPipes = true + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 99d8653d83aa2e2e3a0ea097ab7cb65d62d76daf) +--- + source3/param/loadparm.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c +index 40f3242..7d95256 100644 +--- a/source3/param/loadparm.c ++++ b/source3/param/loadparm.c +@@ -834,6 +834,7 @@ static void init_globals(bool reinit_globals) + Globals.security = SEC_USER; + Globals.bEncryptPasswords = true; + Globals.clientSchannel = Auto; ++ Globals.bWinbindSealedPipes = true; + Globals.serverSchannel = Auto; + Globals.bReadRaw = true; + Globals.bWriteRaw = true; +-- +1.9.3 + + +From 21b9d9847ba236d78156de07dd24032e64f2124d Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 17 Oct 2013 18:39:56 +0200 +Subject: [PATCH 165/249] lib/param: add "neutralize nt4 emulation" option, + defaulting to false + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit b39ca3a2aefdd43a55b9cdd8fa5136254b283927) +--- + .../smbdotconf/winbind/netutralizent4emulation.xml | 19 +++++++++++++++++++ + lib/param/param_functions.c | 1 + + lib/param/param_table.c | 9 +++++++++ + 3 files changed, 29 insertions(+) + create mode 100644 docs-xml/smbdotconf/winbind/netutralizent4emulation.xml + +diff --git a/docs-xml/smbdotconf/winbind/netutralizent4emulation.xml b/docs-xml/smbdotconf/winbind/netutralizent4emulation.xml +new file mode 100644 +index 0000000..8294a90 +--- /dev/null ++++ b/docs-xml/smbdotconf/winbind/netutralizent4emulation.xml +@@ -0,0 +1,19 @@ ++ ++ ++ This option controls whether winbindd sends ++ the NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION flag in order to bypass ++ the NT4 emulation of a domain controller. ++ ++ Typically you should not need set this. ++ It can be useful for upgrades from NT4 to AD domains. ++ ++ The behavior can be controlled per netbios domain ++ by using 'neutralize nt4 emulation:NETBIOSDOMAIN = yes' as option. ++ ++ ++no ++ +diff --git a/lib/param/param_functions.c b/lib/param/param_functions.c +index 60f9c07..aef091b 100644 +--- a/lib/param/param_functions.c ++++ b/lib/param/param_functions.c +@@ -192,6 +192,7 @@ FN_GLOBAL_BOOL(log_writeable_files_on_exit, bLogWriteableFilesOnExit) + FN_GLOBAL_BOOL(map_untrusted_to_domain, bMapUntrustedToDomain) + FN_GLOBAL_BOOL(ms_add_printer_wizard, bMsAddPrinterWizard) + FN_GLOBAL_BOOL(multicast_dns_register, bMulticastDnsRegister) ++FN_GLOBAL_BOOL(neutralize_nt4_emulation, bNeutralizeNT4Emulation) + FN_GLOBAL_BOOL(nis_home_map, bNISHomeMap) + FN_GLOBAL_BOOL(nmbd_bind_explicit_broadcast, bNmbdBindExplicitBroadcast) + FN_GLOBAL_BOOL(ntlm_auth, bNTLMAuth) +diff --git a/lib/param/param_table.c b/lib/param/param_table.c +index 8e3f952..edf6829 100644 +--- a/lib/param/param_table.c ++++ b/lib/param/param_table.c +@@ -4188,6 +4188,15 @@ static struct parm_struct parm_table[] = { + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, ++ { ++ .label = "neutralize nt4 emulation", ++ .type = P_BOOL, ++ .p_class = P_GLOBAL, ++ .offset = GLOBAL_VAR(bNeutralizeNT4Emulation), ++ .special = NULL, ++ .enum_list = NULL, ++ .flags = FLAG_ADVANCED, ++ }, + + {N_("DNS options"), P_SEP, P_SEPARATOR}, + { +-- +1.9.3 + + +From d1cfe2d0f3f72e8b7700eee01e47b0bb9d3b9ca3 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 17 Oct 2013 18:39:56 +0200 +Subject: [PATCH 166/249] lib/param: add "reject md5 servers" option, + defaulting to false + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit de4f8f0825790452455a9d51e9d84d4d4a5c0d3b) +--- + docs-xml/smbdotconf/winbind/rejectmd5servers.xml | 23 +++++++++++++++++++++++ + lib/param/param_functions.c | 1 + + lib/param/param_table.c | 9 +++++++++ + 3 files changed, 33 insertions(+) + create mode 100644 docs-xml/smbdotconf/winbind/rejectmd5servers.xml + +diff --git a/docs-xml/smbdotconf/winbind/rejectmd5servers.xml b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml +new file mode 100644 +index 0000000..18f8bcb +--- /dev/null ++++ b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml +@@ -0,0 +1,23 @@ ++ ++ ++ This option controls whether winbindd requires support ++ for aes support for the netlogon secure channel. ++ ++ The following flags will be required NETLOGON_NEG_ARCFOUR, ++ NETLOGON_NEG_SUPPORTS_AES, NETLOGON_NEG_PASSWORD_SET2 and NETLOGON_NEG_AUTHENTICATED_RPC. ++ ++ You can set this to yes if all domain controllers support aes. ++ This will prevent downgrade attacks. ++ ++ The behavior can be controlled per netbios domain ++ by using 'reject md5 servers:NETBIOSDOMAIN = yes' as option. ++ ++ This option takes precedence to the option. ++ ++ ++no ++ +diff --git a/lib/param/param_functions.c b/lib/param/param_functions.c +index aef091b..ecd7f8e 100644 +--- a/lib/param/param_functions.c ++++ b/lib/param/param_functions.c +@@ -204,6 +204,7 @@ FN_GLOBAL_BOOL(pam_password_change, bPamPasswordChange) + FN_GLOBAL_BOOL(passdb_expand_explicit, bPassdbExpandExplicit) + FN_GLOBAL_BOOL(passwd_chat_debug, bPasswdChatDebug) + FN_GLOBAL_BOOL(registry_shares, bRegistryShares) ++FN_GLOBAL_BOOL(reject_md5_servers, bRejectMD5Servers) + FN_GLOBAL_BOOL(reset_on_zero_vc, bResetOnZeroVC) + FN_GLOBAL_BOOL(rpc_big_endian, bRpcBigEndian) + FN_GLOBAL_BOOL(stat_cache, bStatCache) +diff --git a/lib/param/param_table.c b/lib/param/param_table.c +index edf6829..b53f850 100644 +--- a/lib/param/param_table.c ++++ b/lib/param/param_table.c +@@ -4197,6 +4197,15 @@ static struct parm_struct parm_table[] = { + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, ++ { ++ .label = "reject md5 servers", ++ .type = P_BOOL, ++ .p_class = P_GLOBAL, ++ .offset = GLOBAL_VAR(bRejectMD5Servers), ++ .special = NULL, ++ .enum_list = NULL, ++ .flags = FLAG_ADVANCED, ++ }, + + {N_("DNS options"), P_SEP, P_SEPARATOR}, + { +-- +1.9.3 + + +From 2545090f09da279655510f87d02c631c74409eb1 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 17 Oct 2013 18:39:56 +0200 +Subject: [PATCH 167/249] lib/param: add "require strong key" option, + defaulting to true + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 6630c68cce8fbbd700e7d4cd92ec3ebb2a268f06) +--- + docs-xml/smbdotconf/winbind/requirestrongkey.xml | 27 ++++++++++++++++++++++++ + lib/param/loadparm.c | 1 + + lib/param/param_functions.c | 1 + + lib/param/param_table.c | 9 ++++++++ + 4 files changed, 38 insertions(+) + create mode 100644 docs-xml/smbdotconf/winbind/requirestrongkey.xml + +diff --git a/docs-xml/smbdotconf/winbind/requirestrongkey.xml b/docs-xml/smbdotconf/winbind/requirestrongkey.xml +new file mode 100644 +index 0000000..de749bb +--- /dev/null ++++ b/docs-xml/smbdotconf/winbind/requirestrongkey.xml +@@ -0,0 +1,27 @@ ++ ++ ++ This option controls whether winbindd requires support ++ for md5 strong key support for the netlogon secure channel. ++ ++ The following flags will be required NETLOGON_NEG_STRONG_KEYS, ++ NETLOGON_NEG_ARCFOUR and NETLOGON_NEG_AUTHENTICATED_RPC. ++ ++ You can set this to no if some domain controllers only support des. ++ This might allows weak crypto to be negotiated, may via downgrade attacks. ++ ++ The behavior can be controlled per netbios domain ++ by using 'require strong key:NETBIOSDOMAIN = no' as option. ++ ++ Note for active directory domain this option is hardcoded to 'yes' ++ ++ This option yields precedence to the option. ++ ++ This option takes precedence to the option. ++ ++ ++yes ++ +diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c +index 23b45e2..a84a166 100644 +--- a/lib/param/loadparm.c ++++ b/lib/param/loadparm.c +@@ -2183,6 +2183,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) + + lpcfg_do_global_parameter(lp_ctx, "winbind separator", "\\"); + lpcfg_do_global_parameter(lp_ctx, "winbind sealed pipes", "True"); ++ lpcfg_do_global_parameter(lp_ctx, "require strong key", "True"); + lpcfg_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR); + lpcfg_do_global_parameter(lp_ctx, "winbindd privileged socket directory", dyn_WINBINDD_PRIVILEGED_SOCKET_DIR); + lpcfg_do_global_parameter(lp_ctx, "ntp signd socket directory", dyn_NTP_SIGND_SOCKET_DIR); +diff --git a/lib/param/param_functions.c b/lib/param/param_functions.c +index ecd7f8e..41b137f 100644 +--- a/lib/param/param_functions.c ++++ b/lib/param/param_functions.c +@@ -205,6 +205,7 @@ FN_GLOBAL_BOOL(passdb_expand_explicit, bPassdbExpandExplicit) + FN_GLOBAL_BOOL(passwd_chat_debug, bPasswdChatDebug) + FN_GLOBAL_BOOL(registry_shares, bRegistryShares) + FN_GLOBAL_BOOL(reject_md5_servers, bRejectMD5Servers) ++FN_GLOBAL_BOOL(require_strong_key, bRequireStrongKey) + FN_GLOBAL_BOOL(reset_on_zero_vc, bResetOnZeroVC) + FN_GLOBAL_BOOL(rpc_big_endian, bRpcBigEndian) + FN_GLOBAL_BOOL(stat_cache, bStatCache) +diff --git a/lib/param/param_table.c b/lib/param/param_table.c +index b53f850..36e8554 100644 +--- a/lib/param/param_table.c ++++ b/lib/param/param_table.c +@@ -4206,6 +4206,15 @@ static struct parm_struct parm_table[] = { + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, ++ { ++ .label = "require strong key", ++ .type = P_BOOL, ++ .p_class = P_GLOBAL, ++ .offset = GLOBAL_VAR(bRequireStrongKey), ++ .special = NULL, ++ .enum_list = NULL, ++ .flags = FLAG_ADVANCED, ++ }, + + {N_("DNS options"), P_SEP, P_SEPARATOR}, + { +-- +1.9.3 + + +From 4e604cc566b2854045c5b794a846c1ab1ef4a35f Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 17 Oct 2013 19:01:47 +0200 +Subject: [PATCH 168/249] s3:param: set Globals.bRequireStrongKey = true + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit e7954bcc04ec6761b2ed6dad08b90c65efafa948) +--- + source3/param/loadparm.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c +index 7d95256..ed46e53 100644 +--- a/source3/param/loadparm.c ++++ b/source3/param/loadparm.c +@@ -835,6 +835,7 @@ static void init_globals(bool reinit_globals) + Globals.bEncryptPasswords = true; + Globals.clientSchannel = Auto; + Globals.bWinbindSealedPipes = true; ++ Globals.bRequireStrongKey = true; + Globals.serverSchannel = Auto; + Globals.bReadRaw = true; + Globals.bWriteRaw = true; +-- +1.9.3 + + +From 382f69a0f3762947a3e8cc02e8e9817533073195 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 17 Oct 2013 18:48:15 +0200 +Subject: [PATCH 169/249] libcli/auth: make use of real options in + netlogon_creds_cli_context_global() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit fa3af7c2e8f1bf292e190ba3d933b6e1d552595d) +--- + libcli/auth/netlogon_creds_cli.c | 18 +++--------------- + 1 file changed, 3 insertions(+), 15 deletions(-) + +diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c +index a872b31..6590b21 100644 +--- a/libcli/auth/netlogon_creds_cli.c ++++ b/libcli/auth/netlogon_creds_cli.c +@@ -279,11 +279,7 @@ NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, + * allow overwrite per domain + * reject md5 servers: + */ +- //TODO: add lpcfp_reject_md5_servers() +- reject_md5_servers = lpcfg_parm_bool(lp_ctx, NULL, +- "__default__", +- "reject md5 servers", +- reject_md5_servers); ++ reject_md5_servers = lpcfg_reject_md5_servers(lp_ctx); + reject_md5_servers = lpcfg_parm_bool(lp_ctx, NULL, + "reject md5 servers", + server_netbios_domain, +@@ -293,11 +289,7 @@ NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, + * allow overwrite per domain + * require strong key: + */ +- //TODO: add lpcfp_require_strong_key() +- require_strong_key = lpcfg_parm_bool(lp_ctx, NULL, +- "__default__", +- "require strong key", +- require_strong_key); ++ require_strong_key = lpcfg_require_strong_key(lp_ctx); + require_strong_key = lpcfg_parm_bool(lp_ctx, NULL, + "require strong key", + server_netbios_domain, +@@ -327,11 +319,7 @@ NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, + * allow overwrite per domain + * neutralize nt4 emulation: + */ +- //TODO: add lpcfp_neutralize_nt4_emulation() +- neutralize_nt4_emulation = lpcfg_parm_bool(lp_ctx, NULL, +- "__default__", +- "neutralize nt4 emulation", +- neutralize_nt4_emulation); ++ neutralize_nt4_emulation = lpcfg_neutralize_nt4_emulation(lp_ctx); + neutralize_nt4_emulation = lpcfg_parm_bool(lp_ctx, NULL, + "neutralize nt4 emulation", + server_netbios_domain, +-- +1.9.3 + + +From 79e8c0c97591ed8bc129561e44b0d94757fcc4e1 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 23 Dec 2013 10:45:27 +0100 +Subject: [PATCH 170/249] docs-xml: explain the interaction between security = + ads and other options. + +It implies 'require strong key = yes' and 'client schannel = yes'. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit f703a37a56e215827dbb2a7ec8da6738bf17f600) +--- + docs-xml/smbdotconf/security/security.xml | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/docs-xml/smbdotconf/security/security.xml b/docs-xml/smbdotconf/security/security.xml +index 406089f..2f5c3f7 100644 +--- a/docs-xml/smbdotconf/security/security.xml ++++ b/docs-xml/smbdotconf/security/security.xml +@@ -99,7 +99,10 @@ + + Note that this mode does NOT make Samba operate as a Active Directory Domain + Controller. +- ++ ++ Note that this forces yes ++ and yes for the primary domain. ++ + Read the chapter about Domain Membership in the HOWTO for details. + + +-- +1.9.3 + + +From 27ea332df51e3cd8ed9601633282b688e6f288a7 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 23 Dec 2013 10:46:57 +0100 +Subject: [PATCH 171/249] docs-xml: explain the interaction of 'client + schannel' with 'require strong key = yes' + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 1d69fdddd5287757c2e67b0982d00241a6d75d26) +--- + docs-xml/smbdotconf/security/clientschannel.xml | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/docs-xml/smbdotconf/security/clientschannel.xml b/docs-xml/smbdotconf/security/clientschannel.xml +index e229182..ac4cc59 100644 +--- a/docs-xml/smbdotconf/security/clientschannel.xml ++++ b/docs-xml/smbdotconf/security/clientschannel.xml +@@ -12,6 +12,11 @@ + enforce it, and yes denies access + if the server is not able to speak netlogon schannel. + ++ ++ Note that for active directory domains this is hardcoded to ++ yes. ++ ++ This option yields precedence to the option. + + auto + yes +-- +1.9.3 + + +From 4853daeffb1916db3b92dc6ba9e5776652ec5f4e Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 17 Oct 2013 19:31:58 +0200 +Subject: [PATCH 172/249] s3:winbindd: make use of the "winbind sealed pipes" + option for all connections + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 225982e1cb6276ed5c6a47c0e4827d75e8ab2fb1) +--- + source3/winbindd/winbindd.h | 3 +++ + source3/winbindd/winbindd_cm.c | 20 +++++++++++++++++--- + 2 files changed, 20 insertions(+), 3 deletions(-) + +diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h +index 72eb3ec..afde685 100644 +--- a/source3/winbindd/winbindd.h ++++ b/source3/winbindd/winbindd.h +@@ -25,6 +25,7 @@ + + #include "nsswitch/winbind_struct_protocol.h" + #include "nsswitch/libwbclient/wbclient.h" ++#include "librpc/gen_ndr/dcerpc.h" + #include "librpc/gen_ndr/wbint.h" + + #include "talloc_dict.h" +@@ -105,6 +106,8 @@ struct getpwent_user { + struct winbindd_cm_conn { + struct cli_state *cli; + ++ enum dcerpc_AuthLevel auth_level; ++ + struct rpc_pipe_client *samr_pipe; + struct policy_handle sam_connect_handle, sam_domain_handle; + +diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c +index c4f59d3..6c1244e 100644 +--- a/source3/winbindd/winbindd_cm.c ++++ b/source3/winbindd/winbindd_cm.c +@@ -1722,6 +1722,7 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, + } + + if (NT_STATUS_IS_OK(result)) { ++ bool seal_pipes = true; + + winbindd_set_locator_kdc_envs(domain); + +@@ -1741,6 +1742,17 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, + */ + store_current_dc_in_gencache(domain->name, domain->dcname, + new_conn->cli); ++ ++ seal_pipes = lp_winbind_sealed_pipes(); ++ seal_pipes = lp_parm_bool(-1, "winbind sealed pipes", ++ domain->name, ++ seal_pipes); ++ ++ if (seal_pipes) { ++ new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY; ++ } else { ++ new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; ++ } + } else { + /* Ensure we setup the retry handler. */ + set_domain_offline(domain); +@@ -1813,6 +1825,8 @@ void invalidate_cm_connection(struct winbindd_cm_conn *conn) + } + } + ++ conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY; ++ + if (conn->cli) { + cli_shutdown(conn->cli); + } +@@ -2363,7 +2377,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + &ndr_table_samr, + NCACN_NP, + GENSEC_OID_NTLMSSP, +- DCERPC_AUTH_LEVEL_PRIVACY, ++ conn->auth_level, + smbXcli_conn_remote_name(conn->cli->conn), + domain_name, + machine_account, +@@ -2534,7 +2548,7 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain, + + if (conn->lsa_pipe_tcp && + conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP && +- conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY && ++ conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY && + rpccli_is_connected(conn->lsa_pipe_tcp)) { + goto done; + } +@@ -2602,7 +2616,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + result = cli_rpc_pipe_open_spnego + (conn->cli, &ndr_table_lsarpc, NCACN_NP, + GENSEC_OID_NTLMSSP, +- DCERPC_AUTH_LEVEL_PRIVACY, ++ conn->auth_level, + smbXcli_conn_remote_name(conn->cli->conn), + conn->cli->domain, conn->cli->user_name, conn->cli->password, + &conn->lsa_pipe); +-- +1.9.3 + + +From c2116e6a1ee32ff36942091287e90b08d1ecf6d1 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 14 Nov 2013 18:53:06 +0100 +Subject: [PATCH 173/249] docs-xml: update 'winbind sealed pipes' description + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 11aed7cd3dbd967593b34a206f0802fd0002bf27) +--- + docs-xml/smbdotconf/winbind/winbindsealedpipes.xml | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/docs-xml/smbdotconf/winbind/winbindsealedpipes.xml b/docs-xml/smbdotconf/winbind/winbindsealedpipes.xml +index 26f446e..63f5588 100644 +--- a/docs-xml/smbdotconf/winbind/winbindsealedpipes.xml ++++ b/docs-xml/smbdotconf/winbind/winbindsealedpipes.xml +@@ -4,12 +4,12 @@ + advanced="1" developer="1" + xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> + +- This option controls whether any requests made over the Samba 4 winbind ++ This option controls whether any requests from winbindd to domain controllers + pipe will be sealed. Disabling sealing can be useful for debugging + purposes. + +- Note that this option only applies to the Samba 4 winbind and not +- to the standard winbind. ++ The behavior can be controlled per netbios domain ++ by using 'winbind sealed pipes:NETBIOSDOMAIN = no' as option. + + + yes +-- +1.9.3 + + +From ea14b4a713a85a2d87cba6ad88127020e1d5e813 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sat, 27 Jul 2013 11:30:13 +0200 +Subject: [PATCH 174/249] s3:rpc_client: make use of the new + netlogon_creds_cli_context + +This exchanges rpc_pipe_client->dc with rpc_pipe_client->netlogon_creds +and lets the secure channel session state be stored in node local database. + +This is the proper fix for a large number of bugs: +https://bugzilla.samba.org/show_bug.cgi?id=6563 +https://bugzilla.samba.org/show_bug.cgi?id=7944 +https://bugzilla.samba.org/show_bug.cgi?id=7945 +https://bugzilla.samba.org/show_bug.cgi?id=7568 +https://bugzilla.samba.org/show_bug.cgi?id=8599 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 38d4dba37406515181e4d6f1a1faffc18e652e27) +--- + source3/libnet/libnet_join.c | 3 +- + source3/libnet/libnet_samsync.c | 19 +- + source3/rpc_client/cli_netlogon.c | 436 ++++++++------------------------- + source3/rpc_client/cli_pipe.c | 139 +++-------- + source3/rpc_client/cli_pipe.h | 2 +- + source3/rpc_client/cli_pipe_schannel.c | 3 +- + source3/rpc_client/rpc_client.h | 2 +- + source3/rpcclient/cmd_netlogon.c | 57 ++++- + source3/winbindd/winbindd.h | 9 - + source3/winbindd/winbindd_cm.c | 36 +-- + source3/winbindd/winbindd_pam.c | 136 ++-------- + source3/wscript_build | 6 +- + 12 files changed, 250 insertions(+), 598 deletions(-) + +diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c +index c1eccda..5dc620f 100644 +--- a/source3/libnet/libnet_join.c ++++ b/source3/libnet/libnet_join.c +@@ -1279,7 +1279,8 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, + status = cli_rpc_pipe_open_schannel_with_key( + cli, &ndr_table_netlogon, NCACN_NP, + DCERPC_AUTH_LEVEL_PRIVACY, +- netbios_domain_name, &netlogon_pipe->dc, &pipe_hnd); ++ netbios_domain_name, ++ netlogon_pipe->netlogon_creds, &pipe_hnd); + + cli_shutdown(cli); + +diff --git a/source3/libnet/libnet_samsync.c b/source3/libnet/libnet_samsync.c +index a103785..02d3fc6 100644 +--- a/source3/libnet/libnet_samsync.c ++++ b/source3/libnet/libnet_samsync.c +@@ -30,6 +30,7 @@ + #include "../librpc/gen_ndr/ndr_netlogon_c.h" + #include "../libcli/security/security.h" + #include "messages.h" ++#include "../libcli/auth/netlogon_creds_cli.h" + + /** + * Fix up the delta, dealing with encryption issues so that the final +@@ -213,8 +214,15 @@ static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx, + + do { + struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; ++ struct netlogon_creds_CredentialState *creds = NULL; + +- netlogon_creds_client_authenticator(ctx->cli->dc, &credential); ++ status = netlogon_creds_cli_lock(ctx->cli->netlogon_creds, ++ mem_ctx, &creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ netlogon_creds_client_authenticator(creds, &credential); + + if (ctx->single_object_replication && + !ctx->force_full_replication) { +@@ -254,28 +262,33 @@ static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx, + } + + if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(creds); + return status; + } + + /* Check returned credentials. */ +- if (!netlogon_creds_client_check(ctx->cli->dc, ++ if (!netlogon_creds_client_check(creds, + &return_authenticator.cred)) { ++ TALLOC_FREE(creds); + DEBUG(0,("credentials chain check failed\n")); + return NT_STATUS_ACCESS_DENIED; + } + + if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) { ++ TALLOC_FREE(creds); + return result; + } + + if (NT_STATUS_IS_ERR(result)) { ++ TALLOC_FREE(creds); + break; + } + + samsync_fix_delta_array(mem_ctx, +- ctx->cli->dc, ++ creds, + database_id, + delta_enum_array); ++ TALLOC_FREE(creds); + + /* Process results */ + callback_status = ctx->ops->process_objects(mem_ctx, database_id, +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index 5e8a2fc..fcd24d6 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -23,11 +23,13 @@ + #include "includes.h" + #include "rpc_client/rpc_client.h" + #include "../libcli/auth/libcli_auth.h" ++#include "../libcli/auth/netlogon_creds_cli.h" + #include "../librpc/gen_ndr/ndr_netlogon_c.h" + #include "rpc_client/cli_netlogon.h" + #include "rpc_client/init_netlogon.h" + #include "rpc_client/util_netlogon.h" + #include "../libcli/security/security.h" ++#include "lib/param/param.h" + + /**************************************************************************** + Wrapper function that uses the auth and auth2 calls to set up a NETLOGON +@@ -44,113 +46,81 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, + enum netr_SchannelType sec_chan_type, + uint32_t *neg_flags_inout) + { ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct loadparm_context *lp_ctx; + NTSTATUS status; +- NTSTATUS result = NT_STATUS_UNSUCCESSFUL; +- struct netr_Credential clnt_chal_send; +- struct netr_Credential srv_chal_recv; + struct samr_Password password; +- bool retried = false; + fstring mach_acct; +- uint32_t neg_flags = *neg_flags_inout; + struct dcerpc_binding_handle *b = cli->binding_handle; ++ struct netlogon_creds_CredentialState *creds = NULL; + + if (!ndr_syntax_id_equal(&cli->abstract_syntax, + &ndr_table_netlogon.syntax_id)) { ++ TALLOC_FREE(frame); + return NT_STATUS_INVALID_PARAMETER; + } + +- TALLOC_FREE(cli->dc); +- +- /* Store the machine account password we're going to use. */ +- memcpy(password.hash, machine_pwd, 16); +- +- fstr_sprintf( mach_acct, "%s$", machine_account); +- +- again: +- /* Create the client challenge. */ +- generate_random_buffer(clnt_chal_send.data, 8); +- +- /* Get the server challenge. */ +- status = dcerpc_netr_ServerReqChallenge(b, talloc_tos(), +- cli->srv_name_slash, +- clnt_name, +- &clnt_chal_send, +- &srv_chal_recv, +- &result); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- if (!NT_STATUS_IS_OK(result)) { +- return result; ++ if (!strequal(lp_netbios_name(), clnt_name)) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_INVALID_PARAMETER; + } + +- /* Calculate the session key and client credentials */ ++ TALLOC_FREE(cli->netlogon_creds); + +- cli->dc = netlogon_creds_client_init(cli, +- mach_acct, +- clnt_name, +- sec_chan_type, +- &clnt_chal_send, +- &srv_chal_recv, +- &password, +- &clnt_chal_send, +- neg_flags); ++ fstr_sprintf( mach_acct, "%s$", machine_account); + +- if (!cli->dc) { ++ lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); ++ if (lp_ctx == NULL) { ++ TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } +- +- /* +- * Send client auth-2 challenge and receive server repy. +- */ +- +- status = dcerpc_netr_ServerAuthenticate2(b, talloc_tos(), +- cli->srv_name_slash, +- cli->dc->account_name, +- sec_chan_type, +- cli->dc->computer_name, +- &clnt_chal_send, /* input. */ +- &srv_chal_recv, /* output. */ +- &neg_flags, +- &result); ++ status = netlogon_creds_cli_context_global(lp_ctx, ++ NULL, /* msg_ctx */ ++ mach_acct, ++ sec_chan_type, ++ server_name, ++ domain, ++ cli, &cli->netlogon_creds); ++ talloc_unlink(frame, lp_ctx); + if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); + return status; + } +- /* we might be talking to NT4, so let's downgrade in that case and retry +- * with the returned neg_flags - gd */ + +- if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && !retried) { +- retried = true; +- TALLOC_FREE(cli->dc); +- goto again; ++ status = netlogon_creds_cli_get(cli->netlogon_creds, ++ frame, &creds); ++ if (NT_STATUS_IS_OK(status)) { ++ DEBUG(5,("rpccli_netlogon_setup_creds: server %s using " ++ "cached credential\n", ++ cli->desthost)); ++ *neg_flags_inout = creds->negotiate_flags; ++ TALLOC_FREE(frame); ++ return NT_STATUS_OK; + } + +- if (!NT_STATUS_IS_OK(result)) { +- return result; +- } +- +- /* +- * Check the returned value using the initial +- * server received challenge. +- */ +- +- if (!netlogon_creds_client_check(cli->dc, &srv_chal_recv)) { +- /* +- * Server replied with bad credential. Fail. +- */ +- DEBUG(0,("rpccli_netlogon_setup_creds: server %s " +- "replied with bad credential\n", +- cli->desthost )); +- return NT_STATUS_ACCESS_DENIED; +- } ++ /* Store the machine account password we're going to use. */ ++ memcpy(password.hash, machine_pwd, 16); + + DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential " + "chain established.\n", + cli->desthost )); + +- cli->dc->negotiate_flags = neg_flags; +- *neg_flags_inout = neg_flags; ++ status = netlogon_creds_cli_auth(cli->netlogon_creds, b, ++ password, NULL); ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); ++ return status; ++ } ++ ++ status = netlogon_creds_cli_get(cli->netlogon_creds, ++ frame, &creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_INTERNAL_ERROR; ++ } + ++ *neg_flags_inout = creds->negotiate_flags; ++ TALLOC_FREE(frame); + return NT_STATUS_OK; + } + +@@ -163,20 +133,16 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, + const char *username, + const char *password, + const char *workstation, +- uint16_t validation_level, ++ uint16_t _ignored_validation_level, + int logon_type) + { +- NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + NTSTATUS status; +- struct netr_Authenticator clnt_creds; +- struct netr_Authenticator ret_creds; + union netr_LogonLevel *logon; +- union netr_Validation validation; +- uint8_t authoritative; ++ uint16_t validation_level = 0; ++ union netr_Validation *validation = NULL; ++ uint8_t authoritative = 0; ++ uint32_t flags = 0; + fstring clnt_name_slash; +- struct dcerpc_binding_handle *b = cli->binding_handle; +- +- ZERO_STRUCT(ret_creds); + + logon = talloc_zero(mem_ctx, union netr_LogonLevel); + if (!logon) { +@@ -191,8 +157,6 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, + + /* Initialise input parameters */ + +- netlogon_creds_client_authenticator(cli->dc, &clnt_creds); +- + switch (logon_type) { + case NetlogonInteractiveInformation: { + +@@ -208,17 +172,6 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, + + nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash); + +- if (cli->dc->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { +- netlogon_creds_aes_encrypt(cli->dc, lmpassword.hash, 16); +- netlogon_creds_aes_encrypt(cli->dc, ntpassword.hash, 16); +- } else if (cli->dc->negotiate_flags & NETLOGON_NEG_ARCFOUR) { +- netlogon_creds_arcfour_crypt(cli->dc, lmpassword.hash, 16); +- netlogon_creds_arcfour_crypt(cli->dc, ntpassword.hash, 16); +- } else { +- netlogon_creds_des_encrypt(cli->dc, &lmpassword); +- netlogon_creds_des_encrypt(cli->dc, &ntpassword); +- } +- + password_info->identity_info.domain_name.string = domain; + password_info->identity_info.parameter_control = logon_parameters; + password_info->identity_info.logon_id_low = 0xdead; +@@ -281,28 +234,20 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, + return NT_STATUS_INVALID_INFO_CLASS; + } + +- status = dcerpc_netr_LogonSamLogon(b, mem_ctx, +- cli->srv_name_slash, +- lp_netbios_name(), +- &clnt_creds, +- &ret_creds, +- logon_type, +- logon, +- validation_level, +- &validation, +- &authoritative, +- &result); ++ status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds, ++ cli->binding_handle, ++ logon_type, ++ logon, ++ mem_ctx, ++ &validation_level, ++ &validation, ++ &authoritative, ++ &flags); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + +- /* Always check returned credentials */ +- if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) { +- DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n")); +- return NT_STATUS_ACCESS_DENIED; +- } +- +- return result; ++ return NT_STATUS_OK; + } + + static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx, +@@ -366,29 +311,24 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, + const char *domain, + const char *workstation, + const uint8 chal[8], +- uint16_t validation_level, ++ uint16_t _ignored_validation_level, + DATA_BLOB lm_response, + DATA_BLOB nt_response, + struct netr_SamInfo3 **info3) + { +- NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + NTSTATUS status; + const char *workstation_name_slash; +- const char *server_name_slash; +- struct netr_Authenticator clnt_creds; +- struct netr_Authenticator ret_creds; + union netr_LogonLevel *logon = NULL; + struct netr_NetworkInfo *network_info; +- uint8_t authoritative; +- union netr_Validation validation; ++ uint16_t validation_level = 0; ++ union netr_Validation *validation = NULL; ++ uint8_t authoritative = 0; ++ uint32_t flags = 0; + struct netr_ChallengeResponse lm; + struct netr_ChallengeResponse nt; +- struct dcerpc_binding_handle *b = cli->binding_handle; + + *info3 = NULL; + +- ZERO_STRUCT(ret_creds); +- + ZERO_STRUCT(lm); + ZERO_STRUCT(nt); + +@@ -402,21 +342,13 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, + return NT_STATUS_NO_MEMORY; + } + +- netlogon_creds_client_authenticator(cli->dc, &clnt_creds); +- +- if (server[0] != '\\' && server[1] != '\\') { +- server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server); +- } else { +- server_name_slash = server; +- } +- + if (workstation[0] != '\\' && workstation[1] != '\\') { + workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation); + } else { + workstation_name_slash = workstation; + } + +- if (!workstation_name_slash || !server_name_slash) { ++ if (!workstation_name_slash) { + DEBUG(0, ("talloc_asprintf failed!\n")); + return NT_STATUS_NO_MEMORY; + } +@@ -443,40 +375,27 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, + + /* Marshall data and send request */ + +- status = dcerpc_netr_LogonSamLogon(b, mem_ctx, +- server_name_slash, +- lp_netbios_name(), +- &clnt_creds, +- &ret_creds, +- NetlogonNetworkInformation, +- logon, +- validation_level, +- &validation, +- &authoritative, +- &result); ++ status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds, ++ cli->binding_handle, ++ NetlogonNetworkInformation, ++ logon, ++ mem_ctx, ++ &validation_level, ++ &validation, ++ &authoritative, ++ &flags); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + +- /* Always check returned credentials. */ +- if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) { +- DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n")); +- return NT_STATUS_ACCESS_DENIED; +- } +- +- if (!NT_STATUS_IS_OK(result)) { +- return result; +- } +- +- netlogon_creds_decrypt_samlogon_validation(cli->dc, validation_level, +- &validation); +- +- result = map_validation_to_info3(mem_ctx, validation_level, &validation, info3); +- if (!NT_STATUS_IS_OK(result)) { +- return result; ++ status = map_validation_to_info3(mem_ctx, ++ validation_level, validation, ++ info3); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; + } + +- return result; ++ return NT_STATUS_OK; + } + + NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli, +@@ -492,100 +411,18 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli, + DATA_BLOB nt_response, + struct netr_SamInfo3 **info3) + { +- NTSTATUS result = NT_STATUS_UNSUCCESSFUL; +- NTSTATUS status; +- const char *workstation_name_slash; +- const char *server_name_slash; +- union netr_LogonLevel *logon = NULL; +- struct netr_NetworkInfo *network_info; +- uint8_t authoritative; +- union netr_Validation validation; +- struct netr_ChallengeResponse lm; +- struct netr_ChallengeResponse nt; +- uint32_t flags = 0; +- struct dcerpc_binding_handle *b = cli->binding_handle; +- +- *info3 = NULL; +- +- ZERO_STRUCT(lm); +- ZERO_STRUCT(nt); +- +- logon = talloc_zero(mem_ctx, union netr_LogonLevel); +- if (!logon) { +- return NT_STATUS_NO_MEMORY; +- } +- +- network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo); +- if (!network_info) { +- return NT_STATUS_NO_MEMORY; +- } +- +- if (server[0] != '\\' && server[1] != '\\') { +- server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server); +- } else { +- server_name_slash = server; +- } +- +- if (workstation[0] != '\\' && workstation[1] != '\\') { +- workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation); +- } else { +- workstation_name_slash = workstation; +- } +- +- if (!workstation_name_slash || !server_name_slash) { +- DEBUG(0, ("talloc_asprintf failed!\n")); +- return NT_STATUS_NO_MEMORY; +- } +- +- /* Initialise input parameters */ +- +- lm.data = lm_response.data; +- lm.length = lm_response.length; +- nt.data = nt_response.data; +- nt.length = nt_response.length; +- +- network_info->identity_info.domain_name.string = domain; +- network_info->identity_info.parameter_control = logon_parameters; +- network_info->identity_info.logon_id_low = 0xdead; +- network_info->identity_info.logon_id_high = 0xbeef; +- network_info->identity_info.account_name.string = username; +- network_info->identity_info.workstation.string = workstation_name_slash; +- +- memcpy(network_info->challenge, chal, 8); +- network_info->nt = nt; +- network_info->lm = lm; +- +- logon->network = network_info; +- +- /* Marshall data and send request */ +- +- status = dcerpc_netr_LogonSamLogonEx(b, mem_ctx, +- server_name_slash, +- lp_netbios_name(), +- NetlogonNetworkInformation, +- logon, +- validation_level, +- &validation, +- &authoritative, +- &flags, +- &result); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- +- if (!NT_STATUS_IS_OK(result)) { +- return result; +- } +- +- netlogon_creds_decrypt_samlogon_validation(cli->dc, validation_level, +- &validation); +- +- result = map_validation_to_info3(mem_ctx, validation_level, &validation, info3); +- if (!NT_STATUS_IS_OK(result)) { +- return result; +- } +- +- return result; ++ return rpccli_netlogon_sam_network_logon(cli, ++ mem_ctx, ++ logon_parameters, ++ server, ++ username, ++ domain, ++ workstation, ++ chal, ++ validation_level, ++ lm_response, ++ nt_response, ++ info3); + } + + /********************************************************* +@@ -605,11 +442,9 @@ NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, + const unsigned char new_trust_passwd_hash[16], + enum netr_SchannelType sec_channel_type) + { +- NTSTATUS result, status; +- struct netr_Authenticator clnt_creds, srv_cred; +- struct dcerpc_binding_handle *b = cli->binding_handle; ++ NTSTATUS result; + +- if (!cli->dc) { ++ if (cli->netlogon_creds == NULL) { + uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | + NETLOGON_NEG_SUPPORTS_AES; + result = rpccli_netlogon_setup_creds(cli, +@@ -627,77 +462,16 @@ NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, + } + } + +- netlogon_creds_client_authenticator(cli->dc, &clnt_creds); +- +- if (cli->dc->negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) { +- +- struct netr_CryptPassword new_password; +- uint32_t old_timeout; +- +- init_netr_CryptPassword(new_trust_pwd_cleartext, +- cli->dc, +- &new_password); +- +- old_timeout = dcerpc_binding_handle_set_timeout(b, 600000); +- +- status = dcerpc_netr_ServerPasswordSet2(b, mem_ctx, +- cli->srv_name_slash, +- cli->dc->account_name, +- sec_channel_type, +- cli->dc->computer_name, +- &clnt_creds, +- &srv_cred, +- &new_password, +- &result); +- +- dcerpc_binding_handle_set_timeout(b, old_timeout); +- +- if (!NT_STATUS_IS_OK(status)) { +- DEBUG(0,("dcerpc_netr_ServerPasswordSet2 failed: %s\n", +- nt_errstr(status))); +- return status; +- } +- } else { +- +- struct samr_Password new_password; +- uint32_t old_timeout; +- +- memcpy(new_password.hash, new_trust_passwd_hash, sizeof(new_password.hash)); +- netlogon_creds_des_encrypt(cli->dc, &new_password); +- +- old_timeout = dcerpc_binding_handle_set_timeout(b, 600000); +- +- status = dcerpc_netr_ServerPasswordSet(b, mem_ctx, +- cli->srv_name_slash, +- cli->dc->account_name, +- sec_channel_type, +- cli->dc->computer_name, +- &clnt_creds, +- &srv_cred, +- &new_password, +- &result); +- +- dcerpc_binding_handle_set_timeout(b, old_timeout); +- +- if (!NT_STATUS_IS_OK(status)) { +- DEBUG(0,("dcerpc_netr_ServerPasswordSet failed: %s\n", +- nt_errstr(status))); +- return status; +- } +- } +- +- /* Always check returned credentials. */ +- if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) { +- DEBUG(0,("credentials chain check failed\n")); +- return NT_STATUS_ACCESS_DENIED; +- } +- ++ result = netlogon_creds_cli_ServerPasswordSet(cli->netlogon_creds, ++ cli->binding_handle, ++ new_trust_pwd_cleartext, ++ NULL); /* new_version */ + if (!NT_STATUS_IS_OK(result)) { +- DEBUG(0,("dcerpc_netr_ServerPasswordSet{2} failed: %s\n", ++ DEBUG(0,("netlogon_creds_cli_ServerPasswordSet failed: %s\n", + nt_errstr(result))); + return result; + } + +- return result; ++ return NT_STATUS_OK; + } + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index a45023f..fe1613d 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -24,6 +24,7 @@ + #include "librpc/gen_ndr/ndr_epmapper_c.h" + #include "../librpc/gen_ndr/ndr_dssetup.h" + #include "../libcli/auth/schannel.h" ++#include "../libcli/auth/netlogon_creds_cli.h" + #include "auth_generic.h" + #include "librpc/gen_ndr/ndr_dcerpc.h" + #include "librpc/gen_ndr/ndr_netlogon_c.h" +@@ -3024,34 +3025,39 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + enum dcerpc_transport_t transport, + enum dcerpc_AuthLevel auth_level, + const char *domain, +- struct netlogon_creds_CredentialState **pdc, ++ struct netlogon_creds_cli_context *netlogon_creds, + struct rpc_pipe_client **_rpccli) + { + struct rpc_pipe_client *rpccli; + struct pipe_auth_data *rpcauth; ++ struct netlogon_creds_CredentialState *creds = NULL; + NTSTATUS status; +- NTSTATUS result; +- struct netlogon_creds_CredentialState save_creds; +- struct netr_Authenticator auth; +- struct netr_Authenticator return_auth; +- union netr_Capabilities capabilities; + const char *target_service = table->authservices->names[0]; ++ int rpc_pipe_bind_dbglvl = 0; + + status = cli_rpc_pipe_open(cli, transport, table, &rpccli); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + ++ status = netlogon_creds_cli_lock(netlogon_creds, rpccli, &creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ DEBUG(0, ("netlogon_creds_cli_get returned %s\n", ++ nt_errstr(status))); ++ TALLOC_FREE(rpccli); ++ return status; ++ } ++ + status = rpccli_generic_bind_data(rpccli, + DCERPC_AUTH_TYPE_SCHANNEL, + auth_level, + NULL, + target_service, + domain, +- (*pdc)->computer_name, ++ creds->computer_name, + NULL, + CRED_AUTO_USE_KERBEROS, +- *pdc, ++ creds, + &rpcauth); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("rpccli_generic_bind_data returned %s\n", +@@ -3060,120 +3066,43 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + return status; + } + +- /* +- * The credentials on a new netlogon pipe are the ones we are passed +- * in - copy them over +- * +- * This may get overwritten... in rpc_pipe_bind()... +- */ +- rpccli->dc = netlogon_creds_copy(rpccli, *pdc); +- if (rpccli->dc == NULL) { +- TALLOC_FREE(rpccli); +- return NT_STATUS_NO_MEMORY; +- } +- + status = rpc_pipe_bind(rpccli, rpcauth); ++ if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) { ++ rpc_pipe_bind_dbglvl = 1; ++ netlogon_creds_cli_delete(netlogon_creds, &creds); ++ } + if (!NT_STATUS_IS_OK(status)) { +- DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: " +- "cli_rpc_pipe_bind failed with error %s\n", +- nt_errstr(status) )); ++ DEBUG(rpc_pipe_bind_dbglvl, ++ ("cli_rpc_pipe_open_schannel_with_key: " ++ "rpc_pipe_bind failed with error %s\n", ++ nt_errstr(status))); + TALLOC_FREE(rpccli); + return status; + } + +- if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) { +- goto done; +- } +- +- save_creds = *rpccli->dc; +- ZERO_STRUCT(return_auth); +- ZERO_STRUCT(capabilities); ++ TALLOC_FREE(creds); + +- netlogon_creds_client_authenticator(&save_creds, &auth); +- +- status = dcerpc_netr_LogonGetCapabilities(rpccli->binding_handle, +- talloc_tos(), +- rpccli->srv_name_slash, +- save_creds.computer_name, +- &auth, &return_auth, +- 1, &capabilities, +- &result); +- if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { +- if (save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { +- DEBUG(5, ("AES was negotiated and the error was %s - " +- "downgrade detected\n", +- nt_errstr(status))); +- TALLOC_FREE(rpccli); +- return NT_STATUS_INVALID_NETWORK_RESPONSE; +- } +- +- /* This is probably an old Samba Version */ +- DEBUG(5, ("We are checking against an NT or old Samba - %s\n", +- nt_errstr(status))); ++ if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) { + goto done; + } + ++ status = netlogon_creds_cli_check(netlogon_creds, ++ rpccli->binding_handle); + if (!NT_STATUS_IS_OK(status)) { +- DEBUG(0, ("dcerpc_netr_LogonGetCapabilities failed with %s\n", ++ DEBUG(0, ("netlogon_creds_cli_check failed with %s\n", + nt_errstr(status))); + TALLOC_FREE(rpccli); + return status; + } + +- if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) { +- if (save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { +- /* This means AES isn't supported. */ +- DEBUG(5, ("AES was negotiated and the result was %s - " +- "downgrade detected\n", +- nt_errstr(result))); +- TALLOC_FREE(rpccli); +- return NT_STATUS_INVALID_NETWORK_RESPONSE; +- } +- +- /* This is probably an old Windows version */ +- DEBUG(5, ("We are checking against an win2k3 or Samba - %s\n", +- nt_errstr(result))); +- goto done; +- } +- +- /* +- * We need to check the credential state here, cause win2k3 and earlier +- * returns NT_STATUS_NOT_IMPLEMENTED +- */ +- if (!netlogon_creds_client_check(&save_creds, &return_auth.cred)) { +- /* +- * Server replied with bad credential. Fail. +- */ +- DEBUG(0,("cli_rpc_pipe_open_schannel_with_key: server %s " +- "replied with bad credential\n", +- rpccli->desthost)); +- TALLOC_FREE(rpccli); +- return NT_STATUS_INVALID_NETWORK_RESPONSE; +- } +- *rpccli->dc = save_creds; +- +- if (!NT_STATUS_IS_OK(result)) { +- DEBUG(0, ("dcerpc_netr_LogonGetCapabilities failed with %s\n", +- nt_errstr(result))); +- TALLOC_FREE(rpccli); +- return result; +- } +- +- if (!(save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)) { +- /* This means AES isn't supported. */ +- DEBUG(5, ("AES is not negotiated, but netr_LogonGetCapabilities " +- "was OK - downgrade detected\n")); +- TALLOC_FREE(rpccli); +- return NT_STATUS_INVALID_NETWORK_RESPONSE; +- } +- +- if (save_creds.negotiate_flags != capabilities.server_capabilities) { +- DEBUG(0, ("The client capabilities don't match the server " +- "capabilities: local[0x%08X] remote[0x%08X]\n", +- save_creds.negotiate_flags, +- capabilities.server_capabilities)); ++ status = netlogon_creds_cli_context_copy(netlogon_creds, ++ rpccli, ++ &rpccli->netlogon_creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ DEBUG(0, ("netlogon_creds_cli_context_copy failed with %s\n", ++ nt_errstr(status))); + TALLOC_FREE(rpccli); +- return NT_STATUS_INVALID_NETWORK_RESPONSE; ++ return status; + } + + done: +diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h +index 826f9bf..cf0c5c6 100644 +--- a/source3/rpc_client/cli_pipe.h ++++ b/source3/rpc_client/cli_pipe.h +@@ -96,7 +96,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + enum dcerpc_transport_t transport, + enum dcerpc_AuthLevel auth_level, + const char *domain, +- struct netlogon_creds_CredentialState **pdc, ++ struct netlogon_creds_cli_context *netlogon_creds, + struct rpc_pipe_client **presult); + + NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, +diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c +index aaae44b..e3d65c8 100644 +--- a/source3/rpc_client/cli_pipe_schannel.c ++++ b/source3/rpc_client/cli_pipe_schannel.c +@@ -112,7 +112,8 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, + } + + status = cli_rpc_pipe_open_schannel_with_key( +- cli, table, transport, auth_level, domain, &netlogon_pipe->dc, ++ cli, table, transport, auth_level, domain, ++ netlogon_pipe->netlogon_creds, + &result); + + /* Now we've bound using the session key we can close the netlog pipe. */ +diff --git a/source3/rpc_client/rpc_client.h b/source3/rpc_client/rpc_client.h +index 8024f01..7c4cceb 100644 +--- a/source3/rpc_client/rpc_client.h ++++ b/source3/rpc_client/rpc_client.h +@@ -50,7 +50,7 @@ struct rpc_pipe_client { + struct pipe_auth_data *auth; + + /* The following is only non-null on a netlogon client pipe. */ +- struct netlogon_creds_CredentialState *dc; ++ struct netlogon_creds_cli_context *netlogon_creds; + }; + + #endif /* _RPC_CLIENT_H */ +diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c +index d92434b..2e0b5e5 100644 +--- a/source3/rpcclient/cmd_netlogon.c ++++ b/source3/rpcclient/cmd_netlogon.c +@@ -26,6 +26,7 @@ + #include "../librpc/gen_ndr/ndr_netlogon_c.h" + #include "rpc_client/cli_netlogon.h" + #include "secrets.h" ++#include "../libcli/auth/netlogon_creds_cli.h" + + static WERROR cmd_netlogon_logon_ctrl2(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, int argc, +@@ -630,8 +631,15 @@ static NTSTATUS cmd_netlogon_sam_sync(struct rpc_pipe_client *cli, + + do { + struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; ++ struct netlogon_creds_CredentialState *creds = NULL; + +- netlogon_creds_client_authenticator(cli->dc, &credential); ++ status = netlogon_creds_cli_lock(cli->netlogon_creds, ++ mem_ctx, &creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ netlogon_creds_client_authenticator(creds, &credential); + + status = dcerpc_netr_DatabaseSync2(b, mem_ctx, + logon_server, +@@ -645,15 +653,18 @@ static NTSTATUS cmd_netlogon_sam_sync(struct rpc_pipe_client *cli, + 0xffff, + &result); + if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(creds); + return status; + } + + /* Check returned credentials. */ +- if (!netlogon_creds_client_check(cli->dc, ++ if (!netlogon_creds_client_check(creds, + &return_authenticator.cred)) { + DEBUG(0,("credentials chain check failed\n")); ++ TALLOC_FREE(creds); + return NT_STATUS_ACCESS_DENIED; + } ++ TALLOC_FREE(creds); + + if (NT_STATUS_IS_ERR(result)) { + break; +@@ -699,8 +710,15 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli, + + do { + struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; ++ struct netlogon_creds_CredentialState *creds = NULL; ++ ++ status = netlogon_creds_cli_lock(cli->netlogon_creds, ++ mem_ctx, &creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } + +- netlogon_creds_client_authenticator(cli->dc, &credential); ++ netlogon_creds_client_authenticator(creds, &credential); + + status = dcerpc_netr_DatabaseDeltas(b, mem_ctx, + logon_server, +@@ -713,15 +731,18 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli, + 0xffff, + &result); + if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(creds); + return status; + } + + /* Check returned credentials. */ +- if (!netlogon_creds_client_check(cli->dc, ++ if (!netlogon_creds_client_check(creds, + &return_authenticator.cred)) { + DEBUG(0,("credentials chain check failed\n")); ++ TALLOC_FREE(creds); + return NT_STATUS_ACCESS_DENIED; + } ++ TALLOC_FREE(creds); + + if (NT_STATUS_IS_ERR(result)) { + break; +@@ -1129,6 +1150,7 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, + struct netr_ChangeLogEntry e; + uint32_t rid = 500; + struct dcerpc_binding_handle *b = cli->binding_handle; ++ struct netlogon_creds_CredentialState *creds = NULL; + + if (argc > 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); +@@ -1158,7 +1180,13 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, + return status; + } + +- netlogon_creds_client_authenticator(cli->dc, &clnt_creds); ++ status = netlogon_creds_cli_lock(cli->netlogon_creds, ++ mem_ctx, &creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ netlogon_creds_client_authenticator(creds, &clnt_creds); + + ZERO_STRUCT(e); + +@@ -1176,13 +1204,16 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, + &delta_enum_array, + &result); + if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(creds); + return status; + } + +- if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) { ++ if (!netlogon_creds_client_check(creds, &srv_cred.cred)) { + DEBUG(0,("credentials chain check failed\n")); ++ TALLOC_FREE(creds); + return NT_STATUS_ACCESS_DENIED; + } ++ TALLOC_FREE(creds); + + return result; + } +@@ -1198,6 +1229,7 @@ static NTSTATUS cmd_netlogon_capabilities(struct rpc_pipe_client *cli, + union netr_Capabilities capabilities; + uint32_t level = 1; + struct dcerpc_binding_handle *b = cli->binding_handle; ++ struct netlogon_creds_CredentialState *creds = NULL; + + if (argc > 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); +@@ -1210,7 +1242,13 @@ static NTSTATUS cmd_netlogon_capabilities(struct rpc_pipe_client *cli, + + ZERO_STRUCT(return_authenticator); + +- netlogon_creds_client_authenticator(cli->dc, &credential); ++ status = netlogon_creds_cli_lock(cli->netlogon_creds, ++ mem_ctx, &creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ netlogon_creds_client_authenticator(creds, &credential); + + status = dcerpc_netr_LogonGetCapabilities(b, mem_ctx, + cli->desthost, +@@ -1221,14 +1259,17 @@ static NTSTATUS cmd_netlogon_capabilities(struct rpc_pipe_client *cli, + &capabilities, + &result); + if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(creds); + return status; + } + +- if (!netlogon_creds_client_check(cli->dc, ++ if (!netlogon_creds_client_check(creds, + &return_authenticator.cred)) { + DEBUG(0,("credentials chain check failed\n")); ++ TALLOC_FREE(creds); + return NT_STATUS_ACCESS_DENIED; + } ++ TALLOC_FREE(creds); + + printf("capabilities: 0x%08x\n", capabilities.server_capabilities); + +diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h +index afde685..b5fc010 100644 +--- a/source3/winbindd/winbindd.h ++++ b/source3/winbindd/winbindd.h +@@ -165,16 +165,7 @@ struct winbindd_domain { + time_t startup_time; /* When we set "startup" true. monotonic clock */ + bool startup; /* are we in the first 30 seconds after startup_time ? */ + +- bool can_do_samlogon_ex; /* Due to the lack of finer control what type +- * of DC we have, let us try to do a +- * credential-chain less samlogon_ex call +- * with AD and schannel. If this fails with +- * DCERPC_FAULT_OP_RNG_ERROR, then set this +- * to False. This variable is around so that +- * we don't have to try _ex every time. */ +- + bool can_do_ncacn_ip_tcp; +- bool can_do_validation6; + + /* Lookup methods for this domain (LDAP or RPC) */ + struct winbindd_methods *methods; +diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c +index 6c1244e..e0d1d0c 100644 +--- a/source3/winbindd/winbindd_cm.c ++++ b/source3/winbindd/winbindd_cm.c +@@ -2047,7 +2047,6 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) + domain->active_directory ? "" : "NOT ")); + + domain->can_do_ncacn_ip_tcp = domain->active_directory; +- domain->can_do_validation6 = domain->active_directory; + + domain->initialized = True; + +@@ -2248,7 +2247,6 @@ done: + domain->name, domain->active_directory ? "" : "NOT ")); + + domain->can_do_ncacn_ip_tcp = domain->active_directory; +- domain->can_do_validation6 = domain->active_directory; + + TALLOC_FREE(cli); + +@@ -2289,7 +2287,7 @@ static void set_dc_type_and_flags( struct winbindd_domain *domain ) + ***********************************************************************/ + + static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain, +- struct netlogon_creds_CredentialState **ppdc) ++ struct netlogon_creds_cli_context **ppdc) + { + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + struct rpc_pipe_client *netlogon_pipe; +@@ -2306,11 +2304,11 @@ static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain, + /* Return a pointer to the struct netlogon_creds_CredentialState from the + netlogon pipe. */ + +- if (!domain->conn.netlogon_pipe->dc) { ++ if (!domain->conn.netlogon_pipe->netlogon_creds) { + return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */ + } + +- *ppdc = domain->conn.netlogon_pipe->dc; ++ *ppdc = domain->conn.netlogon_pipe->netlogon_creds; + return NT_STATUS_OK; + } + +@@ -2319,7 +2317,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + { + struct winbindd_cm_conn *conn; + NTSTATUS status, result; +- struct netlogon_creds_CredentialState *p_creds; ++ struct netlogon_creds_cli_context *p_creds; + char *machine_password = NULL; + char *machine_account = NULL; + const char *domain_name = NULL; +@@ -2431,7 +2429,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + status = cli_rpc_pipe_open_schannel_with_key + (conn->cli, &ndr_table_samr, NCACN_NP, + DCERPC_AUTH_LEVEL_PRIVACY, +- domain->name, &p_creds, &conn->samr_pipe); ++ domain->name, p_creds, &conn->samr_pipe); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for " +@@ -2534,7 +2532,7 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain, + struct rpc_pipe_client **cli) + { + struct winbindd_cm_conn *conn; +- struct netlogon_creds_CredentialState *creds; ++ struct netlogon_creds_cli_context *creds; + NTSTATUS status; + + DEBUG(10,("cm_connect_lsa_tcp\n")); +@@ -2565,7 +2563,7 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain, + NCACN_IP_TCP, + DCERPC_AUTH_LEVEL_PRIVACY, + domain->name, +- &creds, ++ creds, + &conn->lsa_pipe_tcp); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n", +@@ -2589,7 +2587,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + { + struct winbindd_cm_conn *conn; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; +- struct netlogon_creds_CredentialState *p_creds; ++ struct netlogon_creds_cli_context *p_creds; + + result = init_dc_connection_rpc(domain); + if (!NT_STATUS_IS_OK(result)) +@@ -2662,7 +2660,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + result = cli_rpc_pipe_open_schannel_with_key + (conn->cli, &ndr_table_lsarpc, NCACN_NP, + DCERPC_AUTH_LEVEL_PRIVACY, +- domain->name, &p_creds, &conn->lsa_pipe); ++ domain->name, p_creds, &conn->lsa_pipe); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for " +@@ -2826,10 +2824,6 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, + no_schannel: + if ((lp_client_schannel() == False) || + ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { +- /* +- * NetSamLogonEx only works for schannel +- */ +- domain->can_do_samlogon_ex = False; + + /* We're done - just keep the existing connection to NETLOGON + * open */ +@@ -2845,7 +2839,8 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, + + result = cli_rpc_pipe_open_schannel_with_key( + conn->cli, &ndr_table_netlogon, NCACN_NP, +- DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc, ++ DCERPC_AUTH_LEVEL_PRIVACY, domain->name, ++ netlogon_pipe->netlogon_creds, + &conn->netlogon_pipe); + + /* We can now close the initial netlogon pipe. */ +@@ -2859,15 +2854,6 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, + return result; + } + +- /* +- * Always try netr_LogonSamLogonEx. We will fall back for NT4 +- * which gives DCERPC_FAULT_OP_RNG_ERROR (function not +- * supported). We used to only try SamLogonEx for AD, but +- * Samba DCs can also do it. And because we don't distinguish +- * between Samba and NT4, always try it once. +- */ +- domain->can_do_samlogon_ex = true; +- + *cli = conn->netlogon_pipe; + return NT_STATUS_OK; + } +diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c +index c356686..39483a5 100644 +--- a/source3/winbindd/winbindd_pam.c ++++ b/source3/winbindd/winbindd_pam.c +@@ -1228,8 +1228,6 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, + + do { + struct rpc_pipe_client *netlogon_pipe; +- const struct pipe_auth_data *auth; +- uint32_t neg_flags = 0; + + ZERO_STRUCTP(info3); + retry = false; +@@ -1278,75 +1276,7 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, + } + netr_attempts = 0; + +- auth = netlogon_pipe->auth; +- if (netlogon_pipe->dc) { +- neg_flags = netlogon_pipe->dc->negotiate_flags; +- } +- +- /* It is really important to try SamLogonEx here, +- * because in a clustered environment, we want to use +- * one machine account from multiple physical +- * computers. +- * +- * With a normal SamLogon call, we must keep the +- * credentials chain updated and intact between all +- * users of the machine account (which would imply +- * cross-node communication for every NTLM logon). +- * +- * (The credentials chain is not per NETLOGON pipe +- * connection, but globally on the server/client pair +- * by machine name). +- * +- * When using SamLogonEx, the credentials are not +- * supplied, but the session key is implied by the +- * wrapping SamLogon context. +- * +- * -- abartlet 21 April 2008 +- * +- * It's also important to use NetlogonValidationSamInfo4 (6), +- * because it relies on the rpc transport encryption +- * and avoids using the global netlogon schannel +- * session key to en/decrypt secret information +- * like the user_session_key for network logons. +- * +- * [MS-APDS] 3.1.5.2 NTLM Network Logon +- * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and +- * NETLOGON_NEG_AUTHENTICATED_RPC set together +- * are the indication that the server supports +- * NetlogonValidationSamInfo4 (6). And it must only +- * be used if "SealSecureChannel" is used. +- * +- * -- metze 4 February 2011 +- */ +- +- if (auth == NULL) { +- domain->can_do_validation6 = false; +- } else if (auth->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { +- domain->can_do_validation6 = false; +- } else if (auth->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) { +- domain->can_do_validation6 = false; +- } else if (!(neg_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) { +- domain->can_do_validation6 = false; +- } else if (!(neg_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { +- domain->can_do_validation6 = false; +- } +- +- if (domain->can_do_samlogon_ex && domain->can_do_validation6) { +- result = rpccli_netlogon_sam_network_logon_ex( +- netlogon_pipe, +- mem_ctx, +- logon_parameters, +- server, /* server name */ +- username, /* user name */ +- domainname, /* target domain */ +- workstation, /* workstation */ +- chal, +- 6, +- lm_response, +- nt_response, +- info3); +- } else { +- result = rpccli_netlogon_sam_network_logon( ++ result = rpccli_netlogon_sam_network_logon( + netlogon_pipe, + mem_ctx, + logon_parameters, +@@ -1355,48 +1285,10 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, + domainname, /* target domain */ + workstation, /* workstation */ + chal, +- domain->can_do_validation6 ? 6 : 3, ++ -1, /* ignored */ + lm_response, + nt_response, + info3); +- } +- +- if (NT_STATUS_EQUAL(result, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { +- +- /* +- * It's likely that the server also does not support +- * validation level 6 +- */ +- domain->can_do_validation6 = false; +- +- if (domain->can_do_samlogon_ex) { +- DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " +- "retrying with NetSamLogon\n")); +- domain->can_do_samlogon_ex = false; +- retry = true; +- continue; +- } +- +- +- /* Got DCERPC_FAULT_OP_RNG_ERROR for SamLogon +- * (no Ex). This happens against old Samba +- * DCs. Drop the connection. +- */ +- invalidate_cm_connection(&domain->conn); +- result = NT_STATUS_LOGON_FAILURE; +- break; +- } +- +- if (domain->can_do_validation6 && +- (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS) || +- NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER) || +- NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL))) { +- DEBUG(3,("Got a DC that can not do validation level 6, " +- "retrying with level 3\n")); +- domain->can_do_validation6 = false; +- retry = true; +- continue; +- } + + /* + * we increment this after the "feature negotiation" +@@ -1428,6 +1320,30 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, + retry = true; + } + ++ if (NT_STATUS_EQUAL(result, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { ++ /* ++ * Got DCERPC_FAULT_OP_RNG_ERROR for SamLogon ++ * (no Ex). This happens against old Samba ++ * DCs, if LogonSamLogonEx() fails with an error ++ * e.g. NT_STATUS_NO_SUCH_USER or NT_STATUS_WRONG_PASSWORD. ++ * ++ * The server will log something like this: ++ * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX. ++ * ++ * This sets the whole connection into a fault_state mode ++ * and all following request get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE. ++ * ++ * This also happens to our retry with LogonSamLogonWithFlags() ++ * and LogonSamLogon(). ++ * ++ * In order to recover from this situation, we need to ++ * drop the connection. ++ */ ++ invalidate_cm_connection(&domain->conn); ++ result = NT_STATUS_LOGON_FAILURE; ++ break; ++ } ++ + } while ( (attempts < 2) && retry ); + + if (NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT)) { +diff --git a/source3/wscript_build b/source3/wscript_build +index 13d15c3..0d3ba8e 100755 +--- a/source3/wscript_build ++++ b/source3/wscript_build +@@ -671,8 +671,8 @@ bld.SAMBA3_LIBRARY('msrpc3', + deps='''ndr ndr-standard + RPC_NDR_EPMAPPER NTLMSSP_COMMON COMMON_SCHANNEL LIBCLI_AUTH + LIBTSOCKET gse dcerpc-binding +- libsmb +- ndr-table''', ++ libsmb ndr-table NETLOGON_CREDS_CLI ++ ''', + vars=locals(), + private_library=True) + +@@ -1114,7 +1114,7 @@ bld.SAMBA3_LIBRARY('libcli_lsa3', + + bld.SAMBA3_LIBRARY('libcli_netlogon3', + source=LIBCLI_NETLOGON_SRC, +- deps='RPC_NDR_NETLOGON INIT_NETLOGON cliauth param', ++ deps='msrpc3 RPC_NDR_NETLOGON INIT_NETLOGON cliauth param NETLOGON_CREDS_CLI', + private_library=True) + + bld.SAMBA3_LIBRARY('cli_spoolss', +-- +1.9.3 + + +From 0b489bffb452e05d595abc2894532100162a4e8c Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 17 Oct 2013 17:03:00 +0200 +Subject: [PATCH 175/249] s3:rpc_client: use netlogon_creds_cli_auth_level() in + cli_rpc_pipe_open_schannel_with_key() + +This means the auth level is now based on the "winbindd sealed pipes" option, +defaulting to "yes" and DCERPC_AUTH_LEVEL_PRIVACY. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 5adfc5f9f737c003b84b0187fa17b9fc3784442e) +--- + source3/libnet/libnet_join.c | 1 - + source3/rpc_client/cli_pipe.c | 4 +++- + source3/rpc_client/cli_pipe.h | 1 - + source3/rpc_client/cli_pipe_schannel.c | 2 +- + source3/winbindd/winbindd_cm.c | 5 +---- + 5 files changed, 5 insertions(+), 8 deletions(-) + +diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c +index 5dc620f..b2805ee 100644 +--- a/source3/libnet/libnet_join.c ++++ b/source3/libnet/libnet_join.c +@@ -1278,7 +1278,6 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, + + status = cli_rpc_pipe_open_schannel_with_key( + cli, &ndr_table_netlogon, NCACN_NP, +- DCERPC_AUTH_LEVEL_PRIVACY, + netbios_domain_name, + netlogon_pipe->netlogon_creds, &pipe_hnd); + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index fe1613d..31cd7f5 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -3023,7 +3023,6 @@ NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli, + NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + const struct ndr_interface_table *table, + enum dcerpc_transport_t transport, +- enum dcerpc_AuthLevel auth_level, + const char *domain, + struct netlogon_creds_cli_context *netlogon_creds, + struct rpc_pipe_client **_rpccli) +@@ -3031,6 +3030,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + struct rpc_pipe_client *rpccli; + struct pipe_auth_data *rpcauth; + struct netlogon_creds_CredentialState *creds = NULL; ++ enum dcerpc_AuthLevel auth_level; + NTSTATUS status; + const char *target_service = table->authservices->names[0]; + int rpc_pipe_bind_dbglvl = 0; +@@ -3048,6 +3048,8 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + return status; + } + ++ auth_level = netlogon_creds_cli_auth_level(netlogon_creds); ++ + status = rpccli_generic_bind_data(rpccli, + DCERPC_AUTH_TYPE_SCHANNEL, + auth_level, +diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h +index cf0c5c6..c21c55d 100644 +--- a/source3/rpc_client/cli_pipe.h ++++ b/source3/rpc_client/cli_pipe.h +@@ -94,7 +94,6 @@ NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli, + NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + const struct ndr_interface_table *table, + enum dcerpc_transport_t transport, +- enum dcerpc_AuthLevel auth_level, + const char *domain, + struct netlogon_creds_cli_context *netlogon_creds, + struct rpc_pipe_client **presult); +diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c +index e3d65c8..8f9161f 100644 +--- a/source3/rpc_client/cli_pipe_schannel.c ++++ b/source3/rpc_client/cli_pipe_schannel.c +@@ -112,7 +112,7 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, + } + + status = cli_rpc_pipe_open_schannel_with_key( +- cli, table, transport, auth_level, domain, ++ cli, table, transport, domain, + netlogon_pipe->netlogon_creds, + &result); + +diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c +index e0d1d0c..1546002 100644 +--- a/source3/winbindd/winbindd_cm.c ++++ b/source3/winbindd/winbindd_cm.c +@@ -2428,7 +2428,6 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + } + status = cli_rpc_pipe_open_schannel_with_key + (conn->cli, &ndr_table_samr, NCACN_NP, +- DCERPC_AUTH_LEVEL_PRIVACY, + domain->name, p_creds, &conn->samr_pipe); + + if (!NT_STATUS_IS_OK(status)) { +@@ -2561,7 +2560,6 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain, + status = cli_rpc_pipe_open_schannel_with_key(conn->cli, + &ndr_table_lsarpc, + NCACN_IP_TCP, +- DCERPC_AUTH_LEVEL_PRIVACY, + domain->name, + creds, + &conn->lsa_pipe_tcp); +@@ -2659,7 +2657,6 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + } + result = cli_rpc_pipe_open_schannel_with_key + (conn->cli, &ndr_table_lsarpc, NCACN_NP, +- DCERPC_AUTH_LEVEL_PRIVACY, + domain->name, p_creds, &conn->lsa_pipe); + + if (!NT_STATUS_IS_OK(result)) { +@@ -2839,7 +2836,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, + + result = cli_rpc_pipe_open_schannel_with_key( + conn->cli, &ndr_table_netlogon, NCACN_NP, +- DCERPC_AUTH_LEVEL_PRIVACY, domain->name, ++ domain->name, + netlogon_pipe->netlogon_creds, + &conn->netlogon_pipe); + +-- +1.9.3 + + +From 0f19f3b64e4f0b969eec4f2048df7c40be661e82 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 7 Aug 2013 11:27:25 +0200 +Subject: [PATCH 176/249] s3:rpc_client: add + rpccli_{create,setup}_netlogon_creds() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 14ceb7b501fce6623be284cbcceb573fd2e10d3a) +--- + source3/rpc_client/cli_netlogon.c | 105 ++++++++++++++++++++++++++++++++++++++ + source3/rpc_client/cli_netlogon.h | 16 ++++++ + 2 files changed, 121 insertions(+) + +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index fcd24d6..89aec37 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -21,15 +21,19 @@ + */ + + #include "includes.h" ++#include "libsmb/libsmb.h" + #include "rpc_client/rpc_client.h" ++#include "rpc_client/cli_pipe.h" + #include "../libcli/auth/libcli_auth.h" + #include "../libcli/auth/netlogon_creds_cli.h" + #include "../librpc/gen_ndr/ndr_netlogon_c.h" ++#include "../librpc/gen_ndr/schannel.h" + #include "rpc_client/cli_netlogon.h" + #include "rpc_client/init_netlogon.h" + #include "rpc_client/util_netlogon.h" + #include "../libcli/security/security.h" + #include "lib/param/param.h" ++#include "libcli/smb/smbXcli_base.h" + + /**************************************************************************** + Wrapper function that uses the auth and auth2 calls to set up a NETLOGON +@@ -124,6 +128,107 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, + return NT_STATUS_OK; + } + ++NTSTATUS rpccli_create_netlogon_creds(const char *server_computer, ++ const char *server_netbios_domain, ++ const char *client_account, ++ enum netr_SchannelType sec_chan_type, ++ struct messaging_context *msg_ctx, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_cli_context **netlogon_creds) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct loadparm_context *lp_ctx; ++ NTSTATUS status; ++ ++ lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); ++ if (lp_ctx == NULL) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ status = netlogon_creds_cli_context_global(lp_ctx, ++ msg_ctx, ++ client_account, ++ sec_chan_type, ++ server_computer, ++ server_netbios_domain, ++ mem_ctx, netlogon_creds); ++ TALLOC_FREE(frame); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ return NT_STATUS_OK; ++} ++ ++NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, ++ struct netlogon_creds_cli_context *netlogon_creds, ++ bool force_reauth, ++ struct samr_Password current_nt_hash, ++ const struct samr_Password *previous_nt_hash) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct rpc_pipe_client *netlogon_pipe = NULL; ++ struct netlogon_creds_CredentialState *creds = NULL; ++ NTSTATUS status; ++ ++ status = netlogon_creds_cli_get(netlogon_creds, ++ frame, &creds); ++ if (NT_STATUS_IS_OK(status)) { ++ const char *action = "using"; ++ ++ if (force_reauth) { ++ action = "overwrite"; ++ } ++ ++ DEBUG(5,("%s: %s cached netlogon_creds cli[%s/%s] to %s\n", ++ __FUNCTION__, action, ++ creds->account_name, creds->computer_name, ++ smbXcli_conn_remote_name(cli->conn))); ++ if (!force_reauth) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_OK; ++ } ++ TALLOC_FREE(creds); ++ } ++ ++ status = cli_rpc_pipe_open_noauth(cli, ++ &ndr_table_netlogon, ++ &netlogon_pipe); ++ if (!NT_STATUS_IS_OK(status)) { ++ DEBUG(5,("%s: failed to open noauth netlogon connection to %s - %s\n", ++ __FUNCTION__, ++ smbXcli_conn_remote_name(cli->conn), ++ nt_errstr(status))); ++ TALLOC_FREE(frame); ++ return status; ++ } ++ talloc_steal(frame, netlogon_pipe); ++ ++ status = netlogon_creds_cli_auth(netlogon_creds, ++ netlogon_pipe->binding_handle, ++ current_nt_hash, ++ previous_nt_hash); ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); ++ return status; ++ } ++ ++ status = netlogon_creds_cli_get(netlogon_creds, ++ frame, &creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_INTERNAL_ERROR; ++ } ++ ++ DEBUG(5,("%s: using new netlogon_creds cli[%s/%s] to %s\n", ++ __FUNCTION__, ++ creds->account_name, creds->computer_name, ++ smbXcli_conn_remote_name(cli->conn))); ++ ++ TALLOC_FREE(frame); ++ return NT_STATUS_OK; ++} ++ + /* Logon domain user */ + + NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, +diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h +index ad59d5b..82e0923 100644 +--- a/source3/rpc_client/cli_netlogon.h ++++ b/source3/rpc_client/cli_netlogon.h +@@ -23,6 +23,10 @@ + #ifndef _RPC_CLIENT_CLI_NETLOGON_H_ + #define _RPC_CLIENT_CLI_NETLOGON_H_ + ++struct cli_state; ++struct messaging_context; ++struct netlogon_creds_cli_context; ++ + /* The following definitions come from rpc_client/cli_netlogon.c */ + + NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, +@@ -33,6 +37,18 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, + const unsigned char machine_pwd[16], + enum netr_SchannelType sec_chan_type, + uint32_t *neg_flags_inout); ++NTSTATUS rpccli_create_netlogon_creds(const char *server_computer, ++ const char *server_netbios_domain, ++ const char *client_account, ++ enum netr_SchannelType sec_chan_type, ++ struct messaging_context *msg_ctx, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_cli_context **netlogon_creds); ++NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, ++ struct netlogon_creds_cli_context *netlogon_creds, ++ bool force_reauth, ++ struct samr_Password current_nt_hash, ++ const struct samr_Password *previous_nt_hash); + NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + uint32 logon_parameters, +-- +1.9.3 + + +From de0ed0882a458e52ef232e7d44234bf393311fc0 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 17 Dec 2013 20:05:56 +0100 +Subject: [PATCH 177/249] s3:rpc_client: add rpccli_pre_open_netlogon_creds() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 3c025af657899c9a2ff14f868c03ff72ab74cf8e) +--- + source3/rpc_client/cli_netlogon.c | 21 +++++++++++++++++++++ + source3/rpc_client/cli_netlogon.h | 1 + + 2 files changed, 22 insertions(+) + +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index 89aec37..9342fc3 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -128,6 +128,27 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, + return NT_STATUS_OK; + } + ++NTSTATUS rpccli_pre_open_netlogon_creds(void) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct loadparm_context *lp_ctx; ++ NTSTATUS status; ++ ++ lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); ++ if (lp_ctx == NULL) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ status = netlogon_creds_cli_open_global_db(lp_ctx); ++ TALLOC_FREE(frame); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ return NT_STATUS_OK; ++} ++ + NTSTATUS rpccli_create_netlogon_creds(const char *server_computer, + const char *server_netbios_domain, + const char *client_account, +diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h +index 82e0923..3096c48 100644 +--- a/source3/rpc_client/cli_netlogon.h ++++ b/source3/rpc_client/cli_netlogon.h +@@ -37,6 +37,7 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, + const unsigned char machine_pwd[16], + enum netr_SchannelType sec_chan_type, + uint32_t *neg_flags_inout); ++NTSTATUS rpccli_pre_open_netlogon_creds(void); + NTSTATUS rpccli_create_netlogon_creds(const char *server_computer, + const char *server_netbios_domain, + const char *client_account, +-- +1.9.3 + + +From f4f7df785d1641f1e21ad8374140715fd41be07a Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 27 Aug 2013 14:07:43 +0200 +Subject: [PATCH 178/249] s3:rpc_client: remove unused + rpccli_netlogon_sam_network_logon_ex() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit a07cc9a1c6ab8fee516e069a6f90bb48a7abf875) +--- + source3/rpc_client/cli_netlogon.c | 27 --------------------------- + source3/rpc_client/cli_netlogon.h | 12 ------------ + 2 files changed, 39 deletions(-) + +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index 9342fc3..253d060 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -524,33 +524,6 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, + return NT_STATUS_OK; + } + +-NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli, +- TALLOC_CTX *mem_ctx, +- uint32 logon_parameters, +- const char *server, +- const char *username, +- const char *domain, +- const char *workstation, +- const uint8 chal[8], +- uint16_t validation_level, +- DATA_BLOB lm_response, +- DATA_BLOB nt_response, +- struct netr_SamInfo3 **info3) +-{ +- return rpccli_netlogon_sam_network_logon(cli, +- mem_ctx, +- logon_parameters, +- server, +- username, +- domain, +- workstation, +- chal, +- validation_level, +- lm_response, +- nt_response, +- info3); +-} +- + /********************************************************* + Change the domain password on the PDC. + +diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h +index 3096c48..f10e5c7 100644 +--- a/source3/rpc_client/cli_netlogon.h ++++ b/source3/rpc_client/cli_netlogon.h +@@ -71,18 +71,6 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, + DATA_BLOB lm_response, + DATA_BLOB nt_response, + struct netr_SamInfo3 **info3); +-NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli, +- TALLOC_CTX *mem_ctx, +- uint32 logon_parameters, +- const char *server, +- const char *username, +- const char *domain, +- const char *workstation, +- const uint8 chal[8], +- uint16_t validation_level, +- DATA_BLOB lm_response, +- DATA_BLOB nt_response, +- struct netr_SamInfo3 **info3); + NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *account_name, +-- +1.9.3 + + +From b250859baf6c720e636c2435b0593af83acf6acc Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 27 Aug 2013 14:36:24 +0200 +Subject: [PATCH 179/249] s3:rpc_client: add rpccli_netlogon_network_logon() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 5196493c9e599b741417b119b48188ba0d646a37) +--- + source3/rpc_client/cli_netlogon.c | 103 ++++++++++++++++++++++++++++++++++++++ + source3/rpc_client/cli_netlogon.h | 14 ++++++ + 2 files changed, 117 insertions(+) + +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index 253d060..e335423 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -524,6 +524,109 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, + return NT_STATUS_OK; + } + ++NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds, ++ struct dcerpc_binding_handle *binding_handle, ++ TALLOC_CTX *mem_ctx, ++ uint32_t logon_parameters, ++ const char *username, ++ const char *domain, ++ const char *workstation, ++ const uint8 chal[8], ++ DATA_BLOB lm_response, ++ DATA_BLOB nt_response, ++ uint8_t *authoritative, ++ uint32_t *flags, ++ struct netr_SamInfo3 **info3) ++{ ++ NTSTATUS status; ++ const char *workstation_name_slash; ++ union netr_LogonLevel *logon = NULL; ++ struct netr_NetworkInfo *network_info; ++ uint16_t validation_level = 0; ++ union netr_Validation *validation = NULL; ++ uint8_t _authoritative = 0; ++ uint32_t _flags = 0; ++ struct netr_ChallengeResponse lm; ++ struct netr_ChallengeResponse nt; ++ ++ *info3 = NULL; ++ ++ if (authoritative == NULL) { ++ authoritative = &_authoritative; ++ } ++ if (flags == NULL) { ++ flags = &_flags; ++ } ++ ++ ZERO_STRUCT(lm); ++ ZERO_STRUCT(nt); ++ ++ logon = talloc_zero(mem_ctx, union netr_LogonLevel); ++ if (!logon) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo); ++ if (!network_info) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ if (workstation[0] != '\\' && workstation[1] != '\\') { ++ workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation); ++ } else { ++ workstation_name_slash = workstation; ++ } ++ ++ if (!workstation_name_slash) { ++ DEBUG(0, ("talloc_asprintf failed!\n")); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ /* Initialise input parameters */ ++ ++ lm.data = lm_response.data; ++ lm.length = lm_response.length; ++ nt.data = nt_response.data; ++ nt.length = nt_response.length; ++ ++ network_info->identity_info.domain_name.string = domain; ++ network_info->identity_info.parameter_control = logon_parameters; ++ network_info->identity_info.logon_id_low = 0xdead; ++ network_info->identity_info.logon_id_high = 0xbeef; ++ network_info->identity_info.account_name.string = username; ++ network_info->identity_info.workstation.string = workstation_name_slash; ++ ++ memcpy(network_info->challenge, chal, 8); ++ network_info->nt = nt; ++ network_info->lm = lm; ++ ++ logon->network = network_info; ++ ++ /* Marshall data and send request */ ++ ++ status = netlogon_creds_cli_LogonSamLogon(creds, ++ binding_handle, ++ NetlogonNetworkInformation, ++ logon, ++ mem_ctx, ++ &validation_level, ++ &validation, ++ authoritative, ++ flags); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ status = map_validation_to_info3(mem_ctx, ++ validation_level, validation, ++ info3); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ return NT_STATUS_OK; ++} ++ + /********************************************************* + Change the domain password on the PDC. + +diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h +index f10e5c7..54ed7ae 100644 +--- a/source3/rpc_client/cli_netlogon.h ++++ b/source3/rpc_client/cli_netlogon.h +@@ -26,6 +26,7 @@ + struct cli_state; + struct messaging_context; + struct netlogon_creds_cli_context; ++struct dcerpc_binding_handle; + + /* The following definitions come from rpc_client/cli_netlogon.c */ + +@@ -71,6 +72,19 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, + DATA_BLOB lm_response, + DATA_BLOB nt_response, + struct netr_SamInfo3 **info3); ++NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds, ++ struct dcerpc_binding_handle *binding_handle, ++ TALLOC_CTX *mem_ctx, ++ uint32_t logon_parameters, ++ const char *username, ++ const char *domain, ++ const char *workstation, ++ const uint8 chal[8], ++ DATA_BLOB lm_response, ++ DATA_BLOB nt_response, ++ uint8_t *authoritative, ++ uint32_t *flags, ++ struct netr_SamInfo3 **info3); + NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *account_name, +-- +1.9.3 + + +From 2488e78fdf3058bf3a48c2086afd0f3248a43417 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 27 Aug 2013 14:56:06 +0200 +Subject: [PATCH 180/249] s3:rpc_client: add rpccli_netlogon_password_logon() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit b7dc3fb20468aa67ea7ddc1cea21fbe458e74565) +--- + source3/rpc_client/cli_netlogon.c | 133 ++++++++++++++++++++++++++++++++++++++ + source3/rpc_client/cli_netlogon.h | 8 +++ + 2 files changed, 141 insertions(+) + +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index e335423..a9f8604 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -376,6 +376,139 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, + return NT_STATUS_OK; + } + ++NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds, ++ struct dcerpc_binding_handle *binding_handle, ++ uint32_t logon_parameters, ++ const char *domain, ++ const char *username, ++ const char *password, ++ const char *workstation, ++ enum netr_LogonInfoClass logon_type) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ NTSTATUS status; ++ union netr_LogonLevel *logon; ++ uint16_t validation_level = 0; ++ union netr_Validation *validation = NULL; ++ uint8_t authoritative = 0; ++ uint32_t flags = 0; ++ char *workstation_slash = NULL; ++ ++ logon = talloc_zero(frame, union netr_LogonLevel); ++ if (logon == NULL) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ if (workstation == NULL) { ++ workstation = lp_netbios_name(); ++ } ++ ++ workstation_slash = talloc_asprintf(frame, "\\\\%s", workstation); ++ if (workstation_slash == NULL) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ /* Initialise input parameters */ ++ ++ switch (logon_type) { ++ case NetlogonInteractiveInformation: { ++ ++ struct netr_PasswordInfo *password_info; ++ ++ struct samr_Password lmpassword; ++ struct samr_Password ntpassword; ++ ++ password_info = talloc_zero(frame, struct netr_PasswordInfo); ++ if (password_info == NULL) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash); ++ ++ password_info->identity_info.domain_name.string = domain; ++ password_info->identity_info.parameter_control = logon_parameters; ++ password_info->identity_info.logon_id_low = 0xdead; ++ password_info->identity_info.logon_id_high = 0xbeef; ++ password_info->identity_info.account_name.string = username; ++ password_info->identity_info.workstation.string = workstation_slash; ++ ++ password_info->lmpassword = lmpassword; ++ password_info->ntpassword = ntpassword; ++ ++ logon->password = password_info; ++ ++ break; ++ } ++ case NetlogonNetworkInformation: { ++ struct netr_NetworkInfo *network_info; ++ uint8 chal[8]; ++ unsigned char local_lm_response[24]; ++ unsigned char local_nt_response[24]; ++ struct netr_ChallengeResponse lm; ++ struct netr_ChallengeResponse nt; ++ ++ ZERO_STRUCT(lm); ++ ZERO_STRUCT(nt); ++ ++ network_info = talloc_zero(frame, struct netr_NetworkInfo); ++ if (network_info == NULL) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ generate_random_buffer(chal, 8); ++ ++ SMBencrypt(password, chal, local_lm_response); ++ SMBNTencrypt(password, chal, local_nt_response); ++ ++ lm.length = 24; ++ lm.data = local_lm_response; ++ ++ nt.length = 24; ++ nt.data = local_nt_response; ++ ++ network_info->identity_info.domain_name.string = domain; ++ network_info->identity_info.parameter_control = logon_parameters; ++ network_info->identity_info.logon_id_low = 0xdead; ++ network_info->identity_info.logon_id_high = 0xbeef; ++ network_info->identity_info.account_name.string = username; ++ network_info->identity_info.workstation.string = workstation_slash; ++ ++ memcpy(network_info->challenge, chal, 8); ++ network_info->nt = nt; ++ network_info->lm = lm; ++ ++ logon->network = network_info; ++ ++ break; ++ } ++ default: ++ DEBUG(0, ("switch value %d not supported\n", ++ logon_type)); ++ TALLOC_FREE(frame); ++ return NT_STATUS_INVALID_INFO_CLASS; ++ } ++ ++ status = netlogon_creds_cli_LogonSamLogon(creds, ++ binding_handle, ++ logon_type, ++ logon, ++ frame, ++ &validation_level, ++ &validation, ++ &authoritative, ++ &flags); ++ TALLOC_FREE(frame); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ return NT_STATUS_OK; ++} ++ + static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx, + uint16_t validation_level, + union netr_Validation *validation, +diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h +index 54ed7ae..d4c6670 100644 +--- a/source3/rpc_client/cli_netlogon.h ++++ b/source3/rpc_client/cli_netlogon.h +@@ -60,6 +60,14 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, + const char *workstation, + uint16_t validation_level, + int logon_type); ++NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds, ++ struct dcerpc_binding_handle *binding_handle, ++ uint32_t logon_parameters, ++ const char *domain, ++ const char *username, ++ const char *password, ++ const char *workstation, ++ enum netr_LogonInfoClass logon_type); + NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + uint32 logon_parameters, +-- +1.9.3 + + +From 10c272f991643913358efd5fefb28fc1ce307c70 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 17 Dec 2013 20:06:14 +0100 +Subject: [PATCH 181/249] s3:winbindd: call rpccli_pre_open_netlogon_creds() in + the parent + +This opens the CLEAR_IF_FIRST tdb in the long living parent. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 07126b6fb22cebce660d1d1a4f0f9fb905064aa0) +--- + source3/winbindd/winbindd.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c +index 69a17bf..a90c8fe 100644 +--- a/source3/winbindd/winbindd.c ++++ b/source3/winbindd/winbindd.c +@@ -31,6 +31,7 @@ + #include "../librpc/gen_ndr/srv_lsa.h" + #include "../librpc/gen_ndr/srv_samr.h" + #include "secrets.h" ++#include "rpc_client/cli_netlogon.h" + #include "idmap.h" + #include "lib/addrchange.h" + #include "serverid.h" +@@ -1538,6 +1539,13 @@ int main(int argc, char **argv, char **envp) + return False; + } + ++ status = rpccli_pre_open_netlogon_creds(); ++ if (!NT_STATUS_IS_OK(status)) { ++ DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n", ++ nt_errstr(status))); ++ exit(1); ++ } ++ + /* Unblock all signals we are interested in as they may have been + blocked by the parent process. */ + +-- +1.9.3 + + +From 4cb4ec2065f1f8b3598eb37ca24ce0f8fdf567aa Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 7 Aug 2013 11:32:44 +0200 +Subject: [PATCH 182/249] s3:winbindd: make use of + rpccli_{create,setup}_netlogon_creds() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 22e4e2c1d1252e434cb928d4530c378a62a64138) +--- + source3/winbindd/winbindd.h | 3 + + source3/winbindd/winbindd_cm.c | 125 ++++++++++++++++++++--------------- + source3/winbindd/winbindd_dual_srv.c | 1 + + 3 files changed, 77 insertions(+), 52 deletions(-) + +diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h +index b5fc010..8f89e27 100644 +--- a/source3/winbindd/winbindd.h ++++ b/source3/winbindd/winbindd.h +@@ -116,6 +116,9 @@ struct winbindd_cm_conn { + struct policy_handle lsa_policy; + + struct rpc_pipe_client *netlogon_pipe; ++ struct netlogon_creds_cli_context *netlogon_creds; ++ uint32_t netlogon_flags; ++ bool netlogon_force_reauth; + }; + + /* Async child */ +diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c +index 1546002..7b6cc96 100644 +--- a/source3/winbindd/winbindd_cm.c ++++ b/source3/winbindd/winbindd_cm.c +@@ -79,6 +79,7 @@ + #include "auth/gensec/gensec.h" + #include "../libcli/smb/smbXcli_base.h" + #include "lib/param/loadparm.h" ++#include "libcli/auth/netlogon_creds_cli.h" + + #undef DBGC_CLASS + #define DBGC_CLASS DBGC_WINBIND +@@ -1826,6 +1827,9 @@ void invalidate_cm_connection(struct winbindd_cm_conn *conn) + } + + conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY; ++ conn->netlogon_force_reauth = false; ++ conn->netlogon_flags = 0; ++ TALLOC_FREE(conn->netlogon_creds); + + if (conn->cli) { + cli_shutdown(conn->cli); +@@ -2292,8 +2296,18 @@ static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain, + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + struct rpc_pipe_client *netlogon_pipe; + +- if (lp_client_schannel() == False) { +- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; ++ *ppdc = NULL; ++ ++ if ((!IS_DC) && (!domain->primary)) { ++ return NT_STATUS_TRUSTED_DOMAIN_FAILURE; ++ } ++ ++ if (domain->conn.netlogon_creds != NULL) { ++ if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { ++ return NT_STATUS_TRUSTED_DOMAIN_FAILURE; ++ } ++ *ppdc = domain->conn.netlogon_creds; ++ return NT_STATUS_OK; + } + + result = cm_connect_netlogon(domain, &netlogon_pipe); +@@ -2301,14 +2315,15 @@ static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain, + return result; + } + +- /* Return a pointer to the struct netlogon_creds_CredentialState from the +- netlogon pipe. */ ++ if (domain->conn.netlogon_creds == NULL) { ++ return NT_STATUS_TRUSTED_DOMAIN_FAILURE; ++ } + +- if (!domain->conn.netlogon_pipe->netlogon_creds) { +- return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */ ++ if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { ++ return NT_STATUS_TRUSTED_DOMAIN_FAILURE; + } + +- *ppdc = domain->conn.netlogon_pipe->netlogon_creds; ++ *ppdc = domain->conn.netlogon_creds; + return NT_STATUS_OK; + } + +@@ -2747,14 +2762,16 @@ NTSTATUS cm_connect_lsat(struct winbindd_domain *domain, + NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, + struct rpc_pipe_client **cli) + { ++ struct messaging_context *msg_ctx = winbind_messaging_context(); + struct winbindd_cm_conn *conn; + NTSTATUS result; +- +- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; +- uint8_t mach_pwd[16]; + enum netr_SchannelType sec_chan_type; ++ const char *_account_name; + const char *account_name; +- struct rpc_pipe_client *netlogon_pipe = NULL; ++ struct samr_Password current_nt_hash; ++ struct samr_Password *previous_nt_hash = NULL; ++ struct netlogon_creds_CredentialState *creds = NULL; ++ bool ok; + + *cli = NULL; + +@@ -2771,60 +2788,68 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, + } + + TALLOC_FREE(conn->netlogon_pipe); +- +- result = cli_rpc_pipe_open_noauth(conn->cli, +- &ndr_table_netlogon, +- &netlogon_pipe); +- if (!NT_STATUS_IS_OK(result)) { +- return result; +- } ++ conn->netlogon_flags = 0; ++ TALLOC_FREE(conn->netlogon_creds); + + if ((!IS_DC) && (!domain->primary)) { +- /* Clear the schannel request bit and drop down */ +- neg_flags &= ~NETLOGON_NEG_SCHANNEL; + goto no_schannel; + } + +- if (lp_client_schannel() != False) { +- neg_flags |= NETLOGON_NEG_SCHANNEL; ++ ok = get_trust_pw_hash(domain->name, ++ current_nt_hash.hash, ++ &_account_name, ++ &sec_chan_type); ++ if (!ok) { ++ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + +- if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name, +- &sec_chan_type)) +- { +- TALLOC_FREE(netlogon_pipe); +- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; ++ account_name = talloc_asprintf(talloc_tos(), "%s$", _account_name); ++ if (account_name == NULL) { ++ return NT_STATUS_NO_MEMORY; + } + +- result = rpccli_netlogon_setup_creds( +- netlogon_pipe, +- domain->dcname, /* server name. */ +- domain->name, /* domain name */ +- lp_netbios_name(), /* client name */ +- account_name, /* machine account */ +- mach_pwd, /* machine password */ +- sec_chan_type, /* from get_trust_pw */ +- &neg_flags); ++ result = rpccli_create_netlogon_creds(domain->dcname, ++ domain->name, ++ account_name, ++ sec_chan_type, ++ msg_ctx, ++ domain, ++ &conn->netlogon_creds); ++ if (!NT_STATUS_IS_OK(result)) { ++ SAFE_FREE(previous_nt_hash); ++ return result; ++ } + ++ result = rpccli_setup_netlogon_creds(conn->cli, ++ conn->netlogon_creds, ++ conn->netlogon_force_reauth, ++ current_nt_hash, ++ previous_nt_hash); ++ conn->netlogon_force_reauth = false; ++ SAFE_FREE(previous_nt_hash); + if (!NT_STATUS_IS_OK(result)) { +- TALLOC_FREE(netlogon_pipe); + return result; + } + +- if ((lp_client_schannel() == True) && +- ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { +- DEBUG(3, ("Server did not offer schannel\n")); +- TALLOC_FREE(netlogon_pipe); +- return NT_STATUS_ACCESS_DENIED; ++ result = netlogon_creds_cli_get(conn->netlogon_creds, ++ talloc_tos(), ++ &creds); ++ if (!NT_STATUS_IS_OK(result)) { ++ return result; + } ++ conn->netlogon_flags = creds->negotiate_flags; ++ TALLOC_FREE(creds); + + no_schannel: +- if ((lp_client_schannel() == False) || +- ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { ++ if (!(conn->netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { ++ result = cli_rpc_pipe_open_noauth(conn->cli, ++ &ndr_table_netlogon, ++ &conn->netlogon_pipe); ++ if (!NT_STATUS_IS_OK(result)) { ++ invalidate_cm_connection(conn); ++ return result; ++ } + +- /* We're done - just keep the existing connection to NETLOGON +- * open */ +- conn->netlogon_pipe = netlogon_pipe; + *cli = conn->netlogon_pipe; + return NT_STATUS_OK; + } +@@ -2837,12 +2862,8 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, + result = cli_rpc_pipe_open_schannel_with_key( + conn->cli, &ndr_table_netlogon, NCACN_NP, + domain->name, +- netlogon_pipe->netlogon_creds, ++ conn->netlogon_creds, + &conn->netlogon_pipe); +- +- /* We can now close the initial netlogon pipe. */ +- TALLOC_FREE(netlogon_pipe); +- + if (!NT_STATUS_IS_OK(result)) { + DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error " + "was %s\n", nt_errstr(result))); +diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c +index b873655..001591a 100644 +--- a/source3/winbindd/winbindd_dual_srv.c ++++ b/source3/winbindd/winbindd_dual_srv.c +@@ -580,6 +580,7 @@ NTSTATUS _wbint_CheckMachineAccount(struct pipes_struct *p, + + again: + invalidate_cm_connection(&domain->conn); ++ domain->conn.netlogon_force_reauth = true; + + { + struct rpc_pipe_client *netlogon_pipe; +-- +1.9.3 + + +From dc77edf0b74a88950f4de2472c05a73fcc629dc1 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 27 Aug 2013 13:07:45 +0200 +Subject: [PATCH 183/249] s3:auth_domain: simplify + connect_to_domain_password_server() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit d9d55f5406949187901476d673c7d6ff0fc165c2) +--- + source3/auth/auth_domain.c | 31 ++++++++++++------------------- + 1 file changed, 12 insertions(+), 19 deletions(-) + +diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c +index 9f88c4a..ae27bf0 100644 +--- a/source3/auth/auth_domain.c ++++ b/source3/auth/auth_domain.c +@@ -47,16 +47,17 @@ static struct named_mutex *mutex; + * + **/ + +-static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, ++static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, + const char *domain, + const char *dc_name, + const struct sockaddr_storage *dc_ss, + struct rpc_pipe_client **pipe_ret) + { +- NTSTATUS result; ++ NTSTATUS result; ++ struct cli_state *cli = NULL; + struct rpc_pipe_client *netlogon_pipe = NULL; + +- *cli = NULL; ++ *cli_ret = NULL; + + *pipe_ret = NULL; + +@@ -80,7 +81,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, + } + + /* Attempt connection */ +- result = cli_full_connection(cli, lp_netbios_name(), dc_name, dc_ss, 0, ++ result = cli_full_connection(&cli, lp_netbios_name(), dc_name, dc_ss, 0, + "IPC$", "IPC", "", "", "", 0, SMB_SIGNING_DEFAULT); + + if (!NT_STATUS_IS_OK(result)) { +@@ -89,11 +90,6 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, + result = NT_STATUS_NO_LOGON_SERVERS; + } + +- if (*cli) { +- cli_shutdown(*cli); +- *cli = NULL; +- } +- + TALLOC_FREE(mutex); + return result; + } +@@ -115,18 +111,17 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, + if (lp_client_schannel()) { + /* We also setup the creds chain in the open_schannel call. */ + result = cli_rpc_pipe_open_schannel( +- *cli, &ndr_table_netlogon, NCACN_NP, ++ cli, &ndr_table_netlogon, NCACN_NP, + DCERPC_AUTH_LEVEL_PRIVACY, domain, &netlogon_pipe); + } else { + result = cli_rpc_pipe_open_noauth( +- *cli, &ndr_table_netlogon, &netlogon_pipe); ++ cli, &ndr_table_netlogon, &netlogon_pipe); + } + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \ + machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); +- cli_shutdown(*cli); +- *cli = NULL; ++ cli_shutdown(cli); + TALLOC_FREE(mutex); + return result; + } +@@ -145,8 +140,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); + DEBUG(0, ("connect_to_domain_password_server: could not fetch " + "trust account password for domain '%s'\n", + domain)); +- cli_shutdown(*cli); +- *cli = NULL; ++ cli_shutdown(cli); + TALLOC_FREE(mutex); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } +@@ -161,8 +155,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); + &neg_flags); + + if (!NT_STATUS_IS_OK(result)) { +- cli_shutdown(*cli); +- *cli = NULL; ++ cli_shutdown(cli); + TALLOC_FREE(mutex); + return result; + } +@@ -172,14 +165,14 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); + DEBUG(0, ("connect_to_domain_password_server: unable to open " + "the domain client session to machine %s. Error " + "was : %s.\n", dc_name, nt_errstr(result))); +- cli_shutdown(*cli); +- *cli = NULL; ++ cli_shutdown(cli); + TALLOC_FREE(mutex); + return NT_STATUS_NO_LOGON_SERVERS; + } + + /* We exit here with the mutex *locked*. JRA */ + ++ *cli_ret = cli; + *pipe_ret = netlogon_pipe; + + return NT_STATUS_OK; +-- +1.9.3 + + +From 8fc2ffafd545dbc4af4c1ebab5fb631da18cade4 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 27 Aug 2013 15:01:10 +0200 +Subject: [PATCH 184/249] s3:auth_domain: make use of + rpccli_{create,setup}_netlogon_creds() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 34e66780e573bebf4b971fb96e1ed8680c1488a9) +--- + source3/auth/auth_domain.c | 136 ++++++++++++++++++++++++++++----------------- + 1 file changed, 85 insertions(+), 51 deletions(-) + +diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c +index ae27bf0..bf2671c 100644 +--- a/source3/auth/auth_domain.c ++++ b/source3/auth/auth_domain.c +@@ -27,6 +27,7 @@ + #include "secrets.h" + #include "passdb.h" + #include "libsmb/libsmb.h" ++#include "libcli/auth/netlogon_creds_cli.h" + + #undef DBGC_CLASS + #define DBGC_CLASS DBGC_AUTH +@@ -53,9 +54,20 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, + const struct sockaddr_storage *dc_ss, + struct rpc_pipe_client **pipe_ret) + { ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct messaging_context *msg_ctx = server_messaging_context(); + NTSTATUS result; + struct cli_state *cli = NULL; + struct rpc_pipe_client *netlogon_pipe = NULL; ++ struct netlogon_creds_cli_context *netlogon_creds = NULL; ++ struct netlogon_creds_CredentialState *creds = NULL; ++ uint32_t netlogon_flags = 0; ++ enum netr_SchannelType sec_chan_type = 0; ++ const char *_account_name = NULL; ++ const char *account_name = NULL; ++ struct samr_Password current_nt_hash; ++ struct samr_Password *previous_nt_hash = NULL; ++ bool ok; + + *cli_ret = NULL; + +@@ -77,6 +89,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, + + mutex = grab_named_mutex(NULL, dc_name, 10); + if (mutex == NULL) { ++ TALLOC_FREE(frame); + return NT_STATUS_NO_LOGON_SERVERS; + } + +@@ -91,6 +104,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, + } + + TALLOC_FREE(mutex); ++ TALLOC_FREE(frame); + return result; + } + +@@ -98,67 +112,85 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, + * We now have an anonymous connection to IPC$ on the domain password server. + */ + +- /* +- * Even if the connect succeeds we need to setup the netlogon +- * pipe here. We do this as we may just have changed the domain +- * account password on the PDC and yet we may be talking to +- * a BDC that doesn't have this replicated yet. In this case +- * a successful connect to a DC needs to take the netlogon connect +- * into account also. This patch from "Bjart Kvarme" . +- */ ++ ok = get_trust_pw_hash(domain, ++ current_nt_hash.hash, ++ &_account_name, ++ &sec_chan_type); ++ if (!ok) { ++ cli_shutdown(cli); ++ TALLOC_FREE(mutex); ++ TALLOC_FREE(frame); ++ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; ++ } + +- /* open the netlogon pipe. */ +- if (lp_client_schannel()) { +- /* We also setup the creds chain in the open_schannel call. */ +- result = cli_rpc_pipe_open_schannel( +- cli, &ndr_table_netlogon, NCACN_NP, +- DCERPC_AUTH_LEVEL_PRIVACY, domain, &netlogon_pipe); +- } else { +- result = cli_rpc_pipe_open_noauth( +- cli, &ndr_table_netlogon, &netlogon_pipe); ++ account_name = talloc_asprintf(talloc_tos(), "%s$", _account_name); ++ if (account_name == NULL) { ++ cli_shutdown(cli); ++ TALLOC_FREE(mutex); ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; + } + ++ result = rpccli_create_netlogon_creds(dc_name, ++ domain, ++ account_name, ++ sec_chan_type, ++ msg_ctx, ++ talloc_tos(), ++ &netlogon_creds); + if (!NT_STATUS_IS_OK(result)) { +- DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \ +-machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); + cli_shutdown(cli); + TALLOC_FREE(mutex); ++ TALLOC_FREE(frame); ++ SAFE_FREE(previous_nt_hash); + return result; + } + +- if (!lp_client_schannel()) { +- /* We need to set up a creds chain on an unauthenticated netlogon pipe. */ +- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | +- NETLOGON_NEG_SUPPORTS_AES; +- enum netr_SchannelType sec_chan_type = 0; +- unsigned char machine_pwd[16]; +- const char *account_name; +- +- if (!get_trust_pw_hash(domain, machine_pwd, &account_name, +- &sec_chan_type)) +- { +- DEBUG(0, ("connect_to_domain_password_server: could not fetch " +- "trust account password for domain '%s'\n", +- domain)); +- cli_shutdown(cli); +- TALLOC_FREE(mutex); +- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; +- } ++ result = rpccli_setup_netlogon_creds(cli, ++ netlogon_creds, ++ false, /* force_reauth */ ++ current_nt_hash, ++ previous_nt_hash); ++ SAFE_FREE(previous_nt_hash); ++ if (!NT_STATUS_IS_OK(result)) { ++ cli_shutdown(cli); ++ TALLOC_FREE(mutex); ++ TALLOC_FREE(frame); ++ return result; ++ } + +- result = rpccli_netlogon_setup_creds(netlogon_pipe, +- dc_name, /* server name */ +- domain, /* domain */ +- lp_netbios_name(), /* client name */ +- account_name, /* machine account name */ +- machine_pwd, +- sec_chan_type, +- &neg_flags); +- +- if (!NT_STATUS_IS_OK(result)) { +- cli_shutdown(cli); +- TALLOC_FREE(mutex); +- return result; +- } ++ result = netlogon_creds_cli_get(netlogon_creds, ++ talloc_tos(), ++ &creds); ++ if (!NT_STATUS_IS_OK(result)) { ++ cli_shutdown(cli); ++ TALLOC_FREE(mutex); ++ TALLOC_FREE(frame); ++ return result; ++ } ++ netlogon_flags = creds->negotiate_flags; ++ TALLOC_FREE(creds); ++ ++ if (netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC) { ++ result = cli_rpc_pipe_open_schannel_with_key( ++ cli, &ndr_table_netlogon, NCACN_NP, ++ domain, netlogon_creds, &netlogon_pipe); ++ } else { ++ result = cli_rpc_pipe_open_noauth(cli, ++ &ndr_table_netlogon, ++ &netlogon_pipe); ++ } ++ ++ if (!NT_STATUS_IS_OK(result)) { ++ DEBUG(0,("connect_to_domain_password_server: " ++ "unable to open the domain client session to " ++ "machine %s. Flags[0x%08X] Error was : %s.\n", ++ dc_name, (unsigned)netlogon_flags, ++ nt_errstr(result))); ++ cli_shutdown(cli); ++ TALLOC_FREE(mutex); ++ TALLOC_FREE(frame); ++ return result; + } + + if(!netlogon_pipe) { +@@ -167,6 +199,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); + "was : %s.\n", dc_name, nt_errstr(result))); + cli_shutdown(cli); + TALLOC_FREE(mutex); ++ TALLOC_FREE(frame); + return NT_STATUS_NO_LOGON_SERVERS; + } + +@@ -175,6 +208,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); + *cli_ret = cli; + *pipe_ret = netlogon_pipe; + ++ TALLOC_FREE(frame); + return NT_STATUS_OK; + } + +-- +1.9.3 + + +From 5cc57e577bc7d144176ffe6f21ed24a95661a861 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 27 Aug 2013 15:02:26 +0200 +Subject: [PATCH 185/249] s3:auth_domain: make use of + rpccli_netlogon_network_logon() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 531bbf3aff3fb08aaf112b21038f20544db60b69) +--- + source3/auth/auth_domain.c | 36 ++++++++++++++++++++++-------------- + 1 file changed, 22 insertions(+), 14 deletions(-) + +diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c +index bf2671c..937841c 100644 +--- a/source3/auth/auth_domain.c ++++ b/source3/auth/auth_domain.c +@@ -52,7 +52,8 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, + const char *domain, + const char *dc_name, + const struct sockaddr_storage *dc_ss, +- struct rpc_pipe_client **pipe_ret) ++ struct rpc_pipe_client **pipe_ret, ++ struct netlogon_creds_cli_context **creds_ret) + { + TALLOC_CTX *frame = talloc_stackframe(); + struct messaging_context *msg_ctx = server_messaging_context(); +@@ -72,6 +73,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, + *cli_ret = NULL; + + *pipe_ret = NULL; ++ *creds_ret = NULL; + + /* TODO: Send a SAMLOGON request to determine whether this is a valid + logonserver. We can avoid a 30-second timeout if the DC is down +@@ -207,6 +209,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, + + *cli_ret = cli; + *pipe_ret = netlogon_pipe; ++ *creds_ret = netlogon_creds; + + TALLOC_FREE(frame); + return NT_STATUS_OK; +@@ -230,8 +233,11 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, + struct netr_SamInfo3 *info3 = NULL; + struct cli_state *cli = NULL; + struct rpc_pipe_client *netlogon_pipe = NULL; ++ struct netlogon_creds_cli_context *netlogon_creds = NULL; + NTSTATUS nt_status = NT_STATUS_NO_LOGON_SERVERS; + int i; ++ uint8_t authoritative = 0; ++ uint32_t flags = 0; + + /* + * At this point, smb_apasswd points to the lanman response to +@@ -248,7 +254,8 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, + domain, + dc_name, + dc_ss, +- &netlogon_pipe); ++ &netlogon_pipe, ++ &netlogon_creds); + } + + if ( !NT_STATUS_IS_OK(nt_status) ) { +@@ -268,18 +275,19 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, + * in the info3 structure. + */ + +- nt_status = rpccli_netlogon_sam_network_logon(netlogon_pipe, +- mem_ctx, +- user_info->logon_parameters, /* flags such as 'allow workstation logon' */ +- dc_name, /* server name */ +- user_info->client.account_name, /* user name logging on. */ +- user_info->client.domain_name, /* domain name */ +- user_info->workstation_name, /* workstation name */ +- chal, /* 8 byte challenge. */ +- 3, /* validation level */ +- user_info->password.response.lanman, /* lanman 24 byte response */ +- user_info->password.response.nt, /* nt 24 byte response */ +- &info3); /* info3 out */ ++ nt_status = rpccli_netlogon_network_logon(netlogon_creds, ++ netlogon_pipe->binding_handle, ++ mem_ctx, ++ user_info->logon_parameters, /* flags such as 'allow workstation logon' */ ++ user_info->client.account_name, /* user name logging on. */ ++ user_info->client.domain_name, /* domain name */ ++ user_info->workstation_name, /* workstation name */ ++ chal, /* 8 byte challenge. */ ++ user_info->password.response.lanman, /* lanman 24 byte response */ ++ user_info->password.response.nt, /* nt 24 byte response */ ++ &authoritative, ++ &flags, ++ &info3); /* info3 out */ + + /* Let go as soon as possible so we avoid any potential deadlocks + with winbind lookup up users or groups. */ +-- +1.9.3 + + +From 5da4eca4d30b3894426a4f7cb0512ae61c097cbc Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 2 Sep 2013 19:32:23 +0200 +Subject: [PATCH 186/249] s3:libnet_join: make use of + rpccli_{create,setup}_netlogon_creds() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 963800539cea7487fc6258f8ac8f7cacc3426b83) +--- + source3/libnet/libnet_join.c | 110 +++++++++++++++++++++++++++++++------------ + source3/libnet/libnet_join.h | 5 +- + source3/utils/net_rpc.c | 4 +- + 3 files changed, 86 insertions(+), 33 deletions(-) + +diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c +index b2805ee..6e653c3 100644 +--- a/source3/libnet/libnet_join.c ++++ b/source3/libnet/libnet_join.c +@@ -40,6 +40,8 @@ + #include "libsmb/libsmb.h" + #include "../libcli/smb/smbXcli_base.h" + #include "lib/param/loadparm.h" ++#include "libcli/auth/netlogon_creds_cli.h" ++#include "auth/credentials/credentials.h" + + /**************************************************************** + ****************************************************************/ +@@ -1189,38 +1191,52 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx, + /**************************************************************** + ****************************************************************/ + +-NTSTATUS libnet_join_ok(const char *netbios_domain_name, +- const char *machine_name, ++NTSTATUS libnet_join_ok(struct messaging_context *msg_ctx, ++ const char *netbios_domain_name, + const char *dc_name, + const bool use_kerberos) + { +- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | +- NETLOGON_NEG_SUPPORTS_AES; ++ TALLOC_CTX *frame = talloc_stackframe(); + struct cli_state *cli = NULL; +- struct rpc_pipe_client *pipe_hnd = NULL; + struct rpc_pipe_client *netlogon_pipe = NULL; ++ struct netlogon_creds_cli_context *netlogon_creds = NULL; ++ struct netlogon_creds_CredentialState *creds = NULL; ++ uint32_t netlogon_flags = 0; ++ enum netr_SchannelType sec_chan_type = 0; + NTSTATUS status; + char *machine_password = NULL; +- char *machine_account = NULL; ++ const char *machine_name = NULL; ++ const char *machine_account = NULL; + int flags = 0; ++ struct samr_Password current_nt_hash; ++ struct samr_Password *previous_nt_hash = NULL; ++ bool ok; + + if (!dc_name) { ++ TALLOC_FREE(frame); + return NT_STATUS_INVALID_PARAMETER; + } + + if (!secrets_init()) { ++ TALLOC_FREE(frame); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + +- machine_password = secrets_fetch_machine_password(netbios_domain_name, +- NULL, NULL); +- if (!machine_password) { +- return NT_STATUS_NO_TRUST_LSA_SECRET; ++ ok = get_trust_pw_clear(netbios_domain_name, ++ &machine_password, ++ &machine_name, ++ &sec_chan_type); ++ if (!ok) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + +- if (asprintf(&machine_account, "%s$", machine_name) == -1) { ++ machine_account = talloc_asprintf(frame, "%s$", machine_name); ++ if (machine_account == NULL) { + SAFE_FREE(machine_password); +- return NT_STATUS_NO_MEMORY; ++ SAFE_FREE(previous_nt_hash); ++ TALLOC_FREE(frame); ++ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + if (use_kerberos) { +@@ -1232,12 +1248,13 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, + NULL, 0, + "IPC$", "IPC", + machine_account, +- NULL, ++ netbios_domain_name, + machine_password, + flags, + SMB_SIGNING_DEFAULT); +- free(machine_account); +- free(machine_password); ++ ++ E_md4hash(machine_password, current_nt_hash.hash); ++ SAFE_FREE(machine_password); + + if (!NT_STATUS_IS_OK(status)) { + status = cli_full_connection(&cli, NULL, +@@ -1252,36 +1269,65 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, + } + + if (!NT_STATUS_IS_OK(status)) { ++ SAFE_FREE(previous_nt_hash); ++ TALLOC_FREE(frame); + return status; + } + +- status = get_schannel_session_key(cli, netbios_domain_name, +- &neg_flags, &netlogon_pipe); ++ status = rpccli_create_netlogon_creds(dc_name, ++ netbios_domain_name, ++ machine_account, ++ sec_chan_type, ++ msg_ctx, ++ frame, ++ &netlogon_creds); + if (!NT_STATUS_IS_OK(status)) { +- if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_NETWORK_RESPONSE)) { +- cli_shutdown(cli); +- return NT_STATUS_OK; +- } ++ SAFE_FREE(previous_nt_hash); ++ cli_shutdown(cli); ++ TALLOC_FREE(frame); ++ return status; ++ } + +- DEBUG(0,("libnet_join_ok: failed to get schannel session " +- "key from server %s for domain %s. Error was %s\n", +- smbXcli_conn_remote_name(cli->conn), +- netbios_domain_name, nt_errstr(status))); ++ status = rpccli_setup_netlogon_creds(cli, ++ netlogon_creds, ++ true, /* force_reauth */ ++ current_nt_hash, ++ previous_nt_hash); ++ SAFE_FREE(previous_nt_hash); ++ if (!NT_STATUS_IS_OK(status)) { ++ DEBUG(0,("connect_to_domain_password_server: " ++ "unable to open the domain client session to " ++ "machine %s. Flags[0x%08X] Error was : %s.\n", ++ dc_name, (unsigned)netlogon_flags, ++ nt_errstr(status))); ++ cli_shutdown(cli); ++ TALLOC_FREE(frame); ++ return status; ++ } ++ ++ status = netlogon_creds_cli_get(netlogon_creds, ++ talloc_tos(), ++ &creds); ++ if (!NT_STATUS_IS_OK(status)) { + cli_shutdown(cli); ++ TALLOC_FREE(frame); + return status; + } ++ netlogon_flags = creds->negotiate_flags; ++ TALLOC_FREE(creds); + +- if (!lp_client_schannel()) { ++ if (!(netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { + cli_shutdown(cli); ++ TALLOC_FREE(frame); + return NT_STATUS_OK; + } + + status = cli_rpc_pipe_open_schannel_with_key( + cli, &ndr_table_netlogon, NCACN_NP, + netbios_domain_name, +- netlogon_pipe->netlogon_creds, &pipe_hnd); ++ netlogon_creds, &netlogon_pipe); + +- cli_shutdown(cli); ++ TALLOC_FREE(netlogon_pipe); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("libnet_join_ok: failed to open schannel session " +@@ -1289,9 +1335,13 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, + "Error was %s\n", + smbXcli_conn_remote_name(cli->conn), + netbios_domain_name, nt_errstr(status))); ++ cli_shutdown(cli); ++ TALLOC_FREE(frame); + return status; + } + ++ cli_shutdown(cli); ++ TALLOC_FREE(frame); + return NT_STATUS_OK; + } + +@@ -1303,8 +1353,8 @@ static WERROR libnet_join_post_verify(TALLOC_CTX *mem_ctx, + { + NTSTATUS status; + +- status = libnet_join_ok(r->out.netbios_domain_name, +- r->in.machine_name, ++ status = libnet_join_ok(r->in.msg_ctx, ++ r->out.netbios_domain_name, + r->in.dc_name, + r->in.use_kerberos); + if (!NT_STATUS_IS_OK(status)) { +diff --git a/source3/libnet/libnet_join.h b/source3/libnet/libnet_join.h +index 58c33b2..b7e2f0b 100644 +--- a/source3/libnet/libnet_join.h ++++ b/source3/libnet/libnet_join.h +@@ -23,8 +23,9 @@ + + /* The following definitions come from libnet/libnet_join.c */ + +-NTSTATUS libnet_join_ok(const char *netbios_domain_name, +- const char *machine_name, ++struct messaging_context; ++NTSTATUS libnet_join_ok(struct messaging_context *msg_ctx, ++ const char *netbios_domain_name, + const char *dc_name, + const bool use_kerberos); + WERROR libnet_init_JoinCtx(TALLOC_CTX *mem_ctx, +diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c +index dff8801..9de74c0 100644 +--- a/source3/utils/net_rpc.c ++++ b/source3/utils/net_rpc.c +@@ -493,7 +493,9 @@ int net_rpc_testjoin(struct net_context *c, int argc, const char **argv) + } + + /* Display success or failure */ +- status = libnet_join_ok(c->opt_workgroup, lp_netbios_name(), dc, ++ status = libnet_join_ok(c->msg_ctx, ++ c->opt_workgroup, ++ dc, + c->opt_kerberos); + if (!NT_STATUS_IS_OK(status)) { + fprintf(stderr,"Join to domain '%s' is not valid: %s\n", +-- +1.9.3 + + +From 0da8c0a71d08de50b614e5df69a61e00d0a9cd99 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 5 Sep 2013 20:57:02 +0200 +Subject: [PATCH 187/249] s3:libnet: use rpccli_{create,setup}_netlogon_creds() + in libnet_join_joindomain_rpc_unsecure + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 3a89eee03a95d4b142bf0830f40debc75bfa2e26) +--- + source3/libnet/libnet_join.c | 66 ++++++++++++++++++++++++++++++++++---------- + 1 file changed, 51 insertions(+), 15 deletions(-) + +diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c +index 6e653c3..a87eb38 100644 +--- a/source3/libnet/libnet_join.c ++++ b/source3/libnet/libnet_join.c +@@ -817,14 +817,17 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, + struct libnet_JoinCtx *r, + struct cli_state *cli) + { +- struct rpc_pipe_client *pipe_hnd = NULL; +- unsigned char orig_trust_passwd_hash[16]; +- unsigned char new_trust_passwd_hash[16]; ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct rpc_pipe_client *netlogon_pipe = NULL; ++ struct netlogon_creds_cli_context *netlogon_creds = NULL; ++ struct samr_Password current_nt_hash; ++ const char *account_name = NULL; + NTSTATUS status; + + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, +- &pipe_hnd); ++ &netlogon_pipe); + if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); + return status; + } + +@@ -832,22 +835,55 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, + r->in.machine_password = generate_random_password(mem_ctx, + DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH, + DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); +- NT_STATUS_HAVE_NO_MEMORY(r->in.machine_password); ++ if (r->in.machine_password == NULL) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } + } + +- E_md4hash(r->in.machine_password, new_trust_passwd_hash); +- + /* according to WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED */ +- E_md4hash(r->in.admin_password, orig_trust_passwd_hash); ++ E_md4hash(r->in.admin_password, current_nt_hash.hash); + +- status = rpccli_netlogon_set_trust_password(pipe_hnd, mem_ctx, +- r->in.machine_name, +- orig_trust_passwd_hash, +- r->in.machine_password, +- new_trust_passwd_hash, +- r->in.secure_channel_type); ++ account_name = talloc_asprintf(frame, "%s$", ++ r->in.machine_name); ++ if (account_name == NULL) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } + +- return status; ++ status = rpccli_create_netlogon_creds(netlogon_pipe->desthost, ++ r->in.domain_name, ++ account_name, ++ r->in.secure_channel_type, ++ r->in.msg_ctx, ++ frame, ++ &netlogon_creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); ++ return status; ++ } ++ ++ status = rpccli_setup_netlogon_creds(cli, ++ netlogon_creds, ++ true, /* force_reauth */ ++ current_nt_hash, ++ NULL); /* previous_nt_hash */ ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); ++ return status; ++ } ++ ++ status = netlogon_creds_cli_ServerPasswordSet(netlogon_creds, ++ netlogon_pipe->binding_handle, ++ r->in.machine_password, ++ NULL); /* new_version */ ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); ++ return status; ++ } ++ ++ TALLOC_FREE(frame); ++ return NT_STATUS_OK; + } + + /**************************************************************** +-- +1.9.3 + + +From 9d192bc1d2dd06efada55792203aaed58b349ab9 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 11 Sep 2013 10:06:41 +0200 +Subject: [PATCH 188/249] s3:rpc_client: use + rpccli_{create,setup}_netlogon_creds() in cli_rpc_pipe_open_schannel() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 94caf7e190563423914b653d0c2fc4a4abf1f899) +--- + source3/rpc_client/cli_pipe.h | 7 -- + source3/rpc_client/cli_pipe_schannel.c | 162 ++++++++++++++------------------- + 2 files changed, 66 insertions(+), 103 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h +index c21c55d..2a76130 100644 +--- a/source3/rpc_client/cli_pipe.h ++++ b/source3/rpc_client/cli_pipe.h +@@ -109,13 +109,6 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, + struct rpc_pipe_client *cli, + DATA_BLOB *session_key); + +-/* The following definitions come from rpc_client/cli_pipe_schannel.c */ +- +-NTSTATUS get_schannel_session_key(struct cli_state *cli, +- const char *domain, +- uint32 *pneg_flags, +- struct rpc_pipe_client **presult); +- + #endif /* _CLI_PIPE_H */ + + /* vim: set ts=8 sw=8 noet cindent ft=c.doxygen: */ +diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c +index 8f9161f..1fcf62e 100644 +--- a/source3/rpc_client/cli_pipe_schannel.c ++++ b/source3/rpc_client/cli_pipe_schannel.c +@@ -23,67 +23,15 @@ + #include "../libcli/auth/schannel.h" + #include "rpc_client/cli_netlogon.h" + #include "rpc_client/cli_pipe.h" +-#include "librpc/gen_ndr/ndr_dcerpc.h" + #include "librpc/rpc/dcerpc.h" + #include "passdb.h" + #include "libsmb/libsmb.h" +-#include "auth/gensec/gensec.h" + #include "../libcli/smb/smbXcli_base.h" ++#include "libcli/auth/netlogon_creds_cli.h" + + #undef DBGC_CLASS + #define DBGC_CLASS DBGC_RPC_CLI + +- +-/**************************************************************************** +- Get a the schannel session key out of an already opened netlogon pipe. +- ****************************************************************************/ +-static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe, +- struct cli_state *cli, +- const char *domain, +- uint32 *pneg_flags) +-{ +- enum netr_SchannelType sec_chan_type = 0; +- unsigned char machine_pwd[16]; +- const char *machine_account; +- NTSTATUS status; +- +- /* Get the machine account credentials from secrets.tdb. */ +- if (!get_trust_pw_hash(domain, machine_pwd, &machine_account, +- &sec_chan_type)) +- { +- DEBUG(0, ("get_schannel_session_key: could not fetch " +- "trust account password for domain '%s'\n", +- domain)); +- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; +- } +- +- status = rpccli_netlogon_setup_creds(netlogon_pipe, +- smbXcli_conn_remote_name(cli->conn), /* server name */ +- domain, /* domain */ +- lp_netbios_name(), /* client name */ +- machine_account, /* machine account name */ +- machine_pwd, +- sec_chan_type, +- pneg_flags); +- +- if (!NT_STATUS_IS_OK(status)) { +- DEBUG(3, ("get_schannel_session_key_common: " +- "rpccli_netlogon_setup_creds failed with result %s " +- "to server %s, domain %s, machine account %s.\n", +- nt_errstr(status), smbXcli_conn_remote_name(cli->conn), domain, +- machine_account )); +- return status; +- } +- +- if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) { +- DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n", +- smbXcli_conn_remote_name(cli->conn))); +- return NT_STATUS_INVALID_NETWORK_RESPONSE; +- } +- +- return NT_STATUS_OK; +-} +- + /**************************************************************************** + Open a named pipe to an SMB server and bind using schannel (bind type 68). + Fetch the session key ourselves using a temporary netlogon pipe. +@@ -96,63 +44,85 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, + const char *domain, + struct rpc_pipe_client **presult) + { +- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | +- NETLOGON_NEG_SUPPORTS_AES; +- struct rpc_pipe_client *netlogon_pipe = NULL; ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct messaging_context *msg_ctx = NULL; ++ const char *dc_name = smbXcli_conn_remote_name(cli->conn); + struct rpc_pipe_client *result = NULL; + NTSTATUS status; ++ struct netlogon_creds_cli_context *netlogon_creds = NULL; ++ struct netlogon_creds_CredentialState *creds = NULL; ++ uint32_t netlogon_flags = 0; ++ enum netr_SchannelType sec_chan_type = 0; ++ const char *_account_name = NULL; ++ const char *account_name = NULL; ++ struct samr_Password current_nt_hash; ++ struct samr_Password *previous_nt_hash = NULL; ++ bool ok; ++ ++ ok = get_trust_pw_hash(domain, ++ current_nt_hash.hash, ++ &_account_name, ++ &sec_chan_type); ++ if (!ok) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; ++ } ++ ++ account_name = talloc_asprintf(frame, "%s$", _account_name); ++ if (account_name == NULL) { ++ SAFE_FREE(previous_nt_hash); ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ status = rpccli_create_netlogon_creds(dc_name, ++ domain, ++ account_name, ++ sec_chan_type, ++ msg_ctx, ++ frame, ++ &netlogon_creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ SAFE_FREE(previous_nt_hash); ++ TALLOC_FREE(frame); ++ return status; ++ } + +- status = get_schannel_session_key(cli, domain, &neg_flags, +- &netlogon_pipe); ++ status = rpccli_setup_netlogon_creds(cli, ++ netlogon_creds, ++ false, /* force_reauth */ ++ current_nt_hash, ++ previous_nt_hash); ++ SAFE_FREE(previous_nt_hash); + if (!NT_STATUS_IS_OK(status)) { +- DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session " +- "key from server %s for domain %s.\n", +- smbXcli_conn_remote_name(cli->conn), domain )); ++ TALLOC_FREE(frame); + return status; + } + ++ status = netlogon_creds_cli_get(netlogon_creds, ++ frame, ++ &creds); ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); ++ return status; ++ } ++ netlogon_flags = creds->negotiate_flags; ++ TALLOC_FREE(creds); ++ ++ if (!(netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_DOWNGRADE_DETECTED; ++ } ++ + status = cli_rpc_pipe_open_schannel_with_key( + cli, table, transport, domain, +- netlogon_pipe->netlogon_creds, ++ netlogon_creds, + &result); + +- /* Now we've bound using the session key we can close the netlog pipe. */ +- TALLOC_FREE(netlogon_pipe); +- + if (NT_STATUS_IS_OK(status)) { + *presult = result; + } + ++ TALLOC_FREE(frame); + return status; + } +- +-/**************************************************************************** +- Open a netlogon pipe and get the schannel session key. +- Now exposed to external callers. +- ****************************************************************************/ +- +- +-NTSTATUS get_schannel_session_key(struct cli_state *cli, +- const char *domain, +- uint32 *pneg_flags, +- struct rpc_pipe_client **presult) +-{ +- struct rpc_pipe_client *netlogon_pipe = NULL; +- NTSTATUS status; +- +- status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, +- &netlogon_pipe); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- +- status = get_schannel_session_key_common(netlogon_pipe, cli, domain, +- pneg_flags); +- if (!NT_STATUS_IS_OK(status)) { +- TALLOC_FREE(netlogon_pipe); +- return status; +- } +- +- *presult = netlogon_pipe; +- return NT_STATUS_OK; +-} +-- +1.9.3 + + +From 5fba6641f79a14c208c5947886c005a87b9f3256 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 18:24:44 +0200 +Subject: [PATCH 189/249] s3:rpcclient: add rpcclient_msg_ctx + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit a1c468e1d75d490f0e531feb08188ddc3f0d77b5) +--- + source3/rpcclient/rpcclient.c | 5 +++++ + source3/rpcclient/rpcclient.h | 2 ++ + 2 files changed, 7 insertions(+) + +diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c +index 0cbec20..39bf613 100644 +--- a/source3/rpcclient/rpcclient.c ++++ b/source3/rpcclient/rpcclient.c +@@ -33,6 +33,7 @@ + #include "libsmb/libsmb.h" + #include "auth/gensec/gensec.h" + #include "../libcli/smb/smbXcli_base.h" ++#include "messages.h" + + enum pipe_auth_type_spnego { + PIPE_AUTH_TYPE_SPNEGO_NONE = 0, +@@ -48,6 +49,7 @@ static enum dcerpc_AuthLevel pipe_default_auth_level = DCERPC_AUTH_LEVEL_NONE; + static unsigned int timeout = 0; + static enum dcerpc_transport_t default_transport = NCACN_NP; + ++struct messaging_context *rpcclient_msg_ctx; + struct user_auth_info *rpcclient_auth_info; + + /* List to hold groups of commands. +@@ -985,6 +987,9 @@ out_free: + /* We must load interfaces after we load the smb.conf */ + load_interfaces(); + ++ rpcclient_msg_ctx = messaging_init(talloc_autofree_context(), ++ samba_tevent_context_init(talloc_autofree_context())); ++ + /* + * Get password + * from stdin if necessary +diff --git a/source3/rpcclient/rpcclient.h b/source3/rpcclient/rpcclient.h +index 762c54a..219da2a 100644 +--- a/source3/rpcclient/rpcclient.h ++++ b/source3/rpcclient/rpcclient.h +@@ -41,4 +41,6 @@ struct cmd_set { + const char *usage; + }; + ++extern struct messaging_context *rpcclient_msg_ctx; ++ + #endif /* RPCCLIENT_H */ +-- +1.9.3 + + +From c6e02d60ef12431cd1a5615fcf514548e86d6dc8 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 18:29:30 +0200 +Subject: [PATCH 190/249] s3:rpcclient: add rpcclient_netlogon_creds + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 1696b127c61fea76fce3d992632a822ed78de07c) +--- + source3/rpcclient/rpcclient.c | 3 +++ + source3/rpcclient/rpcclient.h | 1 + + 2 files changed, 4 insertions(+) + +diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c +index 39bf613..a875ff5 100644 +--- a/source3/rpcclient/rpcclient.c ++++ b/source3/rpcclient/rpcclient.c +@@ -51,6 +51,7 @@ static enum dcerpc_transport_t default_transport = NCACN_NP; + + struct messaging_context *rpcclient_msg_ctx; + struct user_auth_info *rpcclient_auth_info; ++struct netlogon_creds_cli_context *rpcclient_netlogon_creds; + + /* List to hold groups of commands. + * +@@ -797,6 +798,8 @@ static NTSTATUS do_cmd(struct cli_state *cli, + } + } + ++ rpcclient_netlogon_creds = cmd_entry->rpc_pipe->netlogon_creds; ++ + /* Run command */ + + if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) { +diff --git a/source3/rpcclient/rpcclient.h b/source3/rpcclient/rpcclient.h +index 219da2a..9288249 100644 +--- a/source3/rpcclient/rpcclient.h ++++ b/source3/rpcclient/rpcclient.h +@@ -42,5 +42,6 @@ struct cmd_set { + }; + + extern struct messaging_context *rpcclient_msg_ctx; ++extern struct netlogon_creds_cli_context *rpcclient_netlogon_creds; + + #endif /* RPCCLIENT_H */ +-- +1.9.3 + + +From 849cb578d3aa38e7d6508353914d39501cd6b2c8 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 18:57:09 +0200 +Subject: [PATCH 191/249] s3:rpcclient: remove unused + rpccli_netlogon_setup_creds() from cmd_netlogon_database_redo() + +rpccli_netlogon_setup_creds() is already called in the main do_cmd() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit fb13b002d599049f229d2014e1b94f82952b7150) +--- + source3/rpcclient/cmd_netlogon.c | 21 +-------------------- + 1 file changed, 1 insertion(+), 20 deletions(-) + +diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c +index 2e0b5e5..8a865a9 100644 +--- a/source3/rpcclient/cmd_netlogon.c ++++ b/source3/rpcclient/cmd_netlogon.c +@@ -1141,12 +1141,8 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + NTSTATUS result; + const char *server_name = cli->desthost; +- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | +- NETLOGON_NEG_SUPPORTS_AES; + struct netr_Authenticator clnt_creds, srv_cred; + struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; +- unsigned char trust_passwd_hash[16]; +- enum netr_SchannelType sec_channel_type = 0; + struct netr_ChangeLogEntry e; + uint32_t rid = 500; + struct dcerpc_binding_handle *b = cli->binding_handle; +@@ -1161,25 +1157,10 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, + sscanf(argv[1], "%d", &rid); + } + +- if (!secrets_fetch_trust_account_password(lp_workgroup(), +- trust_passwd_hash, +- NULL, &sec_channel_type)) { ++ if (cli->netlogon_creds == NULL) { + return NT_STATUS_UNSUCCESSFUL; + } + +- status = rpccli_netlogon_setup_creds(cli, +- server_name, /* server name */ +- lp_workgroup(), /* domain */ +- lp_netbios_name(), /* client name */ +- lp_netbios_name(), /* machine account name */ +- trust_passwd_hash, +- sec_channel_type, +- &neg_flags); +- +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- + status = netlogon_creds_cli_lock(cli->netlogon_creds, + mem_ctx, &creds); + if (!NT_STATUS_IS_OK(status)) { +-- +1.9.3 + + +From df5ce2ceb4c41e2a952cd9f011626028f8d230ff Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 19:00:22 +0200 +Subject: [PATCH 192/249] s3:rpcclient: make use of rpcclient_netlogon_creds + instead of cli->netlogon_creds + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 3bf77812e80b50f254af64e4935301719f78987e) +--- + source3/rpcclient/cmd_netlogon.c | 22 +++++++++++++++++----- + 1 file changed, 17 insertions(+), 5 deletions(-) + +diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c +index 8a865a9..59e1e4e 100644 +--- a/source3/rpcclient/cmd_netlogon.c ++++ b/source3/rpcclient/cmd_netlogon.c +@@ -633,7 +633,11 @@ static NTSTATUS cmd_netlogon_sam_sync(struct rpc_pipe_client *cli, + struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; + struct netlogon_creds_CredentialState *creds = NULL; + +- status = netlogon_creds_cli_lock(cli->netlogon_creds, ++ if (rpcclient_netlogon_creds == NULL) { ++ return NT_STATUS_UNSUCCESSFUL; ++ } ++ ++ status = netlogon_creds_cli_lock(rpcclient_netlogon_creds, + mem_ctx, &creds); + if (!NT_STATUS_IS_OK(status)) { + return status; +@@ -712,7 +716,11 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli, + struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; + struct netlogon_creds_CredentialState *creds = NULL; + +- status = netlogon_creds_cli_lock(cli->netlogon_creds, ++ if (rpcclient_netlogon_creds == NULL) { ++ return NT_STATUS_UNSUCCESSFUL; ++ } ++ ++ status = netlogon_creds_cli_lock(rpcclient_netlogon_creds, + mem_ctx, &creds); + if (!NT_STATUS_IS_OK(status)) { + return status; +@@ -1157,11 +1165,11 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, + sscanf(argv[1], "%d", &rid); + } + +- if (cli->netlogon_creds == NULL) { ++ if (rpcclient_netlogon_creds == NULL) { + return NT_STATUS_UNSUCCESSFUL; + } + +- status = netlogon_creds_cli_lock(cli->netlogon_creds, ++ status = netlogon_creds_cli_lock(rpcclient_netlogon_creds, + mem_ctx, &creds); + if (!NT_STATUS_IS_OK(status)) { + return status; +@@ -1223,7 +1231,11 @@ static NTSTATUS cmd_netlogon_capabilities(struct rpc_pipe_client *cli, + + ZERO_STRUCT(return_authenticator); + +- status = netlogon_creds_cli_lock(cli->netlogon_creds, ++ if (rpcclient_netlogon_creds == NULL) { ++ return NT_STATUS_UNSUCCESSFUL; ++ } ++ ++ status = netlogon_creds_cli_lock(rpcclient_netlogon_creds, + mem_ctx, &creds); + if (!NT_STATUS_IS_OK(status)) { + return status; +-- +1.9.3 + + +From 4e9d9abc0bae5ca08c3a91cc5d1b2bacffc6cbfc Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 19:59:11 +0200 +Subject: [PATCH 193/249] s3:net_rpc: add net_context->netlogon_creds + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit d1340c20b0900f54e2c73c4a363f45988b1ba097) +--- + source3/utils/net.h | 1 + + source3/utils/net_rpc.c | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/source3/utils/net.h b/source3/utils/net.h +index e97734a..ce19c57 100644 +--- a/source3/utils/net.h ++++ b/source3/utils/net.h +@@ -90,6 +90,7 @@ struct net_context { + bool smb_encrypt; + struct libnetapi_ctx *netapi_ctx; + struct messaging_context *msg_ctx; ++ struct netlogon_creds_cli_context *netlogon_creds; + + bool display_usage; + void *private_data; +diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c +index 9de74c0..3bf3f30 100644 +--- a/source3/utils/net_rpc.c ++++ b/source3/utils/net_rpc.c +@@ -201,6 +201,7 @@ int run_rpc_command(struct net_context *c, + nt_errstr(nt_status) )); + goto fail; + } ++ c->netlogon_creds = pipe_hnd->netlogon_creds; + } else { + if (conn_flags & NET_FLAGS_SEAL) { + nt_status = cli_rpc_pipe_open_generic_auth( +-- +1.9.3 + + +From 7a4535c1e61de498230abd1f99bfe875ae59c2e0 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sun, 15 Sep 2013 13:19:52 +0200 +Subject: [PATCH 194/249] s3:libsmb: add trust_pw_change() + +This protects the password change using a domain specific g_lock, +so multiple parts 'net rpc', 'rpcclient', 'winbindd', 'wbinfo --change-secret' +even on multiple cluster nodes doesn't race anymore. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 16c6e4992fa882207eeaff0a1c4d9fe217be48b7) +--- + source3/include/proto.h | 8 ++ + source3/libsmb/trusts_util.c | 179 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 187 insertions(+) + +diff --git a/source3/include/proto.h b/source3/include/proto.h +index 216a377..edda119 100644 +--- a/source3/include/proto.h ++++ b/source3/include/proto.h +@@ -984,6 +984,14 @@ void update_trustdom_cache( void ); + NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *domain) ; ++struct netlogon_creds_cli_context; ++struct messaging_context; ++struct dcerpc_binding_handle; ++NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, ++ struct messaging_context *msg_ctx, ++ struct dcerpc_binding_handle *b, ++ const char *domain, ++ bool force); + + /* The following definitions come from param/loadparm.c */ + +diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c +index 52fb481..b1bc006 100644 +--- a/source3/libsmb/trusts_util.c ++++ b/source3/libsmb/trusts_util.c +@@ -20,12 +20,15 @@ + + #include "includes.h" + #include "../libcli/auth/libcli_auth.h" ++#include "../libcli/auth/netlogon_creds_cli.h" + #include "rpc_client/cli_netlogon.h" + #include "rpc_client/cli_pipe.h" + #include "../librpc/gen_ndr/ndr_netlogon.h" + #include "secrets.h" + #include "passdb.h" + #include "libsmb/libsmb.h" ++#include "source3/include/messages.h" ++#include "source3/include/g_lock.h" + + /********************************************************* + Change the domain password on the PDC. +@@ -113,3 +116,179 @@ NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, + + return nt_status; + } ++ ++struct trust_pw_change_state { ++ struct g_lock_ctx *g_ctx; ++ char *g_lock_key; ++}; ++ ++static int trust_pw_change_state_destructor(struct trust_pw_change_state *state) ++{ ++ g_lock_unlock(state->g_ctx, state->g_lock_key); ++ return 0; ++} ++ ++NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, ++ struct messaging_context *msg_ctx, ++ struct dcerpc_binding_handle *b, ++ const char *domain, ++ bool force) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct trust_pw_change_state *state; ++ struct samr_Password current_nt_hash; ++ const struct samr_Password *previous_nt_hash = NULL; ++ enum netr_SchannelType sec_channel_type = SEC_CHAN_NULL; ++ const char *account_name; ++ char *new_trust_passwd; ++ char *pwd; ++ struct dom_sid sid; ++ time_t pass_last_set_time; ++ struct timeval g_timeout = { 0, }; ++ int timeout = 0; ++ struct timeval tv = { 0, }; ++ NTSTATUS status; ++ ++ state = talloc_zero(frame, struct trust_pw_change_state); ++ if (state == NULL) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ state->g_ctx = g_lock_ctx_init(state, msg_ctx); ++ if (state->g_ctx == NULL) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ state->g_lock_key = talloc_asprintf(state, ++ "trust_password_change_%s", ++ domain); ++ if (state->g_lock_key == NULL) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ g_timeout = timeval_current_ofs(10, 0); ++ status = g_lock_lock(state->g_ctx, ++ state->g_lock_key, ++ G_LOCK_WRITE, g_timeout); ++ if (!NT_STATUS_IS_OK(status)) { ++ DEBUG(1, ("could not get g_lock on [%s]!\n", ++ state->g_lock_key)); ++ TALLOC_FREE(frame); ++ return status; ++ } ++ ++ talloc_set_destructor(state, trust_pw_change_state_destructor); ++ ++ if (!get_trust_pw_hash(domain, current_nt_hash.hash, ++ &account_name, ++ &sec_channel_type)) { ++ DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain)); ++ TALLOC_FREE(frame); ++ return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE; ++ } ++ ++ switch (sec_channel_type) { ++ case SEC_CHAN_WKSTA: ++ pwd = secrets_fetch_machine_password(domain, ++ &pass_last_set_time, ++ NULL); ++ if (pwd == NULL) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE; ++ } ++ break; ++ case SEC_CHAN_DOMAIN: ++ if (!pdb_get_trusteddom_pw(domain, &pwd, &sid, &pass_last_set_time)) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE; ++ } ++ break; ++ default: ++ TALLOC_FREE(frame); ++ return NT_STATUS_NOT_SUPPORTED; ++ } ++ ++ timeout = lp_machine_password_timeout(); ++ if (timeout == 0) { ++ if (!force) { ++ DEBUG(10,("machine password never expires\n")); ++ TALLOC_FREE(frame); ++ return NT_STATUS_OK; ++ } ++ } ++ ++ tv.tv_sec = pass_last_set_time; ++ DEBUG(10, ("password last changed %s\n", ++ timeval_string(talloc_tos(), &tv, false))); ++ tv.tv_sec += timeout; ++ DEBUGADD(10, ("password valid until %s\n", ++ timeval_string(talloc_tos(), &tv, false))); ++ ++ if (!force && !timeval_expired(&tv)) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_OK; ++ } ++ ++ /* Create a random machine account password */ ++ new_trust_passwd = generate_random_password(frame, ++ DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH, ++ DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); ++ if (new_trust_passwd == NULL) { ++ DEBUG(0, ("generate_random_password failed\n")); ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ status = netlogon_creds_cli_auth(context, b, ++ current_nt_hash, ++ previous_nt_hash); ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); ++ return status; ++ } ++ ++ status = netlogon_creds_cli_ServerPasswordSet(context, b, ++ new_trust_passwd, NULL); ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); ++ return status; ++ } ++ ++ DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n", ++ current_timestring(talloc_tos(), False))); ++ ++ /* ++ * Return the result of trying to write the new password ++ * back into the trust account file. ++ */ ++ ++ switch (sec_channel_type) { ++ ++ case SEC_CHAN_WKSTA: ++ if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_INTERNAL_DB_CORRUPTION; ++ } ++ break; ++ ++ case SEC_CHAN_DOMAIN: ++ /* ++ * we need to get the sid first for the ++ * pdb_set_trusteddom_pw call ++ */ ++ if (!pdb_set_trusteddom_pw(domain, new_trust_passwd, &sid)) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_INTERNAL_DB_CORRUPTION; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ TALLOC_FREE(frame); ++ return NT_STATUS_OK; ++} +-- +1.9.3 + + +From 09dae290b1d49a30eef5b93f5260dc44fb628437 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 18:33:51 +0200 +Subject: [PATCH 195/249] s3:rpcclient: make use of trust_pw_change() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit a9281e6570fcc5ff5abe3149615bed7029d1cf71) +--- + source3/rpcclient/cmd_netlogon.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c +index 59e1e4e..000d65c 100644 +--- a/source3/rpcclient/cmd_netlogon.c ++++ b/source3/rpcclient/cmd_netlogon.c +@@ -829,11 +829,11 @@ static NTSTATUS cmd_netlogon_change_trust_pw(struct rpc_pipe_client *cli, + return NT_STATUS_OK; + } + +- /* Perform the sam logon */ +- +- result = trust_pw_find_change_and_store_it(cli, mem_ctx, +- lp_workgroup()); +- ++ result = trust_pw_change(rpcclient_netlogon_creds, ++ rpcclient_msg_ctx, ++ cli->binding_handle, ++ lp_workgroup(), ++ true); /* force */ + if (!NT_STATUS_IS_OK(result)) + goto done; + +-- +1.9.3 + + +From 3731b2163f6bb88922a9fa84e60fa48afbbbda9a Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 18:34:48 +0200 +Subject: [PATCH 196/249] s3:net_rpc: make use of trust_pw_change() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit cfd139347c21f4f4ddd16026c2c8c221feabd6c5) +--- + source3/utils/net_rpc.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c +index 3bf3f30..ba49f3e 100644 +--- a/source3/utils/net_rpc.c ++++ b/source3/utils/net_rpc.c +@@ -279,7 +279,11 @@ static NTSTATUS rpc_changetrustpw_internals(struct net_context *c, + { + NTSTATUS status; + +- status = trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup); ++ status = trust_pw_change(c->netlogon_creds, ++ c->msg_ctx, ++ pipe_hnd->binding_handle, ++ c->opt_target_workgroup, ++ true); /* force */ + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, _("Failed to change machine account password: %s\n"), + nt_errstr(status)); +-- +1.9.3 + + +From cd8fdfc923adcc5b6c700ec52d1bba4643079247 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 18:35:39 +0200 +Subject: [PATCH 197/249] s3:winbindd: use invalidate_cm_connection() to kill + the netlogon connection + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit dbd49d90bbf175525557eaa983ad57ca5076d710) +--- + source3/winbindd/winbindd_dual.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c +index 64af571..b26cdca 100644 +--- a/source3/winbindd/winbindd_dual.c ++++ b/source3/winbindd/winbindd_dual.c +@@ -1056,7 +1056,7 @@ static void machine_password_change_handler(struct tevent_context *ctx, + "password was changed and we didn't know it. " + "Killing connections to domain %s\n", + child->domain->name)); +- TALLOC_FREE(child->domain->conn.netlogon_pipe); ++ invalidate_cm_connection(&child->domain->conn); + } + + if (!calculate_next_machine_pwd_change(child->domain->name, +-- +1.9.3 + + +From 6369757af75412746c0d9950971a77be72826b92 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 18:36:43 +0200 +Subject: [PATCH 198/249] s3:winbindd: make use of trust_pw_change() for + periodic password changes + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 57741dd4ba5a9ed3abf7aad35a2a69fd66b49b4b) +--- + source3/winbindd/winbindd_dual.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c +index b26cdca..1d6a5ba 100644 +--- a/source3/winbindd/winbindd_dual.c ++++ b/source3/winbindd/winbindd_dual.c +@@ -29,6 +29,7 @@ + + #include "includes.h" + #include "winbindd.h" ++#include "rpc_client/rpc_client.h" + #include "nsswitch/wb_reqtrans.h" + #include "secrets.h" + #include "../lib/util/select.h" +@@ -999,10 +1000,10 @@ static void machine_password_change_handler(struct tevent_context *ctx, + struct timeval now, + void *private_data) + { ++ struct messaging_context *msg_ctx = winbind_messaging_context(); + struct winbindd_child *child = + (struct winbindd_child *)private_data; + struct rpc_pipe_client *netlogon_pipe = NULL; +- TALLOC_CTX *frame; + NTSTATUS result; + struct timeval next_change; + +@@ -1039,15 +1040,14 @@ static void machine_password_change_handler(struct tevent_context *ctx, + return; + } + +- frame = talloc_stackframe(); +- +- result = trust_pw_find_change_and_store_it(netlogon_pipe, +- frame, +- child->domain->name); +- TALLOC_FREE(frame); ++ result = trust_pw_change(child->domain->conn.netlogon_creds, ++ msg_ctx, ++ netlogon_pipe->binding_handle, ++ child->domain->name, ++ false); /* force */ + + DEBUG(10, ("machine_password_change_handler: " +- "trust_pw_find_change_and_store_it returned %s\n", ++ "trust_pw_change returned %s\n", + nt_errstr(result))); + + if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) { +-- +1.9.3 + + +From 5fe11c760d853dff63ad9b3505f3d3721b7e14f6 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 18:37:34 +0200 +Subject: [PATCH 199/249] s3:winbindd: make use of trust_pw_change() in + _wbint_ChangeMachineAccount() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 3c30e19c4a0e60e355b2f1d35edbb0a3b7688089) +--- + source3/winbindd/winbindd_dual_srv.c | 35 +++++++---------------------------- + 1 file changed, 7 insertions(+), 28 deletions(-) + +diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c +index 001591a..f064467 100644 +--- a/source3/winbindd/winbindd_dual_srv.c ++++ b/source3/winbindd/winbindd_dual_srv.c +@@ -622,48 +622,27 @@ again: + NTSTATUS _wbint_ChangeMachineAccount(struct pipes_struct *p, + struct wbint_ChangeMachineAccount *r) + { ++ struct messaging_context *msg_ctx = winbind_messaging_context(); + struct winbindd_domain *domain; +- int num_retries = 0; + NTSTATUS status; + struct rpc_pipe_client *netlogon_pipe; +- TALLOC_CTX *tmp_ctx; + +-again: + domain = wb_child_domain(); + if (domain == NULL) { + return NT_STATUS_REQUEST_NOT_ACCEPTED; + } + +- invalidate_cm_connection(&domain->conn); +- +- { +- status = cm_connect_netlogon(domain, &netlogon_pipe); +- } +- +- /* There is a race condition between fetching the trust account +- password and the periodic machine password change. So it's +- possible that the trust account password has been changed on us. +- We are returned NT_STATUS_ACCESS_DENIED if this happens. */ +- +-#define MAX_RETRIES 3 +- +- if ((num_retries < MAX_RETRIES) +- && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { +- num_retries++; +- goto again; +- } +- ++ status = cm_connect_netlogon(domain, &netlogon_pipe); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("could not open handle to NETLOGON pipe\n")); + goto done; + } + +- tmp_ctx = talloc_new(p->mem_ctx); +- +- status = trust_pw_find_change_and_store_it(netlogon_pipe, +- tmp_ctx, +- domain->name); +- talloc_destroy(tmp_ctx); ++ status = trust_pw_change(domain->conn.netlogon_creds, ++ msg_ctx, ++ netlogon_pipe->binding_handle, ++ domain->name, ++ true); /* force */ + + /* Pass back result code - zero for success, other values for + specific failures. */ +-- +1.9.3 + + +From 9956ea8b561da89fb79739dd8a8552116c7867f7 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 18:39:52 +0200 +Subject: [PATCH 200/249] s3:libsmb: remove unused + trust_pw_find_change_and_store_it() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit a8ecebe3e840005c81df043cb07773972aaa2371) +--- + source3/include/proto.h | 3 -- + source3/libsmb/trusts_util.c | 81 -------------------------------------------- + 2 files changed, 84 deletions(-) + +diff --git a/source3/include/proto.h b/source3/include/proto.h +index edda119..18348e5 100644 +--- a/source3/include/proto.h ++++ b/source3/include/proto.h +@@ -981,9 +981,6 @@ void update_trustdom_cache( void ); + + /* The following definitions come from libsmb/trusts_util.c */ + +-NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, +- TALLOC_CTX *mem_ctx, +- const char *domain) ; + struct netlogon_creds_cli_context; + struct messaging_context; + struct dcerpc_binding_handle; +diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c +index b1bc006..b38aec6 100644 +--- a/source3/libsmb/trusts_util.c ++++ b/source3/libsmb/trusts_util.c +@@ -36,87 +36,6 @@ + already setup the connection to the NETLOGON pipe + **********************************************************/ + +-NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, +- TALLOC_CTX *mem_ctx, +- const char *domain) +-{ +- unsigned char old_trust_passwd_hash[16]; +- unsigned char new_trust_passwd_hash[16]; +- enum netr_SchannelType sec_channel_type = SEC_CHAN_NULL; +- const char *account_name; +- char *new_trust_passwd; +- NTSTATUS nt_status; +- +- if (!get_trust_pw_hash(domain, old_trust_passwd_hash, &account_name, +- &sec_channel_type)) { +- DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain)); +- return NT_STATUS_UNSUCCESSFUL; +- } +- +- switch (sec_channel_type) { +- case SEC_CHAN_WKSTA: +- case SEC_CHAN_DOMAIN: +- break; +- default: +- return NT_STATUS_NOT_SUPPORTED; +- } +- +- /* Create a random machine account password */ +- new_trust_passwd = generate_random_password(mem_ctx, +- DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH, +- DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); +- if (new_trust_passwd == NULL) { +- DEBUG(0, ("generate_random_password failed\n")); +- return NT_STATUS_NO_MEMORY; +- } +- +- E_md4hash(new_trust_passwd, new_trust_passwd_hash); +- +- nt_status = rpccli_netlogon_set_trust_password(cli, mem_ctx, +- account_name, +- old_trust_passwd_hash, +- new_trust_passwd, +- new_trust_passwd_hash, +- sec_channel_type); +- +- if (NT_STATUS_IS_OK(nt_status)) { +- DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n", +- current_timestring(talloc_tos(), False))); +- /* +- * Return the result of trying to write the new password +- * back into the trust account file. +- */ +- +- switch (sec_channel_type) { +- +- case SEC_CHAN_WKSTA: +- if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) { +- nt_status = NT_STATUS_UNSUCCESSFUL; +- } +- break; +- +- case SEC_CHAN_DOMAIN: { +- char *pwd; +- struct dom_sid sid; +- time_t pass_last_set_time; +- +- /* we need to get the sid first for the +- * pdb_set_trusteddom_pw call */ +- +- if (!pdb_get_trusteddom_pw(domain, &pwd, &sid, &pass_last_set_time)) { +- nt_status = NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE; +- } +- if (!pdb_set_trusteddom_pw(domain, new_trust_passwd, &sid)) { +- nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION; +- } +- break; +- } +- } +- } +- +- return nt_status; +-} +- + struct trust_pw_change_state { + struct g_lock_ctx *g_ctx; + char *g_lock_key; +-- +1.9.3 + + +From f71cb73d7f034165802aad97e9be6f45ba32d519 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 19:19:39 +0200 +Subject: [PATCH 201/249] s3:libnet: pass in struct netlogon_creds_cli_context + from the caller. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 77defb175e3ffd1b096485ac7de38ad161594b72) +--- + source3/libnet/libnet_samsync.c | 2 +- + source3/libnet/libnet_samsync.h | 1 + + source3/utils/net_rpc_samsync.c | 1 + + 3 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/source3/libnet/libnet_samsync.c b/source3/libnet/libnet_samsync.c +index 02d3fc6..e7e1393 100644 +--- a/source3/libnet/libnet_samsync.c ++++ b/source3/libnet/libnet_samsync.c +@@ -216,7 +216,7 @@ static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx, + struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; + struct netlogon_creds_CredentialState *creds = NULL; + +- status = netlogon_creds_cli_lock(ctx->cli->netlogon_creds, ++ status = netlogon_creds_cli_lock(ctx->netlogon_creds, + mem_ctx, &creds); + if (!NT_STATUS_IS_OK(status)) { + return status; +diff --git a/source3/libnet/libnet_samsync.h b/source3/libnet/libnet_samsync.h +index efdbb37..e1d66ec 100644 +--- a/source3/libnet/libnet_samsync.h ++++ b/source3/libnet/libnet_samsync.h +@@ -75,6 +75,7 @@ struct samsync_context { + struct samsync_object *objects; + + struct rpc_pipe_client *cli; ++ struct netlogon_creds_cli_context *netlogon_creds; + struct messaging_context *msg_ctx; + + const struct samsync_ops *ops; +diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c +index 772651f..6377ad4 100644 +--- a/source3/utils/net_rpc_samsync.c ++++ b/source3/utils/net_rpc_samsync.c +@@ -129,6 +129,7 @@ NTSTATUS rpc_samdump_internals(struct net_context *c, + + ctx->mode = NET_SAMSYNC_MODE_DUMP; + ctx->cli = pipe_hnd; ++ ctx->netlogon_creds = c->netlogon_creds; + ctx->ops = &libnet_samsync_display_ops; + ctx->domain_name = domain_name; + +-- +1.9.3 + + +From acb678ce415403e1442116b32eb8b8b32b677f4a Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 20:51:25 +0200 +Subject: [PATCH 202/249] s3:rpcclient: make use of + rpccli_{create,setup}_netlogon_creds() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 5107ca02a41673739a1fc4a1c2a0fbe8465f211a) +--- + source3/rpcclient/rpcclient.c | 59 ++++++++++++++++++++++++++++++------------- + 1 file changed, 41 insertions(+), 18 deletions(-) + +diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c +index a875ff5..490f8df 100644 +--- a/source3/rpcclient/rpcclient.c ++++ b/source3/rpcclient/rpcclient.c +@@ -676,6 +676,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, + { + NTSTATUS ntresult; + WERROR wresult; ++ bool ok; + + TALLOC_CTX *mem_ctx; + +@@ -759,17 +760,20 @@ static NTSTATUS do_cmd(struct cli_state *cli, + return ntresult; + } + +- if (ndr_syntax_id_equal(&cmd_entry->table->syntax_id, +- &ndr_table_netlogon.syntax_id)) { +- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | +- NETLOGON_NEG_SUPPORTS_AES; +- enum netr_SchannelType sec_channel_type; +- uchar trust_password[16]; +- const char *machine_account; ++ ok = ndr_syntax_id_equal(&cmd_entry->table->syntax_id, ++ &ndr_table_netlogon.syntax_id); ++ if (cmd_entry->rpc_pipe->netlogon_creds == NULL && ok) { ++ const char *dc_name = cmd_entry->rpc_pipe->desthost; ++ const char *domain = get_cmdline_auth_info_domain(auth_info); ++ enum netr_SchannelType sec_chan_type = 0; ++ const char *_account_name = NULL; ++ const char *account_name = NULL; ++ struct samr_Password current_nt_hash; ++ struct samr_Password *previous_nt_hash = NULL; + + if (!get_trust_pw_hash(get_cmdline_auth_info_domain(auth_info), +- trust_password, &machine_account, +- &sec_channel_type)) ++ current_nt_hash.hash, &_account_name, ++ &sec_chan_type)) + { + DEBUG(0, ("Failed to fetch trust password for %s to connect to %s.\n", + get_cmdline_auth_info_domain(auth_info), +@@ -779,22 +783,41 @@ static NTSTATUS do_cmd(struct cli_state *cli, + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + +- ntresult = rpccli_netlogon_setup_creds(cmd_entry->rpc_pipe, +- cmd_entry->rpc_pipe->desthost, /* server name */ +- get_cmdline_auth_info_domain(auth_info), /* domain */ +- lp_netbios_name(), /* client name */ +- machine_account, /* machine account name */ +- trust_password, +- sec_channel_type, +- &neg_flags); ++ account_name = talloc_asprintf(mem_ctx, "%s$", _account_name); ++ if (account_name == NULL) { ++ SAFE_FREE(previous_nt_hash); ++ TALLOC_FREE(mem_ctx); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ ntresult = rpccli_create_netlogon_creds(dc_name, ++ domain, ++ account_name, ++ sec_chan_type, ++ rpcclient_msg_ctx, ++ talloc_autofree_context(), ++ &rpcclient_netlogon_creds); ++ if (!NT_STATUS_IS_OK(ntresult)) { ++ SAFE_FREE(previous_nt_hash); ++ TALLOC_FREE(mem_ctx); ++ return ntresult; ++ } + ++ ntresult = rpccli_setup_netlogon_creds(cli, ++ rpcclient_netlogon_creds, ++ false, /* force_reauth */ ++ current_nt_hash, ++ previous_nt_hash); ++ SAFE_FREE(previous_nt_hash); + if (!NT_STATUS_IS_OK(ntresult)) { + DEBUG(0, ("Could not initialise credentials for %s.\n", + cmd_entry->table->name)); + TALLOC_FREE(cmd_entry->rpc_pipe); +- talloc_free(mem_ctx); ++ TALLOC_FREE(rpcclient_netlogon_creds); ++ TALLOC_FREE(mem_ctx); + return ntresult; + } ++ cmd_entry->rpc_pipe->netlogon_creds = rpcclient_netlogon_creds; + } + } + +-- +1.9.3 + + +From b04744971aa9cc696aa4a3c56dd46d58db8dda75 Mon Sep 17 00:00:00 2001 +From: Garming Sam +Date: Fri, 29 Nov 2013 14:45:20 +1300 +Subject: [PATCH 203/249] s3:rpcclient: give errors and clean up correctly + after failing to obtain secret + +Signed-off-by: Garming Sam +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit a012e2fdd6733e871ddeb68874a2df8413ad91ed) +--- + source3/rpcclient/rpcclient.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c +index 490f8df..fd3ebdf 100644 +--- a/source3/rpcclient/rpcclient.c ++++ b/source3/rpcclient/rpcclient.c +@@ -785,6 +785,9 @@ static NTSTATUS do_cmd(struct cli_state *cli, + + account_name = talloc_asprintf(mem_ctx, "%s$", _account_name); + if (account_name == NULL) { ++ DEBUG(0, ("Out of memory creating account name to connect to %s.\n", ++ cmd_entry->table->name)); ++ TALLOC_FREE(cmd_entry->rpc_pipe); + SAFE_FREE(previous_nt_hash); + TALLOC_FREE(mem_ctx); + return NT_STATUS_NO_MEMORY; +@@ -798,6 +801,9 @@ static NTSTATUS do_cmd(struct cli_state *cli, + talloc_autofree_context(), + &rpcclient_netlogon_creds); + if (!NT_STATUS_IS_OK(ntresult)) { ++ DEBUG(0, ("Could not initialise credentials for %s.\n", ++ cmd_entry->table->name)); ++ TALLOC_FREE(cmd_entry->rpc_pipe); + SAFE_FREE(previous_nt_hash); + TALLOC_FREE(mem_ctx); + return ntresult; +-- +1.9.3 + + +From 564e6df9361025ff7da6fa92d83491cfd9e60b2b Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 17 Sep 2013 00:46:09 +0200 +Subject: [PATCH 204/249] s3:rpcclient: remove optional auth_level parameter of + the 'samlogon' cmd + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 4c99e49898151a514e334a07f38eed83fe608c05) +--- + source3/rpcclient/cmd_netlogon.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c +index 000d65c..97b79cb 100644 +--- a/source3/rpcclient/cmd_netlogon.c ++++ b/source3/rpcclient/cmd_netlogon.c +@@ -782,9 +782,9 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, + + /* Check arguments */ + +- if (argc < 3 || argc > 7) { ++ if (argc < 3 || argc > 6) { + fprintf(stderr, "Usage: samlogon [workstation]" +- "[logon_type (1 or 2)] [auth level (2 or 3)] [logon_parameter]\n"); ++ "[logon_type (1 or 2)] [logon_parameter]\n"); + return NT_STATUS_OK; + } + +@@ -797,11 +797,8 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, + if (argc >= 5) + sscanf(argv[4], "%i", &logon_type); + +- if (argc >= 6) +- validation_level = atoi(argv[5]); +- +- if (argc == 7) +- sscanf(argv[6], "%x", &logon_param); ++ if (argc == 6) ++ sscanf(argv[5], "%x", &logon_param); + + /* Perform the sam logon */ + +-- +1.9.3 + + +From a61d399c13c9f46e283f85f3d076b0607c2729f3 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 17 Sep 2013 00:48:31 +0200 +Subject: [PATCH 205/249] s3:rpcclient: make use of + rpccli_netlogon_password_logon() in the 'samlogon' cmd + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit c6bb47f2f199cc13101dccf656ac36e9eb879201) +--- + source3/rpcclient/cmd_netlogon.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c +index 97b79cb..b637b3e 100644 +--- a/source3/rpcclient/cmd_netlogon.c ++++ b/source3/rpcclient/cmd_netlogon.c +@@ -776,7 +776,6 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + int logon_type = NetlogonNetworkInformation; + const char *username, *password; +- uint16_t validation_level = 3; + uint32 logon_param = 0; + const char *workstation = NULL; + +@@ -802,8 +801,14 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, + + /* Perform the sam logon */ + +- result = rpccli_netlogon_sam_logon(cli, mem_ctx, logon_param, lp_workgroup(), username, password, workstation, validation_level, logon_type); +- ++ result = rpccli_netlogon_password_logon(rpcclient_netlogon_creds, ++ cli->binding_handle, ++ logon_param, ++ lp_workgroup(), ++ username, ++ password, ++ workstation, ++ logon_type); + if (!NT_STATUS_IS_OK(result)) + goto done; + +-- +1.9.3 + + +From fbe0154a63d401acd47c5190be37b8d69d3d64ba Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 17 Sep 2013 00:56:15 +0200 +Subject: [PATCH 206/249] s3:winbindd: make use of + rpccli_netlogon_network_logon() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit a34c837fdb59df1e66be9b5f23a07990e34fea1c) +--- + source3/winbindd/winbindd_pam.c | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c +index 39483a5..3f3ec70 100644 +--- a/source3/winbindd/winbindd_pam.c ++++ b/source3/winbindd/winbindd_pam.c +@@ -1228,6 +1228,8 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, + + do { + struct rpc_pipe_client *netlogon_pipe; ++ uint8_t authoritative = 0; ++ uint32_t flags = 0; + + ZERO_STRUCTP(info3); + retry = false; +@@ -1276,19 +1278,19 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, + } + netr_attempts = 0; + +- result = rpccli_netlogon_sam_network_logon( +- netlogon_pipe, +- mem_ctx, +- logon_parameters, +- server, /* server name */ +- username, /* user name */ +- domainname, /* target domain */ +- workstation, /* workstation */ +- chal, +- -1, /* ignored */ +- lm_response, +- nt_response, +- info3); ++ result = rpccli_netlogon_network_logon(domain->conn.netlogon_creds, ++ netlogon_pipe->binding_handle, ++ mem_ctx, ++ logon_parameters, ++ username, ++ domainname, ++ workstation, ++ chal, ++ lm_response, ++ nt_response, ++ &authoritative, ++ &flags, ++ info3); + + /* + * we increment this after the "feature negotiation" +-- +1.9.3 + + +From cfcb681d6f80253b6f2db769f5c5be1ffb54cc0e Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 20:53:51 +0200 +Subject: [PATCH 207/249] s3:rpc_client: make cli_rpc_pipe_open_schannel() more + flexible + +It expects a messaging_context now +and returns a netlogon_creds_cli_context. + +This way we can finally avoid having a rpc_pipe_client->netlogon_creds. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 660150b12a637da7f9ebb820e687f27ac22fb93a) +--- + source3/rpc_client/cli_pipe.h | 5 ++++- + source3/rpc_client/cli_pipe_schannel.c | 9 +++++++-- + source3/rpcclient/rpcclient.c | 13 +++++++------ + source3/utils/net_rpc.c | 6 +++--- + 4 files changed, 21 insertions(+), 12 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h +index 2a76130..b704d8a 100644 +--- a/source3/rpc_client/cli_pipe.h ++++ b/source3/rpc_client/cli_pipe.h +@@ -99,11 +99,14 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + struct rpc_pipe_client **presult); + + NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, ++ struct messaging_context *msg_ctx, + const struct ndr_interface_table *table, + enum dcerpc_transport_t transport, + enum dcerpc_AuthLevel auth_level, + const char *domain, +- struct rpc_pipe_client **presult); ++ struct rpc_pipe_client **presult, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_cli_context **pcreds); + + NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, + struct rpc_pipe_client *cli, +diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c +index 1fcf62e..a842333 100644 +--- a/source3/rpc_client/cli_pipe_schannel.c ++++ b/source3/rpc_client/cli_pipe_schannel.c +@@ -38,14 +38,16 @@ + ****************************************************************************/ + + NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, ++ struct messaging_context *msg_ctx, + const struct ndr_interface_table *table, + enum dcerpc_transport_t transport, + enum dcerpc_AuthLevel auth_level, + const char *domain, +- struct rpc_pipe_client **presult) ++ struct rpc_pipe_client **presult, ++ TALLOC_CTX *mem_ctx, ++ struct netlogon_creds_cli_context **pcreds) + { + TALLOC_CTX *frame = talloc_stackframe(); +- struct messaging_context *msg_ctx = NULL; + const char *dc_name = smbXcli_conn_remote_name(cli->conn); + struct rpc_pipe_client *result = NULL; + NTSTATUS status; +@@ -121,6 +123,9 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, + + if (NT_STATUS_IS_OK(status)) { + *presult = result; ++ if (pcreds != NULL) { ++ *pcreds = talloc_move(mem_ctx, &netlogon_creds); ++ } + } + + TALLOC_FREE(frame); +diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c +index fd3ebdf..43343e8 100644 +--- a/source3/rpcclient/rpcclient.c ++++ b/source3/rpcclient/rpcclient.c +@@ -737,12 +737,16 @@ static NTSTATUS do_cmd(struct cli_state *cli, + &cmd_entry->rpc_pipe); + break; + case DCERPC_AUTH_TYPE_SCHANNEL: ++ TALLOC_FREE(rpcclient_netlogon_creds); + ntresult = cli_rpc_pipe_open_schannel( +- cli, cmd_entry->table, ++ cli, rpcclient_msg_ctx, ++ cmd_entry->table, + default_transport, + pipe_default_auth_level, + get_cmdline_auth_info_domain(auth_info), +- &cmd_entry->rpc_pipe); ++ &cmd_entry->rpc_pipe, ++ talloc_autofree_context(), ++ &rpcclient_netlogon_creds); + break; + default: + DEBUG(0, ("Could not initialise %s. Invalid " +@@ -762,7 +766,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, + + ok = ndr_syntax_id_equal(&cmd_entry->table->syntax_id, + &ndr_table_netlogon.syntax_id); +- if (cmd_entry->rpc_pipe->netlogon_creds == NULL && ok) { ++ if (rpcclient_netlogon_creds == NULL && ok) { + const char *dc_name = cmd_entry->rpc_pipe->desthost; + const char *domain = get_cmdline_auth_info_domain(auth_info); + enum netr_SchannelType sec_chan_type = 0; +@@ -823,12 +827,9 @@ static NTSTATUS do_cmd(struct cli_state *cli, + TALLOC_FREE(mem_ctx); + return ntresult; + } +- cmd_entry->rpc_pipe->netlogon_creds = rpcclient_netlogon_creds; + } + } + +- rpcclient_netlogon_creds = cmd_entry->rpc_pipe->netlogon_creds; +- + /* Run command */ + + if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) { +diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c +index ba49f3e..d0f699a 100644 +--- a/source3/utils/net_rpc.c ++++ b/source3/utils/net_rpc.c +@@ -192,16 +192,16 @@ int run_rpc_command(struct net_context *c, + && (ndr_syntax_id_equal(&table->syntax_id, + &ndr_table_netlogon.syntax_id))) { + /* Always try and create an schannel netlogon pipe. */ ++ TALLOC_FREE(c->netlogon_creds); + nt_status = cli_rpc_pipe_open_schannel( +- cli, table, NCACN_NP, ++ cli, c->msg_ctx, table, NCACN_NP, + DCERPC_AUTH_LEVEL_PRIVACY, domain_name, +- &pipe_hnd); ++ &pipe_hnd, c, &c->netlogon_creds); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n", + nt_errstr(nt_status) )); + goto fail; + } +- c->netlogon_creds = pipe_hnd->netlogon_creds; + } else { + if (conn_flags & NET_FLAGS_SEAL) { + nt_status = cli_rpc_pipe_open_generic_auth( +-- +1.9.3 + + +From 603b40eeee3cf21de94f11471889d0443713ba4f Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 6 Sep 2013 13:54:30 +0200 +Subject: [PATCH 208/249] s3:rpc_client: remove unused + rpccli_netlogon_set_trust_password() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 6d457ad9c156cf86d99e58dea21dba170defad1b) +--- + source3/rpc_client/cli_netlogon.c | 51 --------------------------------------- + source3/rpc_client/cli_netlogon.h | 7 ------ + 2 files changed, 58 deletions(-) + +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index a9f8604..2f23d1b 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -759,54 +759,3 @@ NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds, + + return NT_STATUS_OK; + } +- +-/********************************************************* +- Change the domain password on the PDC. +- +- Just changes the password betwen the two values specified. +- +- Caller must have the cli connected to the netlogon pipe +- already. +-**********************************************************/ +- +-NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, +- TALLOC_CTX *mem_ctx, +- const char *account_name, +- const unsigned char orig_trust_passwd_hash[16], +- const char *new_trust_pwd_cleartext, +- const unsigned char new_trust_passwd_hash[16], +- enum netr_SchannelType sec_channel_type) +-{ +- NTSTATUS result; +- +- if (cli->netlogon_creds == NULL) { +- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | +- NETLOGON_NEG_SUPPORTS_AES; +- result = rpccli_netlogon_setup_creds(cli, +- cli->desthost, /* server name */ +- lp_workgroup(), /* domain */ +- lp_netbios_name(), /* client name */ +- account_name, /* machine account name */ +- orig_trust_passwd_hash, +- sec_channel_type, +- &neg_flags); +- if (!NT_STATUS_IS_OK(result)) { +- DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n", +- nt_errstr(result))); +- return result; +- } +- } +- +- result = netlogon_creds_cli_ServerPasswordSet(cli->netlogon_creds, +- cli->binding_handle, +- new_trust_pwd_cleartext, +- NULL); /* new_version */ +- if (!NT_STATUS_IS_OK(result)) { +- DEBUG(0,("netlogon_creds_cli_ServerPasswordSet failed: %s\n", +- nt_errstr(result))); +- return result; +- } +- +- return NT_STATUS_OK; +-} +- +diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h +index d4c6670..8547db6 100644 +--- a/source3/rpc_client/cli_netlogon.h ++++ b/source3/rpc_client/cli_netlogon.h +@@ -93,12 +93,5 @@ NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds, + uint8_t *authoritative, + uint32_t *flags, + struct netr_SamInfo3 **info3); +-NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, +- TALLOC_CTX *mem_ctx, +- const char *account_name, +- const unsigned char orig_trust_passwd_hash[16], +- const char *new_trust_pwd_cleartext, +- const unsigned char new_trust_passwd_hash[16], +- enum netr_SchannelType sec_channel_type); + + #endif /* _RPC_CLIENT_CLI_NETLOGON_H_ */ +-- +1.9.3 + + +From c9dc23d434bc7015f400b1969a055b95faac6594 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 6 Sep 2013 13:06:53 +0200 +Subject: [PATCH 209/249] s3:rpc_client: remove unused + rpccli_netlogon_setup_creds() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit a4faf57b47095bfc0f4370ac093c8c4cef17584f) +--- + source3/rpc_client/cli_netlogon.c | 92 --------------------------------------- + source3/rpc_client/cli_netlogon.h | 8 ---- + 2 files changed, 100 deletions(-) + +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index 2f23d1b..687d0c2 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -35,98 +35,6 @@ + #include "lib/param/param.h" + #include "libcli/smb/smbXcli_base.h" + +-/**************************************************************************** +- Wrapper function that uses the auth and auth2 calls to set up a NETLOGON +- credentials chain. Stores the credentials in the struct dcinfo in the +- netlogon pipe struct. +-****************************************************************************/ +- +-NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, +- const char *server_name, +- const char *domain, +- const char *clnt_name, +- const char *machine_account, +- const unsigned char machine_pwd[16], +- enum netr_SchannelType sec_chan_type, +- uint32_t *neg_flags_inout) +-{ +- TALLOC_CTX *frame = talloc_stackframe(); +- struct loadparm_context *lp_ctx; +- NTSTATUS status; +- struct samr_Password password; +- fstring mach_acct; +- struct dcerpc_binding_handle *b = cli->binding_handle; +- struct netlogon_creds_CredentialState *creds = NULL; +- +- if (!ndr_syntax_id_equal(&cli->abstract_syntax, +- &ndr_table_netlogon.syntax_id)) { +- TALLOC_FREE(frame); +- return NT_STATUS_INVALID_PARAMETER; +- } +- +- if (!strequal(lp_netbios_name(), clnt_name)) { +- TALLOC_FREE(frame); +- return NT_STATUS_INVALID_PARAMETER; +- } +- +- TALLOC_FREE(cli->netlogon_creds); +- +- fstr_sprintf( mach_acct, "%s$", machine_account); +- +- lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); +- if (lp_ctx == NULL) { +- TALLOC_FREE(frame); +- return NT_STATUS_NO_MEMORY; +- } +- status = netlogon_creds_cli_context_global(lp_ctx, +- NULL, /* msg_ctx */ +- mach_acct, +- sec_chan_type, +- server_name, +- domain, +- cli, &cli->netlogon_creds); +- talloc_unlink(frame, lp_ctx); +- if (!NT_STATUS_IS_OK(status)) { +- TALLOC_FREE(frame); +- return status; +- } +- +- status = netlogon_creds_cli_get(cli->netlogon_creds, +- frame, &creds); +- if (NT_STATUS_IS_OK(status)) { +- DEBUG(5,("rpccli_netlogon_setup_creds: server %s using " +- "cached credential\n", +- cli->desthost)); +- *neg_flags_inout = creds->negotiate_flags; +- TALLOC_FREE(frame); +- return NT_STATUS_OK; +- } +- +- /* Store the machine account password we're going to use. */ +- memcpy(password.hash, machine_pwd, 16); +- +- DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential " +- "chain established.\n", +- cli->desthost )); +- +- status = netlogon_creds_cli_auth(cli->netlogon_creds, b, +- password, NULL); +- if (!NT_STATUS_IS_OK(status)) { +- TALLOC_FREE(frame); +- return status; +- } +- +- status = netlogon_creds_cli_get(cli->netlogon_creds, +- frame, &creds); +- if (!NT_STATUS_IS_OK(status)) { +- TALLOC_FREE(frame); +- return NT_STATUS_INTERNAL_ERROR; +- } +- +- *neg_flags_inout = creds->negotiate_flags; +- TALLOC_FREE(frame); +- return NT_STATUS_OK; +-} + + NTSTATUS rpccli_pre_open_netlogon_creds(void) + { +diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h +index 8547db6..0de836a 100644 +--- a/source3/rpc_client/cli_netlogon.h ++++ b/source3/rpc_client/cli_netlogon.h +@@ -30,14 +30,6 @@ struct dcerpc_binding_handle; + + /* The following definitions come from rpc_client/cli_netlogon.c */ + +-NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, +- const char *server_name, +- const char *domain, +- const char *clnt_name, +- const char *machine_account, +- const unsigned char machine_pwd[16], +- enum netr_SchannelType sec_chan_type, +- uint32_t *neg_flags_inout); + NTSTATUS rpccli_pre_open_netlogon_creds(void); + NTSTATUS rpccli_create_netlogon_creds(const char *server_computer, + const char *server_netbios_domain, +-- +1.9.3 + + +From 2a072da1cc18acc7eb6d82769dc96b7e94ec57fe Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 19:23:18 +0200 +Subject: [PATCH 210/249] s3:rpc_client: remove unused + rpccli_netlogon_sam_logon() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit e4fea80693b49e79a96acdac09d5ea292756635c) +--- + source3/rpc_client/cli_netlogon.c | 124 -------------------------------------- + source3/rpc_client/cli_netlogon.h | 9 --- + 2 files changed, 133 deletions(-) + +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index 687d0c2..171337a 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -160,130 +160,6 @@ NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, + + /* Logon domain user */ + +-NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, +- TALLOC_CTX *mem_ctx, +- uint32 logon_parameters, +- const char *domain, +- const char *username, +- const char *password, +- const char *workstation, +- uint16_t _ignored_validation_level, +- int logon_type) +-{ +- NTSTATUS status; +- union netr_LogonLevel *logon; +- uint16_t validation_level = 0; +- union netr_Validation *validation = NULL; +- uint8_t authoritative = 0; +- uint32_t flags = 0; +- fstring clnt_name_slash; +- +- logon = talloc_zero(mem_ctx, union netr_LogonLevel); +- if (!logon) { +- return NT_STATUS_NO_MEMORY; +- } +- +- if (workstation) { +- fstr_sprintf( clnt_name_slash, "\\\\%s", workstation ); +- } else { +- fstr_sprintf( clnt_name_slash, "\\\\%s", lp_netbios_name() ); +- } +- +- /* Initialise input parameters */ +- +- switch (logon_type) { +- case NetlogonInteractiveInformation: { +- +- struct netr_PasswordInfo *password_info; +- +- struct samr_Password lmpassword; +- struct samr_Password ntpassword; +- +- password_info = talloc_zero(mem_ctx, struct netr_PasswordInfo); +- if (!password_info) { +- return NT_STATUS_NO_MEMORY; +- } +- +- nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash); +- +- password_info->identity_info.domain_name.string = domain; +- password_info->identity_info.parameter_control = logon_parameters; +- password_info->identity_info.logon_id_low = 0xdead; +- password_info->identity_info.logon_id_high = 0xbeef; +- password_info->identity_info.account_name.string = username; +- password_info->identity_info.workstation.string = clnt_name_slash; +- +- password_info->lmpassword = lmpassword; +- password_info->ntpassword = ntpassword; +- +- logon->password = password_info; +- +- break; +- } +- case NetlogonNetworkInformation: { +- struct netr_NetworkInfo *network_info; +- uint8 chal[8]; +- unsigned char local_lm_response[24]; +- unsigned char local_nt_response[24]; +- struct netr_ChallengeResponse lm; +- struct netr_ChallengeResponse nt; +- +- ZERO_STRUCT(lm); +- ZERO_STRUCT(nt); +- +- network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo); +- if (!network_info) { +- return NT_STATUS_NO_MEMORY; +- } +- +- generate_random_buffer(chal, 8); +- +- SMBencrypt(password, chal, local_lm_response); +- SMBNTencrypt(password, chal, local_nt_response); +- +- lm.length = 24; +- lm.data = local_lm_response; +- +- nt.length = 24; +- nt.data = local_nt_response; +- +- network_info->identity_info.domain_name.string = domain; +- network_info->identity_info.parameter_control = logon_parameters; +- network_info->identity_info.logon_id_low = 0xdead; +- network_info->identity_info.logon_id_high = 0xbeef; +- network_info->identity_info.account_name.string = username; +- network_info->identity_info.workstation.string = clnt_name_slash; +- +- memcpy(network_info->challenge, chal, 8); +- network_info->nt = nt; +- network_info->lm = lm; +- +- logon->network = network_info; +- +- break; +- } +- default: +- DEBUG(0, ("switch value %d not supported\n", +- logon_type)); +- return NT_STATUS_INVALID_INFO_CLASS; +- } +- +- status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds, +- cli->binding_handle, +- logon_type, +- logon, +- mem_ctx, +- &validation_level, +- &validation, +- &authoritative, +- &flags); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- +- return NT_STATUS_OK; +-} +- + NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds, + struct dcerpc_binding_handle *binding_handle, + uint32_t logon_parameters, +diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h +index 0de836a..eaa5b0c 100644 +--- a/source3/rpc_client/cli_netlogon.h ++++ b/source3/rpc_client/cli_netlogon.h +@@ -43,15 +43,6 @@ NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, + bool force_reauth, + struct samr_Password current_nt_hash, + const struct samr_Password *previous_nt_hash); +-NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, +- TALLOC_CTX *mem_ctx, +- uint32 logon_parameters, +- const char *domain, +- const char *username, +- const char *password, +- const char *workstation, +- uint16_t validation_level, +- int logon_type); + NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds, + struct dcerpc_binding_handle *binding_handle, + uint32_t logon_parameters, +-- +1.9.3 + + +From 4092fca5daf42e1cd26af8069b09b97a7d01df9c Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 19:23:54 +0200 +Subject: [PATCH 211/249] s3:rpc_client: remove unused + rpccli_netlogon_sam_network_logon() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 3f41b583840ffa2220f61eea61833bf3c6bd33db) +--- + source3/rpc_client/cli_netlogon.c | 94 --------------------------------------- + source3/rpc_client/cli_netlogon.h | 12 ----- + 2 files changed, 106 deletions(-) + +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index 171337a..ca2d9bf 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -346,100 +346,6 @@ static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx, + * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller. + **/ + +-NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, +- TALLOC_CTX *mem_ctx, +- uint32 logon_parameters, +- const char *server, +- const char *username, +- const char *domain, +- const char *workstation, +- const uint8 chal[8], +- uint16_t _ignored_validation_level, +- DATA_BLOB lm_response, +- DATA_BLOB nt_response, +- struct netr_SamInfo3 **info3) +-{ +- NTSTATUS status; +- const char *workstation_name_slash; +- union netr_LogonLevel *logon = NULL; +- struct netr_NetworkInfo *network_info; +- uint16_t validation_level = 0; +- union netr_Validation *validation = NULL; +- uint8_t authoritative = 0; +- uint32_t flags = 0; +- struct netr_ChallengeResponse lm; +- struct netr_ChallengeResponse nt; +- +- *info3 = NULL; +- +- ZERO_STRUCT(lm); +- ZERO_STRUCT(nt); +- +- logon = talloc_zero(mem_ctx, union netr_LogonLevel); +- if (!logon) { +- return NT_STATUS_NO_MEMORY; +- } +- +- network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo); +- if (!network_info) { +- return NT_STATUS_NO_MEMORY; +- } +- +- if (workstation[0] != '\\' && workstation[1] != '\\') { +- workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation); +- } else { +- workstation_name_slash = workstation; +- } +- +- if (!workstation_name_slash) { +- DEBUG(0, ("talloc_asprintf failed!\n")); +- return NT_STATUS_NO_MEMORY; +- } +- +- /* Initialise input parameters */ +- +- lm.data = lm_response.data; +- lm.length = lm_response.length; +- nt.data = nt_response.data; +- nt.length = nt_response.length; +- +- network_info->identity_info.domain_name.string = domain; +- network_info->identity_info.parameter_control = logon_parameters; +- network_info->identity_info.logon_id_low = 0xdead; +- network_info->identity_info.logon_id_high = 0xbeef; +- network_info->identity_info.account_name.string = username; +- network_info->identity_info.workstation.string = workstation_name_slash; +- +- memcpy(network_info->challenge, chal, 8); +- network_info->nt = nt; +- network_info->lm = lm; +- +- logon->network = network_info; +- +- /* Marshall data and send request */ +- +- status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds, +- cli->binding_handle, +- NetlogonNetworkInformation, +- logon, +- mem_ctx, +- &validation_level, +- &validation, +- &authoritative, +- &flags); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- +- status = map_validation_to_info3(mem_ctx, +- validation_level, validation, +- info3); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- +- return NT_STATUS_OK; +-} + + NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds, + struct dcerpc_binding_handle *binding_handle, +diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h +index eaa5b0c..61fed4a 100644 +--- a/source3/rpc_client/cli_netlogon.h ++++ b/source3/rpc_client/cli_netlogon.h +@@ -51,18 +51,6 @@ NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds + const char *password, + const char *workstation, + enum netr_LogonInfoClass logon_type); +-NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, +- TALLOC_CTX *mem_ctx, +- uint32 logon_parameters, +- const char *server, +- const char *username, +- const char *domain, +- const char *workstation, +- const uint8 chal[8], +- uint16_t validation_level, +- DATA_BLOB lm_response, +- DATA_BLOB nt_response, +- struct netr_SamInfo3 **info3); + NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds, + struct dcerpc_binding_handle *binding_handle, + TALLOC_CTX *mem_ctx, +-- +1.9.3 + + +From bdfc02fd5830ed6e2f14aaf90456e572028ada6a Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 16 Sep 2013 19:25:27 +0200 +Subject: [PATCH 212/249] s3:rpc_client: finally remove unused + rpc_pipe_client->netlogon_creds + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit c0761c3eae34175d772476006caf5caad68bd8c6) +--- + source3/rpc_client/cli_pipe.c | 9 --------- + source3/rpc_client/rpc_client.h | 3 --- + 2 files changed, 12 deletions(-) + +diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c +index 31cd7f5..8613a21 100644 +--- a/source3/rpc_client/cli_pipe.c ++++ b/source3/rpc_client/cli_pipe.c +@@ -3097,15 +3097,6 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + return status; + } + +- status = netlogon_creds_cli_context_copy(netlogon_creds, +- rpccli, +- &rpccli->netlogon_creds); +- if (!NT_STATUS_IS_OK(status)) { +- DEBUG(0, ("netlogon_creds_cli_context_copy failed with %s\n", +- nt_errstr(status))); +- TALLOC_FREE(rpccli); +- return status; +- } + + done: + DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s " +diff --git a/source3/rpc_client/rpc_client.h b/source3/rpc_client/rpc_client.h +index 7c4cceb..7c5ff0e 100644 +--- a/source3/rpc_client/rpc_client.h ++++ b/source3/rpc_client/rpc_client.h +@@ -48,9 +48,6 @@ struct rpc_pipe_client { + uint16 max_recv_frag; + + struct pipe_auth_data *auth; +- +- /* The following is only non-null on a netlogon client pipe. */ +- struct netlogon_creds_cli_context *netlogon_creds; + }; + + #endif /* _RPC_CLIENT_H */ +-- +1.9.3 + + +From 710124dca6a97d9148d62bc9aa727568d5284e45 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 17 Oct 2013 19:17:12 +0200 +Subject: [PATCH 213/249] libcli/auth: remove unused + netlogon_creds_cli_context_copy() + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 3d45d4dc3c69557bf1d1fe6d4a880ad74a2a41f1) +--- + libcli/auth/netlogon_creds_cli.c | 47 ---------------------------------------- + libcli/auth/netlogon_creds_cli.h | 4 ---- + 2 files changed, 51 deletions(-) + +diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c +index 6590b21..1724064 100644 +--- a/libcli/auth/netlogon_creds_cli.c ++++ b/libcli/auth/netlogon_creds_cli.c +@@ -488,53 +488,6 @@ NTSTATUS netlogon_creds_cli_context_tmp(const char *client_computer, + return NT_STATUS_OK; + } + +-NTSTATUS netlogon_creds_cli_context_copy( +- const struct netlogon_creds_cli_context *src, +- TALLOC_CTX *mem_ctx, +- struct netlogon_creds_cli_context **_dst) +-{ +- struct netlogon_creds_cli_context *dst; +- +- dst = talloc_zero(mem_ctx, struct netlogon_creds_cli_context); +- if (dst == NULL) { +- return NT_STATUS_NO_MEMORY; +- } +- +- *dst = *src; +- +- dst->client.computer = talloc_strdup(dst, src->client.computer); +- if (dst->client.computer == NULL) { +- TALLOC_FREE(dst); +- return NT_STATUS_NO_MEMORY; +- } +- dst->client.account = talloc_strdup(dst, src->client.account); +- if (dst->client.account == NULL) { +- TALLOC_FREE(dst); +- return NT_STATUS_NO_MEMORY; +- } +- dst->server.computer = talloc_strdup(dst, src->server.computer); +- if (dst->server.computer == NULL) { +- TALLOC_FREE(dst); +- return NT_STATUS_NO_MEMORY; +- } +- dst->server.netbios_domain = talloc_strdup(dst, src->server.netbios_domain); +- if (dst->server.netbios_domain == NULL) { +- TALLOC_FREE(dst); +- return NT_STATUS_NO_MEMORY; +- } +- +- dst->db.key_name = talloc_strdup(dst, src->db.key_name); +- if (dst->db.key_name == NULL) { +- TALLOC_FREE(dst); +- return NT_STATUS_NO_MEMORY; +- } +- +- dst->db.key_data = string_term_tdb_data(dst->db.key_name); +- +- *_dst = dst; +- return NT_STATUS_OK; +-} +- + enum dcerpc_AuthLevel netlogon_creds_cli_auth_level( + struct netlogon_creds_cli_context *context) + { +diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h +index f8f2bef..5bd8bd3 100644 +--- a/libcli/auth/netlogon_creds_cli.h ++++ b/libcli/auth/netlogon_creds_cli.h +@@ -49,10 +49,6 @@ NTSTATUS netlogon_creds_cli_context_tmp(const char *client_computer, + const char *server_netbios_domain, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_cli_context **_context); +-NTSTATUS netlogon_creds_cli_context_copy( +- const struct netlogon_creds_cli_context *src, +- TALLOC_CTX *mem_ctx, +- struct netlogon_creds_cli_context **_dst); + + enum dcerpc_AuthLevel netlogon_creds_cli_auth_level( + struct netlogon_creds_cli_context *context); +-- +1.9.3 + + +From aa3a65e9770bb81e73b30e71b49855b18d012e68 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 6 Dec 2013 11:38:21 +0100 +Subject: [PATCH 214/249] lib/param: add "allow nt4 crypto" option, defaulting + to false + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 87bdc88328568359e51af6615b378ba8dc67f647) +--- + docs-xml/smbdotconf/logon/allownt4crypto.xml | 26 ++++++++++++++++++++++++++ + lib/param/param_functions.c | 1 + + lib/param/param_table.c | 9 +++++++++ + 3 files changed, 36 insertions(+) + create mode 100644 docs-xml/smbdotconf/logon/allownt4crypto.xml + +diff --git a/docs-xml/smbdotconf/logon/allownt4crypto.xml b/docs-xml/smbdotconf/logon/allownt4crypto.xml +new file mode 100644 +index 0000000..4d417c7 +--- /dev/null ++++ b/docs-xml/smbdotconf/logon/allownt4crypto.xml +@@ -0,0 +1,26 @@ ++ ++ ++ This option controls whether the netlogon server (currently ++ only in 'active directory domain controller' mode), will ++ reject clients which does not support NETLOGON_NEG_STRONG_KEYS ++ nor NETLOGON_NEG_SUPPORTS_AES. ++ ++ This option was added with Samba 4.2.0. It may lock out clients ++ which worked fine with Samba versions up to 4.1.x. as the effective default ++ was "yes" there, while it is "no" now. ++ ++ If you have clients without RequireStrongKey = 1 in the registry, ++ you may need to set "allow nt4 crypto = yes", until you have fixed all clients. ++ ++ ++ "allow nt4 crypto = yes" allows weak crypto to be negotiated, maybe via downgrade attacks. ++ ++ This option yields precedence to the 'reject md5 clients' option. ++ ++ ++no ++ +diff --git a/lib/param/param_functions.c b/lib/param/param_functions.c +index 41b137f..bf931c6 100644 +--- a/lib/param/param_functions.c ++++ b/lib/param/param_functions.c +@@ -154,6 +154,7 @@ FN_LOCAL_PARM_BOOL(kernel_change_notify, bKernelChangeNotify) + FN_LOCAL_BOOL(durable_handles, bDurableHandles) + + FN_GLOBAL_BOOL(allow_insecure_widelinks, bAllowInsecureWidelinks) ++FN_GLOBAL_BOOL(allow_nt4_crypto, bAllowNT4Crypto) + FN_GLOBAL_BOOL(allow_trusted_domains, bAllowTrustedDomains) + FN_GLOBAL_BOOL(async_smb_echo_handler, bAsyncSMBEchoHandler) + FN_GLOBAL_BOOL(bind_interfaces_only, bBindInterfacesOnly) +diff --git a/lib/param/param_table.c b/lib/param/param_table.c +index 36e8554..5ef78de 100644 +--- a/lib/param/param_table.c ++++ b/lib/param/param_table.c +@@ -4324,6 +4324,15 @@ static struct parm_struct parm_table[] = { + .special = NULL, + .enum_list = NULL + }, ++ { ++ .label = "allow nt4 crypto", ++ .type = P_BOOL, ++ .p_class = P_GLOBAL, ++ .offset = GLOBAL_VAR(bAllowNT4Crypto), ++ .special = NULL, ++ .enum_list = NULL, ++ .flags = FLAG_ADVANCED, ++ }, + + {N_("TLS options"), P_SEP, P_SEPARATOR}, + +-- +1.9.3 + + +From 51323c0574963065e2edf9346f310f08ce2b59e8 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 6 Dec 2013 11:39:15 +0100 +Subject: [PATCH 215/249] lib/param: add "reject md5 client" option, defaulting + to false + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 807bcb4981fb20a9b97e69f01c3545ea7e85666e) +--- + docs-xml/smbdotconf/logon/rejectmd5clients.xml | 18 ++++++++++++++++++ + lib/param/param_functions.c | 1 + + lib/param/param_table.c | 9 +++++++++ + 3 files changed, 28 insertions(+) + create mode 100644 docs-xml/smbdotconf/logon/rejectmd5clients.xml + +diff --git a/docs-xml/smbdotconf/logon/rejectmd5clients.xml b/docs-xml/smbdotconf/logon/rejectmd5clients.xml +new file mode 100644 +index 0000000..04a5b4d +--- /dev/null ++++ b/docs-xml/smbdotconf/logon/rejectmd5clients.xml +@@ -0,0 +1,18 @@ ++ ++ ++ This option controls whether the netlogon server (currently ++ only in 'active directory domain controller' mode), will ++ reject clients which does not support NETLOGON_NEG_SUPPORTS_AES. ++ ++ You can set this to yes if all domain members support aes. ++ This will prevent downgrade attacks. ++ ++ This option takes precedence to the 'allow nt4 crypto' option. ++ ++ ++no ++ +diff --git a/lib/param/param_functions.c b/lib/param/param_functions.c +index bf931c6..99f0b7f 100644 +--- a/lib/param/param_functions.c ++++ b/lib/param/param_functions.c +@@ -205,6 +205,7 @@ FN_GLOBAL_BOOL(pam_password_change, bPamPasswordChange) + FN_GLOBAL_BOOL(passdb_expand_explicit, bPassdbExpandExplicit) + FN_GLOBAL_BOOL(passwd_chat_debug, bPasswdChatDebug) + FN_GLOBAL_BOOL(registry_shares, bRegistryShares) ++FN_GLOBAL_BOOL(reject_md5_clients, bRejectMD5Clients) + FN_GLOBAL_BOOL(reject_md5_servers, bRejectMD5Servers) + FN_GLOBAL_BOOL(require_strong_key, bRequireStrongKey) + FN_GLOBAL_BOOL(reset_on_zero_vc, bResetOnZeroVC) +diff --git a/lib/param/param_table.c b/lib/param/param_table.c +index 5ef78de..4850324 100644 +--- a/lib/param/param_table.c ++++ b/lib/param/param_table.c +@@ -4333,6 +4333,15 @@ static struct parm_struct parm_table[] = { + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, ++ { ++ .label = "reject md5 clients", ++ .type = P_BOOL, ++ .p_class = P_GLOBAL, ++ .offset = GLOBAL_VAR(bRejectMD5Clients), ++ .special = NULL, ++ .enum_list = NULL, ++ .flags = FLAG_ADVANCED, ++ }, + + {N_("TLS options"), P_SEP, P_SEPARATOR}, + +-- +1.9.3 + + +From 4f3cd17f89ddedaf6e34bc17b220f6ae6993d0c0 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 6 Dec 2013 13:41:43 +0100 +Subject: [PATCH 216/249] selftest/Samba4: use "allow nt4 crypto = yes" for + testing + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 0d4806f9f056c3e37f5aed1ef19e2924aa8f4151) +--- + selftest/target/Samba4.pm | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm +index ac2fdd9..ee6a365 100644 +--- a/selftest/target/Samba4.pm ++++ b/selftest/target/Samba4.pm +@@ -776,6 +776,7 @@ sub provision($$$$$$$$$) + server max protocol = SMB2 + host msdfs = $msdfs + lanman auth = yes ++ allow nt4 crypto = yes + + $extra_smbconf_options + +-- +1.9.3 + + +From 32f88ae5a3d254c6e1b94ea2aaa45febf475af9e Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 23 Dec 2013 10:12:24 +0100 +Subject: [PATCH 217/249] s4:netlogon: correctly calculate the negotiate_flags + +We need to bit-wise AND the client and server flags. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 3b77b804cdc9e7621f026ef9bc8e7059f471348e) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 59 +++++++++++++-------------- + 1 file changed, 28 insertions(+), 31 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index c41cd02..b001cb5 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -120,6 +120,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca + + const char *trust_dom_attrs[] = {"flatname", NULL}; + const char *account_name; ++ uint32_t server_flags = 0; + uint32_t negotiate_flags = 0; + + ZERO_STRUCTP(r->out.return_credentials); +@@ -176,37 +177,33 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca + memcache_delete(global_challenge_table, + SINGLETON_CACHE, challenge_key); + +- negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT | +- NETLOGON_NEG_PERSISTENT_SAMREPL | +- NETLOGON_NEG_ARCFOUR | +- NETLOGON_NEG_PROMOTION_COUNT | +- NETLOGON_NEG_CHANGELOG_BDC | +- NETLOGON_NEG_FULL_SYNC_REPL | +- NETLOGON_NEG_MULTIPLE_SIDS | +- NETLOGON_NEG_REDO | +- NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL | +- NETLOGON_NEG_SEND_PASSWORD_INFO_PDC | +- NETLOGON_NEG_GENERIC_PASSTHROUGH | +- NETLOGON_NEG_CONCURRENT_RPC | +- NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL | +- NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL | +- NETLOGON_NEG_TRANSITIVE_TRUSTS | +- NETLOGON_NEG_DNS_DOMAIN_TRUSTS | +- NETLOGON_NEG_PASSWORD_SET2 | +- NETLOGON_NEG_GETDOMAININFO | +- NETLOGON_NEG_CROSS_FOREST_TRUSTS | +- NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION | +- NETLOGON_NEG_RODC_PASSTHROUGH | +- NETLOGON_NEG_AUTHENTICATED_RPC_LSASS | +- NETLOGON_NEG_AUTHENTICATED_RPC; +- +- if (*r->in.negotiate_flags & NETLOGON_NEG_STRONG_KEYS) { +- negotiate_flags |= NETLOGON_NEG_STRONG_KEYS; +- } +- +- if (*r->in.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { +- negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES; +- } ++ server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT | ++ NETLOGON_NEG_PERSISTENT_SAMREPL | ++ NETLOGON_NEG_ARCFOUR | ++ NETLOGON_NEG_PROMOTION_COUNT | ++ NETLOGON_NEG_CHANGELOG_BDC | ++ NETLOGON_NEG_FULL_SYNC_REPL | ++ NETLOGON_NEG_MULTIPLE_SIDS | ++ NETLOGON_NEG_REDO | ++ NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL | ++ NETLOGON_NEG_SEND_PASSWORD_INFO_PDC | ++ NETLOGON_NEG_GENERIC_PASSTHROUGH | ++ NETLOGON_NEG_CONCURRENT_RPC | ++ NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL | ++ NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL | ++ NETLOGON_NEG_STRONG_KEYS | ++ NETLOGON_NEG_TRANSITIVE_TRUSTS | ++ NETLOGON_NEG_DNS_DOMAIN_TRUSTS | ++ NETLOGON_NEG_PASSWORD_SET2 | ++ NETLOGON_NEG_GETDOMAININFO | ++ NETLOGON_NEG_CROSS_FOREST_TRUSTS | ++ NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION | ++ NETLOGON_NEG_RODC_PASSTHROUGH | ++ NETLOGON_NEG_SUPPORTS_AES | ++ NETLOGON_NEG_AUTHENTICATED_RPC_LSASS | ++ NETLOGON_NEG_AUTHENTICATED_RPC; ++ ++ negotiate_flags = *r->in.negotiate_flags & server_flags; + + /* + * According to Microsoft (see bugid #6099) +-- +1.9.3 + + +From ce8c9b651d9da88a13a8cd0fe02e5f3e2f1f6b51 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 23 Dec 2013 10:10:17 +0100 +Subject: [PATCH 218/249] s4:netlogon: don't generate a debug message for + SEC_CHAN_NULL. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 2e36fbc77dc43f31ec78cdbef23b94bd00d6f565) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index b001cb5..45a7262 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -220,6 +220,8 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca + case SEC_CHAN_BDC: + case SEC_CHAN_RODC: + break; ++ case SEC_CHAN_NULL: ++ return NT_STATUS_INVALID_PARAMETER; + default: + DEBUG(1, ("Client asked for an invalid secure channel type: %d\n", + r->in.secure_channel_type)); +-- +1.9.3 + + +From b4d5ace784d207f8562a4c93b55de415a81cec42 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 6 Dec 2013 12:08:50 +0100 +Subject: [PATCH 219/249] s4:netlogon: implement "allow nt4 crypto" and "reject + md5 clients" features. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett + +Autobuild-User(master): Stefan Metzmacher +Autobuild-Date(master): Tue Jan 7 16:53:31 CET 2014 on sn-devel-104 +(cherry picked from commit 7d2abf520df1ff46d79dfd8ff579c230f2bc3c2a) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index 45a7262..6b57cda 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -122,6 +122,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca + const char *account_name; + uint32_t server_flags = 0; + uint32_t negotiate_flags = 0; ++ bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx); ++ bool reject_des_client = !allow_nt4_crypto; ++ bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx); + + ZERO_STRUCTP(r->out.return_credentials); + *r->out.rid = 0; +@@ -205,6 +208,23 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca + + negotiate_flags = *r->in.negotiate_flags & server_flags; + ++ if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) { ++ reject_des_client = false; ++ } ++ ++ if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { ++ reject_des_client = false; ++ reject_md5_client = false; ++ } ++ ++ if (reject_des_client || reject_md5_client) { ++ /* ++ * Here we match Windows 2012 and return no flags. ++ */ ++ *r->out.negotiate_flags = 0; ++ return NT_STATUS_DOWNGRADE_DETECTED; ++ } ++ + /* + * According to Microsoft (see bugid #6099) + * Windows 7 looks at the negotiate_flags +-- +1.9.3 + + +From ff28e17cdcbe8e1ec4a275d80b3e749da4920c6d Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 8 Jan 2014 12:04:22 +0100 +Subject: [PATCH 220/249] libcli/auth: fix usage of an uninitialized variable + in netlogon_creds_cli_check_caps() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If status is RPC_PROCNUM_OUT_OF_RANGE, result might be uninitialized. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andreas Schneider +Reviewed-by: Günther Deschner +(cherry picked from commit 0e62f3279525ea864590f713f334f4dc5f5d3a32) +--- + libcli/auth/netlogon_creds_cli.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c +index 1724064..51b30a1 100644 +--- a/libcli/auth/netlogon_creds_cli.c ++++ b/libcli/auth/netlogon_creds_cli.c +@@ -1390,7 +1390,7 @@ struct netlogon_creds_cli_check_state { + }; + + static void netlogon_creds_cli_check_cleanup(struct tevent_req *req, +- NTSTATUS status); ++ NTSTATUS status); + static void netlogon_creds_cli_check_locked(struct tevent_req *subreq); + + struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx, +@@ -1582,7 +1582,7 @@ static void netlogon_creds_cli_check_caps(struct tevent_req *subreq) + * with the next request as the sequence number processing + * gets out of sync. + */ +- netlogon_creds_cli_check_cleanup(req, result); ++ netlogon_creds_cli_check_cleanup(req, status); + tevent_req_done(req); + return; + } +-- +1.9.3 + + +From d4902881482eeecf5a219342b3862ac0fbb7b7a9 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 17 Jan 2014 14:00:27 +0100 +Subject: [PATCH 221/249] libcli/auth: add netlogon_creds_cli_set_global_db() + +This can be used to inject a db_context from dbwrap_ctdb. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit ece3ba10a16138a75b207a0cf9fe299759253d99) +--- + libcli/auth/netlogon_creds_cli.c | 10 ++++++++++ + libcli/auth/netlogon_creds_cli.h | 2 ++ + 2 files changed, 12 insertions(+) + +diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c +index 51b30a1..37bdf74 100644 +--- a/libcli/auth/netlogon_creds_cli.c ++++ b/libcli/auth/netlogon_creds_cli.c +@@ -199,6 +199,16 @@ static NTSTATUS netlogon_creds_cli_context_common( + + static struct db_context *netlogon_creds_cli_global_db; + ++NTSTATUS netlogon_creds_cli_set_global_db(struct db_context **db) ++{ ++ if (netlogon_creds_cli_global_db != NULL) { ++ return NT_STATUS_INVALID_PARAMETER_MIX; ++ } ++ ++ netlogon_creds_cli_global_db = talloc_move(talloc_autofree_context(), db); ++ return NT_STATUS_OK; ++} ++ + NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx) + { + char *fname; +diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h +index 5bd8bd3..90d0182 100644 +--- a/libcli/auth/netlogon_creds_cli.h ++++ b/libcli/auth/netlogon_creds_cli.h +@@ -28,7 +28,9 @@ + struct netlogon_creds_cli_context; + struct messaging_context; + struct dcerpc_binding_handle; ++struct db_context; + ++NTSTATUS netlogon_creds_cli_set_global_db(struct db_context **db); + NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx); + + NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, +-- +1.9.3 + + +From 80407a74da35cac64bef252698a2477787f0997d Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 17 Jan 2014 14:07:37 +0100 +Subject: [PATCH 222/249] s3:rpc_client: use db_open() to open + "netlogon_creds_cli.tdb" + +This uses dbwrap_ctdb if running in a cluster. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 8cf4eff201aa9e1ba8127311bcfc2a357fb4ef03) +--- + source3/rpc_client/cli_netlogon.c | 38 ++++++++++++++++++++++++++++++++++++-- + 1 file changed, 36 insertions(+), 2 deletions(-) + +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index ca2d9bf..b7b490f 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -21,6 +21,7 @@ + */ + + #include "includes.h" ++#include "system/filesys.h" + #include "libsmb/libsmb.h" + #include "rpc_client/rpc_client.h" + #include "rpc_client/cli_pipe.h" +@@ -34,26 +35,53 @@ + #include "../libcli/security/security.h" + #include "lib/param/param.h" + #include "libcli/smb/smbXcli_base.h" ++#include "dbwrap/dbwrap.h" ++#include "dbwrap/dbwrap_open.h" ++#include "util_tdb.h" + + + NTSTATUS rpccli_pre_open_netlogon_creds(void) + { +- TALLOC_CTX *frame = talloc_stackframe(); ++ static bool already_open = false; ++ TALLOC_CTX *frame; + struct loadparm_context *lp_ctx; ++ char *fname; ++ struct db_context *global_db; + NTSTATUS status; + ++ if (already_open) { ++ return NT_STATUS_OK; ++ } ++ ++ frame = talloc_stackframe(); ++ + lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); + if (lp_ctx == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + +- status = netlogon_creds_cli_open_global_db(lp_ctx); ++ fname = lpcfg_private_db_path(frame, lp_ctx, "netlogon_creds_cli"); ++ if (fname == NULL) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ global_db = db_open(talloc_autofree_context(), fname, ++ 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, ++ O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_2); ++ if (global_db == NULL) { ++ TALLOC_FREE(frame); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ status = netlogon_creds_cli_set_global_db(&global_db); + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + ++ already_open = true; + return NT_STATUS_OK; + } + +@@ -69,6 +97,12 @@ NTSTATUS rpccli_create_netlogon_creds(const char *server_computer, + struct loadparm_context *lp_ctx; + NTSTATUS status; + ++ status = rpccli_pre_open_netlogon_creds(); ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); ++ return status; ++ } ++ + lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); + if (lp_ctx == NULL) { + TALLOC_FREE(frame); +-- +1.9.3 + + +From 2ed3041405f5808031f2d5fd0e42f48246d22b7b Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 17 Jan 2014 14:08:59 +0100 +Subject: [PATCH 223/249] libcli/auth: don't alter the computer_name in cluster + mode. + +This breaks NTLMv2 authentication. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 387ed2e15df085274f72cebda341040a1e767a4b) +--- + libcli/auth/netlogon_creds_cli.c | 22 +++------------------- + 1 file changed, 3 insertions(+), 19 deletions(-) + +diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c +index 37bdf74..88893ad 100644 +--- a/libcli/auth/netlogon_creds_cli.c ++++ b/libcli/auth/netlogon_creds_cli.c +@@ -261,28 +261,12 @@ NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, + bool seal_secure_channel = true; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + bool neutralize_nt4_emulation = false; +- struct server_id self = { +- .vnn = NONCLUSTER_VNN, +- .unique_id = SERVERID_UNIQUE_ID_NOT_TO_VERIFY, +- }; +- +- if (msg_ctx != NULL) { +- self = messaging_server_id(msg_ctx); +- } + + *_context = NULL; + +- if (self.vnn != NONCLUSTER_VNN) { +- client_computer = talloc_asprintf(frame, +- "%s_cluster_vnn_%u", +- lpcfg_netbios_name(lp_ctx), +- (unsigned)self.vnn); +- if (client_computer == NULL) { +- TALLOC_FREE(frame); +- return NT_STATUS_NO_MEMORY; +- } +- } else { +- client_computer = lpcfg_netbios_name(lp_ctx); ++ client_computer = lpcfg_netbios_name(lp_ctx); ++ if (strlen(client_computer) > 15) { ++ return NT_STATUS_INVALID_PARAMETER_MIX; + } + + /* +-- +1.9.3 + + +From 8257c3a5d6e8319578d224e544242da81b043a54 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 10 Jan 2014 13:13:40 +0100 +Subject: [PATCH 224/249] libcli/auth: reject computer_name longer than 15 + chars + +This matches Windows, it seems they use a fixed size field to store +netlogon_creds_CredentialState. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit b8fdeb8ca7ce362058bb86a4e58b34fb6340867e) +--- + libcli/auth/schannel_state_tdb.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/libcli/auth/schannel_state_tdb.c b/libcli/auth/schannel_state_tdb.c +index 8f9c1f0..b91e242 100644 +--- a/libcli/auth/schannel_state_tdb.c ++++ b/libcli/auth/schannel_state_tdb.c +@@ -78,6 +78,14 @@ NTSTATUS schannel_store_session_key_tdb(struct db_context *db_sc, + char *name_upper; + NTSTATUS status; + ++ if (strlen(creds->computer_name) > 15) { ++ /* ++ * We may want to check for a completely ++ * valid netbios name. ++ */ ++ return STATUS_BUFFER_OVERFLOW; ++ } ++ + name_upper = strupper_talloc(mem_ctx, creds->computer_name); + if (!name_upper) { + return NT_STATUS_NO_MEMORY; +-- +1.9.3 + + +From d6af8ed76f728621a8ba7515cf1180d6654c8d83 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sat, 11 Jan 2014 17:13:04 +0100 +Subject: [PATCH 225/249] s3:rpc_server/netlogon: return a zero + return_authenticator on error + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit dcc2c8362df9af088613722ebd8a6261fb098a5c) +--- + source3/rpc_server/netlogon/srv_netlog_nt.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c +index 09857b6..7bb9dd6 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -1020,6 +1020,7 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, + talloc_unlink(p->mem_ctx, lp_ctx); + + if (!NT_STATUS_IS_OK(status)) { ++ ZERO_STRUCTP(r->out.return_credentials); + goto out; + } + +-- +1.9.3 + + +From be06629b25f8340ac54a9e674e6a5da1eb01e733 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Sat, 11 Jan 2014 17:13:04 +0100 +Subject: [PATCH 226/249] s4:rpc_server/netlogon: return a zero + return_authenticator and rid on error + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 25fb73f2821821630dde4cc263794e754ca03d68) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index 6b57cda..afa15d8 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -348,9 +348,6 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca + return NT_STATUS_INTERNAL_ERROR; + } + +- *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0], +- "objectSid", 0); +- + mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd"); + if (mach_pwd == NULL) { + return NT_STATUS_ACCESS_DENIED; +@@ -383,8 +380,15 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca + nt_status = schannel_save_creds_state(mem_ctx, + dce_call->conn->dce_ctx->lp_ctx, + creds); ++ if (!NT_STATUS_IS_OK(nt_status)) { ++ ZERO_STRUCTP(r->out.return_credentials); ++ return nt_status; ++ } + +- return nt_status; ++ *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0], ++ "objectSid", 0); ++ ++ return NT_STATUS_OK; + } + + static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, +-- +1.9.3 + + +From f5fe58d49fc66867db743393a92e1cd8e4cb293b Mon Sep 17 00:00:00 2001 +From: Michael Adam +Date: Wed, 29 Jan 2014 16:58:37 +0100 +Subject: [PATCH 227/249] dbwrap_tool: remove the short form "-p" of + "--persistent" + +Signed-off-by: Michael Adam +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 6dd1008c4e8b0b798d589959021c9b578db74ff4) +--- + source3/utils/dbwrap_tool.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source3/utils/dbwrap_tool.c b/source3/utils/dbwrap_tool.c +index 79b40d2..406e89e 100644 +--- a/source3/utils/dbwrap_tool.c ++++ b/source3/utils/dbwrap_tool.c +@@ -420,7 +420,7 @@ int main(int argc, const char **argv) + struct poptOption popt_options[] = { + POPT_AUTOHELP + POPT_COMMON_SAMBA +- { "persistent", 'p', POPT_ARG_NONE, &persistent, 0, "treat the database as persistent", NULL }, ++ { "persistent", 0, POPT_ARG_NONE, &persistent, 0, "treat the database as persistent", NULL }, + POPT_TABLEEND + }; + int opt; +-- +1.9.3 + + +From 209b5ec86620f8caadcc714db0cbec4789db0377 Mon Sep 17 00:00:00 2001 +From: Michael Adam +Date: Thu, 30 Jan 2014 10:33:00 +0100 +Subject: [PATCH 228/249] docs: remove short form "-p" of --persistent from + dbwrap_tool manpage + +Signed-off-by: Michael Adam +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 6f748fef652bbea3c8dbbbfb96b95270e6f1dcfc) +--- + docs-xml/manpages/dbwrap_tool.1.xml | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/docs-xml/manpages/dbwrap_tool.1.xml b/docs-xml/manpages/dbwrap_tool.1.xml +index 074d819..94ae281 100644 +--- a/docs-xml/manpages/dbwrap_tool.1.xml ++++ b/docs-xml/manpages/dbwrap_tool.1.xml +@@ -19,7 +19,7 @@ + + + dbwrap_tool +- -p|--persistent ++ --persistent + -d <debug level> + -s <config file> + -l <log file base> +@@ -70,7 +70,7 @@ + + + +- -p|--persistent ++ --persistent + Open the database as a persistent database. + If this option is not specified, the database is opened as + non-persistent. +-- +1.9.3 + + +From f3b8b74ff6d74fe9a0047256074e21c3363b112f Mon Sep 17 00:00:00 2001 +From: Michael Adam +Date: Thu, 30 Jan 2014 10:29:49 +0100 +Subject: [PATCH 229/249] dbwrap_tool: add option "--non-persistent" and force + excatly one of "--[non-]persistent" + +We want to force users of dbwrap_tool to explicitly specify +persistent or non-persistent. Otherwise, one could easily +by accident wipe a whole database that is actually persistent +but not currently opened by a samba process, just by openeing +the DB with the default non-persistent mode... + +Signed-off-by: Michael Adam +Reviewed-by: Stefan Metzmacher +(cherry picked from commit c3f93271ef447f9f16cd3002307c630c5f149f5a) +--- + source3/utils/dbwrap_tool.c | 23 ++++++++++++++++++----- + 1 file changed, 18 insertions(+), 5 deletions(-) + +diff --git a/source3/utils/dbwrap_tool.c b/source3/utils/dbwrap_tool.c +index 406e89e..ffca6b6 100644 +--- a/source3/utils/dbwrap_tool.c ++++ b/source3/utils/dbwrap_tool.c +@@ -411,6 +411,7 @@ int main(int argc, const char **argv) + enum dbwrap_type type; + const char *valuestr = "0"; + int persistent = 0; ++ int non_persistent = 0; + int tdb_flags = TDB_DEFAULT; + + TALLOC_CTX *mem_ctx = talloc_stackframe(); +@@ -420,7 +421,13 @@ int main(int argc, const char **argv) + struct poptOption popt_options[] = { + POPT_AUTOHELP + POPT_COMMON_SAMBA +- { "persistent", 0, POPT_ARG_NONE, &persistent, 0, "treat the database as persistent", NULL }, ++ { "non-persistent", 0, POPT_ARG_NONE, &non_persistent, 0, ++ "treat the database as non-persistent " ++ "(CAVEAT: This mode might wipe your database!)", ++ NULL }, ++ { "persistent", 0, POPT_ARG_NONE, &persistent, 0, ++ "treat the database as persistent", ++ NULL }, + POPT_TABLEEND + }; + int opt; +@@ -463,6 +470,16 @@ int main(int argc, const char **argv) + goto done; + } + ++ if ((persistent == 0 && non_persistent == 0) || ++ (persistent == 1 && non_persistent == 1)) ++ { ++ d_fprintf(stderr, "ERROR: you must specify exactly one " ++ "of --persistent and --non-persistent\n"); ++ goto done; ++ } else if (non_persistent == 1) { ++ tdb_flags |= TDB_CLEAR_IF_FIRST; ++ } ++ + dbname = extra_argv[0]; + opname = extra_argv[1]; + +@@ -563,10 +580,6 @@ int main(int argc, const char **argv) + goto done; + } + +- if (persistent == 0) { +- tdb_flags |= TDB_CLEAR_IF_FIRST; +- } +- + switch (op) { + case OP_FETCH: + case OP_STORE: +-- +1.9.3 + + +From 7209e84e02c722365bec4e2a473c24217cbeb22b Mon Sep 17 00:00:00 2001 +From: Michael Adam +Date: Thu, 30 Jan 2014 10:36:46 +0100 +Subject: [PATCH 230/249] docs: document new --non-persistent option to + dbwrap_tool + +Signed-off-by: Michael Adam +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 1e3b352f799038ec25437db53e051dadb9d97c95) +--- + docs-xml/manpages/dbwrap_tool.1.xml | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/docs-xml/manpages/dbwrap_tool.1.xml b/docs-xml/manpages/dbwrap_tool.1.xml +index 94ae281..ff0e478 100644 +--- a/docs-xml/manpages/dbwrap_tool.1.xml ++++ b/docs-xml/manpages/dbwrap_tool.1.xml +@@ -20,6 +20,7 @@ + + dbwrap_tool + --persistent ++ --non-persistent + -d <debug level> + -s <config file> + -l <log file base> +@@ -72,8 +73,23 @@ + + --persistent + Open the database as a persistent database. +- If this option is not specified, the database is opened as +- non-persistent. ++ ++ ++ Exactly one of --persistent and --non-persistent must be ++ specified. ++ ++ ++ ++ --non-persistent ++ Open the database as a non-persistent database. ++ ++ ++ Caveat: opening a database as non-persistent when there ++ is currently no other opener will wipe the database. ++ ++ ++ Exactly one of --persistent and --non-persistent must be ++ specified. + + + &popt.common.samba.client; +-- +1.9.3 + + +From accf5a617055c161540384fdfe195ad9c43cd048 Mon Sep 17 00:00:00 2001 +From: Michael Adam +Date: Thu, 30 Jan 2014 10:47:15 +0100 +Subject: [PATCH 231/249] docs: remove extra spaces in synopsis of dbwrap_tool + +Signed-off-by: Michael Adam +Reviewed-by: Stefan Metzmacher +(cherry picked from commit e93f052e37e736e5776fe7f7c7d246f9ecc4b4c8) +--- + docs-xml/manpages/dbwrap_tool.1.xml | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/docs-xml/manpages/dbwrap_tool.1.xml b/docs-xml/manpages/dbwrap_tool.1.xml +index ff0e478..68a88df 100644 +--- a/docs-xml/manpages/dbwrap_tool.1.xml ++++ b/docs-xml/manpages/dbwrap_tool.1.xml +@@ -30,9 +30,7 @@ + <operation> + <key> + <type> +- <value> +- +- ++ <value> + + + +-- +1.9.3 + + +From 0e193981caa2ad9458e758a46076664d2efdb70e Mon Sep 17 00:00:00 2001 +From: Michael Adam +Date: Fri, 24 Jan 2014 00:09:50 +0100 +Subject: [PATCH 232/249] smbd:smb2: fix durable reconnect: set fsp->fnum from + the smbXsrv_open->local_id + +Originally, fsp->fnum was left at the INVALID fnum value. + +Signed-off-by: Michael Adam +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 6b2d67a345e90306f0d35402d0f4e3067a014057) +--- + source3/smbd/durable.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/source3/smbd/durable.c b/source3/smbd/durable.c +index c3d0a6f..471c5b9 100644 +--- a/source3/smbd/durable.c ++++ b/source3/smbd/durable.c +@@ -703,6 +703,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn, + fsp->share_access = e->share_access; + fsp->can_read = ((fsp->access_mask & (FILE_READ_DATA)) != 0); + fsp->can_write = ((fsp->access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA)) != 0); ++ fsp->fnum = op->local_id; + + /* + * TODO: +-- +1.9.3 + + +From dbc1d6f8479cf84c714c4ed6b69df2a3673d0a46 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 24 Dec 2013 09:00:01 +0100 +Subject: [PATCH 233/249] s3:smbd: skip empty records in smbXsrv_open_cleanup() + +This should avoid scary ndr_pull errors, if there's +a cleanup race. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Michael Adam + +Autobuild-User(master): Stefan Metzmacher +Autobuild-Date(master): Thu Jan 30 18:49:37 CET 2014 on sn-devel-104 +(cherry picked from commit 0b23345676c6f02d5bb1a327174d8456705ec0c7) +--- + source3/smbd/smbXsrv_open.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c +index 27dd50c..29c172c 100644 +--- a/source3/smbd/smbXsrv_open.c ++++ b/source3/smbd/smbXsrv_open.c +@@ -1380,6 +1380,7 @@ NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id) + struct smbXsrv_open_global0 *op = NULL; + uint8_t key_buf[SMBXSRV_OPEN_GLOBAL_TDB_KEY_SIZE]; + TDB_DATA key; ++ TDB_DATA val; + struct db_record *rec; + bool delete_open = false; + uint32_t global_id = persistent_id & UINT32_MAX; +@@ -1395,6 +1396,14 @@ NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id) + goto done; + } + ++ val = dbwrap_record_get_value(rec); ++ if (val.dsize == 0) { ++ DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " ++ "empty record in %s, skipping...\n", ++ global_id, dbwrap_name(smbXsrv_open_global_db_ctx))); ++ goto done; ++ } ++ + status = smbXsrv_open_global_parse_record(talloc_tos(), rec, &op); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] " +-- +1.9.3 + + +From 838d9da4a7fe6c90ba7cae6563f0af5d8b6cf6d5 Mon Sep 17 00:00:00 2001 +From: Michael Adam +Date: Mon, 27 Jan 2014 13:38:51 +0100 +Subject: [PATCH 234/249] dbwrap: add flags DBWRAP_FLAG_NONE + +This is in preparation of adding a dbwrap_flags argument to db_open +and firends. + +Signed-off-by: Michael Adam +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 229dcfd3501e4743d5d9aea5c9f7a97d7612a499) +--- + lib/dbwrap/dbwrap.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/lib/dbwrap/dbwrap.h b/lib/dbwrap/dbwrap.h +index 8bf3286..4064ba2 100644 +--- a/lib/dbwrap/dbwrap.h ++++ b/lib/dbwrap/dbwrap.h +@@ -32,6 +32,8 @@ enum dbwrap_lock_order { + }; + #define DBWRAP_LOCK_ORDER_MAX DBWRAP_LOCK_ORDER_3 + ++#define DBWRAP_FLAG_NONE 0x0000000000000000ULL ++ + /* The following definitions come from lib/dbwrap.c */ + + TDB_DATA dbwrap_record_get_key(const struct db_record *rec); +-- +1.9.3 + + +From 868d8e2fa389ab0c697e9a70a4373908aa7df80b Mon Sep 17 00:00:00 2001 +From: Michael Adam +Date: Mon, 27 Jan 2014 14:49:12 +0100 +Subject: [PATCH 235/249] dbwrap: add a dbwrap_flags argument to db_open() + +This is in preparation to support handing flags to backends, +in particular activating read only record support for ctdb +databases. For a start, this does nothing but adding the +parameter, and all databases use DBWRAP_FLAG_NONE. + +Signed-off-by: Michael Adam +(similar to commit cf0cb0add9ed47b8974272237fee0e1a4ba7bf68) +--- + source3/groupdb/mapping_tdb.c | 2 +- + source3/lib/dbwrap/dbwrap_open.c | 3 ++- + source3/lib/dbwrap/dbwrap_open.h | 3 ++- + source3/lib/dbwrap/dbwrap_watch.c | 3 ++- + source3/lib/g_lock.c | 3 ++- + source3/lib/serverid.c | 3 ++- + source3/lib/sharesec.c | 2 +- + source3/locking/brlock.c | 2 +- + source3/locking/share_mode_lock.c | 2 +- + source3/modules/vfs_acl_tdb.c | 2 +- + source3/modules/vfs_xattr_tdb.c | 2 +- + source3/passdb/account_pol.c | 4 ++-- + source3/passdb/pdb_tdb.c | 6 +++--- + source3/passdb/secrets.c | 2 +- + source3/printing/printer_list.c | 3 ++- + source3/registry/reg_backend_db.c | 6 +++--- + source3/rpc_client/cli_netlogon.c | 3 ++- + source3/smbd/notify_internal.c | 2 +- + source3/smbd/smbXsrv_open.c | 3 ++- + source3/smbd/smbXsrv_session.c | 3 ++- + source3/smbd/smbXsrv_tcon.c | 3 ++- + source3/smbd/smbXsrv_version.c | 3 ++- + source3/torture/test_dbwrap_watch.c | 3 ++- + source3/torture/test_idmap_tdb_common.c | 2 +- + source3/torture/torture.c | 3 ++- + source3/utils/dbwrap_tool.c | 2 +- + source3/utils/dbwrap_torture.c | 2 +- + source3/utils/net_idmap.c | 6 +++--- + source3/utils/net_idmap_check.c | 2 +- + source3/utils/net_registry_check.c | 4 ++-- + source3/utils/status.c | 2 +- + source3/winbindd/idmap_autorid.c | 2 +- + source3/winbindd/idmap_tdb.c | 2 +- + source3/winbindd/idmap_tdb2.c | 2 +- + 34 files changed, 55 insertions(+), 42 deletions(-) + +diff --git a/source3/groupdb/mapping_tdb.c b/source3/groupdb/mapping_tdb.c +index 088874f..0863187 100644 +--- a/source3/groupdb/mapping_tdb.c ++++ b/source3/groupdb/mapping_tdb.c +@@ -54,7 +54,7 @@ static bool init_group_mapping(void) + + db = db_open(NULL, state_path("group_mapping.tdb"), 0, + TDB_DEFAULT, O_RDWR|O_CREAT, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (db == NULL) { + DEBUG(0, ("Failed to open group mapping database: %s\n", + strerror(errno))); +diff --git a/source3/lib/dbwrap/dbwrap_open.c b/source3/lib/dbwrap/dbwrap_open.c +index 515b4bf..6c9280c 100644 +--- a/source3/lib/dbwrap/dbwrap_open.c ++++ b/source3/lib/dbwrap/dbwrap_open.c +@@ -60,7 +60,8 @@ struct db_context *db_open(TALLOC_CTX *mem_ctx, + const char *name, + int hash_size, int tdb_flags, + int open_flags, mode_t mode, +- enum dbwrap_lock_order lock_order) ++ enum dbwrap_lock_order lock_order, ++ uint64_t dbwrap_flags) + { + struct db_context *result = NULL; + #ifdef CLUSTER_SUPPORT +diff --git a/source3/lib/dbwrap/dbwrap_open.h b/source3/lib/dbwrap/dbwrap_open.h +index 51c7dfd..d14794e 100644 +--- a/source3/lib/dbwrap/dbwrap_open.h ++++ b/source3/lib/dbwrap/dbwrap_open.h +@@ -39,6 +39,7 @@ struct db_context *db_open(TALLOC_CTX *mem_ctx, + const char *name, + int hash_size, int tdb_flags, + int open_flags, mode_t mode, +- enum dbwrap_lock_order lock_order); ++ enum dbwrap_lock_order lock_order, ++ uint64_t dbwrap_flags); + + #endif /* __DBWRAP_OPEN_H__ */ +diff --git a/source3/lib/dbwrap/dbwrap_watch.c b/source3/lib/dbwrap/dbwrap_watch.c +index 7bdcd99..5f3d17d 100644 +--- a/source3/lib/dbwrap/dbwrap_watch.c ++++ b/source3/lib/dbwrap/dbwrap_watch.c +@@ -34,7 +34,8 @@ static struct db_context *dbwrap_record_watchers_db(void) + watchers_db = db_open( + NULL, lock_path("dbwrap_watchers.tdb"), 0, + TDB_CLEAR_IF_FIRST | TDB_INCOMPATIBLE_HASH, +- O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_3); ++ O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_3, ++ DBWRAP_FLAG_NONE); + } + return watchers_db; + } +diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c +index 8c7a6c2..6813f06 100644 +--- a/source3/lib/g_lock.c ++++ b/source3/lib/g_lock.c +@@ -61,7 +61,8 @@ struct g_lock_ctx *g_lock_ctx_init(TALLOC_CTX *mem_ctx, + result->db = db_open(result, lock_path("g_lock.tdb"), 0, + TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, + O_RDWR|O_CREAT, 0600, +- DBWRAP_LOCK_ORDER_2); ++ DBWRAP_LOCK_ORDER_2, ++ DBWRAP_FLAG_NONE); + if (result->db == NULL) { + DEBUG(1, ("g_lock_init: Could not open g_lock.tdb\n")); + TALLOC_FREE(result); +diff --git a/source3/lib/serverid.c b/source3/lib/serverid.c +index cb49520..4259887 100644 +--- a/source3/lib/serverid.c ++++ b/source3/lib/serverid.c +@@ -77,7 +77,8 @@ static struct db_context *serverid_db(void) + } + db = db_open(NULL, lock_path("serverid.tdb"), 0, + TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, +- O_RDWR|O_CREAT, 0644, DBWRAP_LOCK_ORDER_2); ++ O_RDWR|O_CREAT, 0644, DBWRAP_LOCK_ORDER_2, ++ DBWRAP_FLAG_NONE); + return db; + } + +diff --git a/source3/lib/sharesec.c b/source3/lib/sharesec.c +index c7a8e51..095c851 100644 +--- a/source3/lib/sharesec.c ++++ b/source3/lib/sharesec.c +@@ -149,7 +149,7 @@ bool share_info_db_init(void) + + share_db = db_open(NULL, state_path("share_info.tdb"), 0, + TDB_DEFAULT, O_RDWR|O_CREAT, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (share_db == NULL) { + DEBUG(0,("Failed to open share info database %s (%s)\n", + state_path("share_info.tdb"), strerror(errno) )); +diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c +index 5d683dd..d88aa2d 100644 +--- a/source3/locking/brlock.c ++++ b/source3/locking/brlock.c +@@ -292,7 +292,7 @@ void brl_init(bool read_only) + brlock_db = db_open(NULL, lock_path("brlock.tdb"), + lp_open_files_db_hash_size(), tdb_flags, + read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644, +- DBWRAP_LOCK_ORDER_2); ++ DBWRAP_LOCK_ORDER_2, DBWRAP_FLAG_NONE); + if (!brlock_db) { + DEBUG(0,("Failed to open byte range locking database %s\n", + lock_path("brlock.tdb"))); +diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c +index 4f049bd..22f8d9a 100644 +--- a/source3/locking/share_mode_lock.c ++++ b/source3/locking/share_mode_lock.c +@@ -67,7 +67,7 @@ static bool locking_init_internal(bool read_only) + lp_open_files_db_hash_size(), + TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, + read_only?O_RDONLY:O_RDWR|O_CREAT, 0644, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + + if (!lock_db) { + DEBUG(0,("ERROR: Failed to initialise locking database\n")); +diff --git a/source3/modules/vfs_acl_tdb.c b/source3/modules/vfs_acl_tdb.c +index 80839e3..8ee4bd5 100644 +--- a/source3/modules/vfs_acl_tdb.c ++++ b/source3/modules/vfs_acl_tdb.c +@@ -60,7 +60,7 @@ static bool acl_tdb_init(void) + + become_root(); + acl_db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + unbecome_root(); + + if (acl_db == NULL) { +diff --git a/source3/modules/vfs_xattr_tdb.c b/source3/modules/vfs_xattr_tdb.c +index 43456cf..63a12fd 100644 +--- a/source3/modules/vfs_xattr_tdb.c ++++ b/source3/modules/vfs_xattr_tdb.c +@@ -320,7 +320,7 @@ static bool xattr_tdb_init(int snum, TALLOC_CTX *mem_ctx, struct db_context **p_ + + become_root(); + db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600, +- DBWRAP_LOCK_ORDER_2); ++ DBWRAP_LOCK_ORDER_2, DBWRAP_FLAG_NONE); + unbecome_root(); + + if (db == NULL) { +diff --git a/source3/passdb/account_pol.c b/source3/passdb/account_pol.c +index c94df29..09a2d20 100644 +--- a/source3/passdb/account_pol.c ++++ b/source3/passdb/account_pol.c +@@ -220,13 +220,13 @@ bool init_account_policy(void) + } + + db = db_open(NULL, state_path("account_policy.tdb"), 0, TDB_DEFAULT, +- O_RDWR, 0600, DBWRAP_LOCK_ORDER_1); ++ O_RDWR, 0600, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + + if (db == NULL) { /* the account policies files does not exist or open + * failed, try to create a new one */ + db = db_open(NULL, state_path("account_policy.tdb"), 0, + TDB_DEFAULT, O_RDWR|O_CREAT, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (db == NULL) { + DEBUG(0,("Failed to open account policy database\n")); + return False; +diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c +index f256e6c..162083f 100644 +--- a/source3/passdb/pdb_tdb.c ++++ b/source3/passdb/pdb_tdb.c +@@ -226,7 +226,7 @@ static bool tdbsam_convert_backup(const char *dbname, struct db_context **pp_db) + + tmp_db = db_open(NULL, tmp_fname, 0, + TDB_DEFAULT, O_CREAT|O_RDWR, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (tmp_db == NULL) { + DEBUG(0, ("tdbsam_convert_backup: Failed to create backup TDB passwd " + "[%s]\n", tmp_fname)); +@@ -293,7 +293,7 @@ static bool tdbsam_convert_backup(const char *dbname, struct db_context **pp_db) + + orig_db = db_open(NULL, dbname, 0, + TDB_DEFAULT, O_CREAT|O_RDWR, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (orig_db == NULL) { + DEBUG(0, ("tdbsam_convert_backup: Failed to re-open " + "converted passdb TDB [%s]\n", dbname)); +@@ -444,7 +444,7 @@ static bool tdbsam_open( const char *name ) + /* Try to open tdb passwd. Create a new one if necessary */ + + db_sam = db_open(NULL, name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (db_sam == NULL) { + DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd " + "[%s]\n", name)); +diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c +index 548b030..bff9a0d 100644 +--- a/source3/passdb/secrets.c ++++ b/source3/passdb/secrets.c +@@ -79,7 +79,7 @@ bool secrets_init_path(const char *private_dir, bool use_ntdb) + + db_ctx = db_open(NULL, fname, 0, + TDB_DEFAULT, O_RDWR|O_CREAT, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + + if (db_ctx == NULL) { + DEBUG(0,("Failed to open %s\n", fname)); +diff --git a/source3/printing/printer_list.c b/source3/printing/printer_list.c +index 815f89f..9a9fa0b 100644 +--- a/source3/printing/printer_list.c ++++ b/source3/printing/printer_list.c +@@ -40,7 +40,8 @@ static struct db_context *get_printer_list_db(void) + } + db = db_open(NULL, PL_DB_NAME(), 0, + TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, +- O_RDWR|O_CREAT, 0644, DBWRAP_LOCK_ORDER_1); ++ O_RDWR|O_CREAT, 0644, DBWRAP_LOCK_ORDER_1, ++ DBWRAP_FLAG_NONE); + return db; + } + +diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c +index 3e561eb..fdaf576 100644 +--- a/source3/registry/reg_backend_db.c ++++ b/source3/registry/reg_backend_db.c +@@ -732,11 +732,11 @@ WERROR regdb_init(void) + + regdb = db_open(NULL, state_path("registry.tdb"), 0, + REG_TDB_FLAGS, O_RDWR, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (!regdb) { + regdb = db_open(NULL, state_path("registry.tdb"), 0, + REG_TDB_FLAGS, O_RDWR|O_CREAT, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (!regdb) { + werr = ntstatus_to_werror(map_nt_error_from_unix(errno)); + DEBUG(1,("regdb_init: Failed to open registry %s (%s)\n", +@@ -852,7 +852,7 @@ WERROR regdb_open( void ) + + regdb = db_open(NULL, state_path("registry.tdb"), 0, + REG_TDB_FLAGS, O_RDWR, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if ( !regdb ) { + result = ntstatus_to_werror( map_nt_error_from_unix( errno ) ); + DEBUG(0,("regdb_open: Failed to open %s! (%s)\n", +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index b7b490f..9e3c1bd 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -69,7 +69,8 @@ NTSTATUS rpccli_pre_open_netlogon_creds(void) + + global_db = db_open(talloc_autofree_context(), fname, + 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, +- O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_2); ++ O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_2, ++ DBWRAP_FLAG_NONE); + if (global_db == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; +diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c +index 2dc8674..67d8774 100644 +--- a/source3/smbd/notify_internal.c ++++ b/source3/smbd/notify_internal.c +@@ -145,7 +145,7 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, + notify->db_index = db_open( + notify, lock_path("notify_index.tdb"), + 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, +- O_RDWR|O_CREAT, 0644, DBWRAP_LOCK_ORDER_3); ++ O_RDWR|O_CREAT, 0644, DBWRAP_LOCK_ORDER_3, DBWRAP_FLAG_NONE); + if (notify->db_index == NULL) { + goto fail; + } +diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c +index 29c172c..830c7aa 100644 +--- a/source3/smbd/smbXsrv_open.c ++++ b/source3/smbd/smbXsrv_open.c +@@ -64,7 +64,8 @@ NTSTATUS smbXsrv_open_global_init(void) + TDB_CLEAR_IF_FIRST | + TDB_INCOMPATIBLE_HASH, + O_RDWR | O_CREAT, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, ++ DBWRAP_FLAG_NONE); + if (db_ctx == NULL) { + NTSTATUS status; + +diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c +index 017880c..a1ba52d 100644 +--- a/source3/smbd/smbXsrv_session.c ++++ b/source3/smbd/smbXsrv_session.c +@@ -75,7 +75,8 @@ NTSTATUS smbXsrv_session_global_init(void) + TDB_CLEAR_IF_FIRST | + TDB_INCOMPATIBLE_HASH, + O_RDWR | O_CREAT, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, ++ DBWRAP_FLAG_NONE); + if (db_ctx == NULL) { + NTSTATUS status; + +diff --git a/source3/smbd/smbXsrv_tcon.c b/source3/smbd/smbXsrv_tcon.c +index b6e2058..2cbd761 100644 +--- a/source3/smbd/smbXsrv_tcon.c ++++ b/source3/smbd/smbXsrv_tcon.c +@@ -62,7 +62,8 @@ NTSTATUS smbXsrv_tcon_global_init(void) + TDB_CLEAR_IF_FIRST | + TDB_INCOMPATIBLE_HASH, + O_RDWR | O_CREAT, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, ++ DBWRAP_FLAG_NONE); + if (db_ctx == NULL) { + NTSTATUS status; + +diff --git a/source3/smbd/smbXsrv_version.c b/source3/smbd/smbXsrv_version.c +index 8ba5e1f..b24dae9 100644 +--- a/source3/smbd/smbXsrv_version.c ++++ b/source3/smbd/smbXsrv_version.c +@@ -80,7 +80,8 @@ NTSTATUS smbXsrv_version_global_init(const struct server_id *server_id) + TDB_CLEAR_IF_FIRST | + TDB_INCOMPATIBLE_HASH, + O_RDWR | O_CREAT, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, ++ DBWRAP_FLAG_NONE); + if (db_ctx == NULL) { + status = map_nt_error_from_unix_common(errno); + DEBUG(0,("smbXsrv_version_global_init: " +diff --git a/source3/torture/test_dbwrap_watch.c b/source3/torture/test_dbwrap_watch.c +index 9c2a679..4e699fe 100644 +--- a/source3/torture/test_dbwrap_watch.c ++++ b/source3/torture/test_dbwrap_watch.c +@@ -48,7 +48,8 @@ bool run_dbwrap_watch1(int dummy) + goto fail; + } + db = db_open(msg, "test_watch.tdb", 0, TDB_DEFAULT, +- O_CREAT|O_RDWR, 0644, DBWRAP_LOCK_ORDER_1); ++ O_CREAT|O_RDWR, 0644, DBWRAP_LOCK_ORDER_1, ++ DBWRAP_FLAG_NONE); + if (db == NULL) { + fprintf(stderr, "db_open failed: %s\n", strerror(errno)); + goto fail; +diff --git a/source3/torture/test_idmap_tdb_common.c b/source3/torture/test_idmap_tdb_common.c +index 6f5f3c5..f7262a2 100644 +--- a/source3/torture/test_idmap_tdb_common.c ++++ b/source3/torture/test_idmap_tdb_common.c +@@ -86,7 +86,7 @@ static bool open_db(struct idmap_tdb_common_context *ctx) + + ctx->db = db_open(ctx, db_path, 0, TDB_DEFAULT, + O_RDWR | O_CREAT, 0600, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + + if(!ctx->db) { + DEBUG(0, ("Failed to open database: %s\n", strerror(errno))); +diff --git a/source3/torture/torture.c b/source3/torture/torture.c +index 2e66912..1dc3eaf 100644 +--- a/source3/torture/torture.c ++++ b/source3/torture/torture.c +@@ -9011,7 +9011,8 @@ static bool run_local_dbtrans(int dummy) + TDB_DATA value; + + db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT, +- O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1); ++ O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1, ++ DBWRAP_FLAG_NONE); + if (db == NULL) { + printf("Could not open transtest.db\n"); + return false; +diff --git a/source3/utils/dbwrap_tool.c b/source3/utils/dbwrap_tool.c +index ffca6b6..b56e07a 100644 +--- a/source3/utils/dbwrap_tool.c ++++ b/source3/utils/dbwrap_tool.c +@@ -588,7 +588,7 @@ int main(int argc, const char **argv) + case OP_LISTKEYS: + case OP_EXISTS: + db = db_open(mem_ctx, dbname, 0, tdb_flags, O_RDWR | O_CREAT, +- 0644, DBWRAP_LOCK_ORDER_1); ++ 0644, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (db == NULL) { + d_fprintf(stderr, "ERROR: could not open dbname\n"); + goto done; +diff --git a/source3/utils/dbwrap_torture.c b/source3/utils/dbwrap_torture.c +index 2741820..f748ac2 100644 +--- a/source3/utils/dbwrap_torture.c ++++ b/source3/utils/dbwrap_torture.c +@@ -309,7 +309,7 @@ int main(int argc, const char *argv[]) + } + + db = db_open(mem_ctx, db_name, 0, tdb_flags, O_RDWR | O_CREAT, 0644, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + + if (db == NULL) { + d_fprintf(stderr, "failed to open db '%s': %s\n", db_name, +diff --git a/source3/utils/net_idmap.c b/source3/utils/net_idmap.c +index fbeca3e..6fc07e7 100644 +--- a/source3/utils/net_idmap.c ++++ b/source3/utils/net_idmap.c +@@ -210,7 +210,7 @@ static int net_idmap_dump(struct net_context *c, int argc, const char **argv) + d_fprintf(stderr, _("dumping id mapping from %s\n"), dbfile); + + db = db_open(mem_ctx, dbfile, 0, TDB_DEFAULT, O_RDONLY, 0, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (db == NULL) { + d_fprintf(stderr, _("Could not open idmap db (%s): %s\n"), + dbfile, strerror(errno)); +@@ -336,7 +336,7 @@ static int net_idmap_restore(struct net_context *c, int argc, const char **argv) + } + + db = db_open(mem_ctx, dbfile, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (db == NULL) { + d_fprintf(stderr, _("Could not open idmap db (%s): %s\n"), + dbfile, strerror(errno)); +@@ -546,7 +546,7 @@ static int net_idmap_delete(struct net_context *c, int argc, const char **argv) + d_fprintf(stderr, _("deleting id mapping from %s\n"), dbfile); + + db = db_open(mem_ctx, dbfile, 0, TDB_DEFAULT, O_RDWR, 0, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (db == NULL) { + d_fprintf(stderr, _("Could not open idmap db (%s): %s\n"), + dbfile, strerror(errno)); +diff --git a/source3/utils/net_idmap_check.c b/source3/utils/net_idmap_check.c +index e75c890..4b82871 100644 +--- a/source3/utils/net_idmap_check.c ++++ b/source3/utils/net_idmap_check.c +@@ -790,7 +790,7 @@ static bool check_open_db(struct check_ctx* ctx, const char* name, int oflags) + } + + ctx->db = db_open(ctx, name, 0, TDB_DEFAULT, oflags, 0, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (ctx->db == NULL) { + d_fprintf(stderr, + _("Could not open idmap db (%s) for writing: %s\n"), +diff --git a/source3/utils/net_registry_check.c b/source3/utils/net_registry_check.c +index 8cdb8fa..d57c2aa 100644 +--- a/source3/utils/net_registry_check.c ++++ b/source3/utils/net_registry_check.c +@@ -338,7 +338,7 @@ static bool check_ctx_open_output(struct check_ctx *ctx) + } + + ctx->odb = db_open(ctx, ctx->opt.output, 0, TDB_DEFAULT, oflags, 0644, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (ctx->odb == NULL) { + d_fprintf(stderr, + _("Could not open db (%s) for writing: %s\n"), +@@ -351,7 +351,7 @@ static bool check_ctx_open_output(struct check_ctx *ctx) + + static bool check_ctx_open_input(struct check_ctx *ctx) { + ctx->idb = db_open(ctx, ctx->fname, 0, TDB_DEFAULT, O_RDONLY, 0, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (ctx->idb == NULL) { + d_fprintf(stderr, + _("Could not open db (%s) for reading: %s\n"), +diff --git a/source3/utils/status.c b/source3/utils/status.c +index be7c52f..1ff0e36 100644 +--- a/source3/utils/status.c ++++ b/source3/utils/status.c +@@ -508,7 +508,7 @@ static void print_notify_recs(const char *path, + struct db_context *db; + db = db_open(NULL, lock_path("locking.tdb"), 0, + TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, O_RDONLY, 0, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + + if (!db) { + d_printf("%s not initialised\n", +diff --git a/source3/winbindd/idmap_autorid.c b/source3/winbindd/idmap_autorid.c +index 57d952e..0bd2938 100644 +--- a/source3/winbindd/idmap_autorid.c ++++ b/source3/winbindd/idmap_autorid.c +@@ -728,7 +728,7 @@ static NTSTATUS idmap_autorid_db_init(void) + /* Open idmap repository */ + autorid_db = db_open(NULL, state_path("autorid.tdb"), 0, + TDB_DEFAULT, O_RDWR | O_CREAT, 0644, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + + if (!autorid_db) { + DEBUG(0, ("Unable to open idmap_autorid database '%s'\n", +diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c +index cc930ff..ebff347 100644 +--- a/source3/winbindd/idmap_tdb.c ++++ b/source3/winbindd/idmap_tdb.c +@@ -321,7 +321,7 @@ static NTSTATUS idmap_tdb_open_db(struct idmap_domain *dom) + + /* Open idmap repository */ + db = db_open(mem_ctx, tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (!db) { + DEBUG(0, ("Unable to open idmap database\n")); + ret = NT_STATUS_UNSUCCESSFUL; +diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c +index 4a9c2fe..942490d 100644 +--- a/source3/winbindd/idmap_tdb2.c ++++ b/source3/winbindd/idmap_tdb2.c +@@ -114,7 +114,7 @@ static NTSTATUS idmap_tdb2_open_db(struct idmap_domain *dom) + + /* Open idmap repository */ + ctx->db = db_open(ctx, db_path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644, +- DBWRAP_LOCK_ORDER_1); ++ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + TALLOC_FREE(db_path); + + if (ctx->db == NULL) { +-- +1.9.3 + + +From b904731a81df57b3d33fe0c35663bc47d061d744 Mon Sep 17 00:00:00 2001 +From: Michael Adam +Date: Tue, 28 Jan 2014 12:53:24 +0100 +Subject: [PATCH 236/249] dbwrap: add a dbwrap_flags argument to db_open_ctdb() + +This is in preparation of directly supporting ctdb read only +record copies when opening a ctdb database from samba. + +Signed-off-by: Michael Adam +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 6def1c3f6e145abcc81ea69505133bbe128eacac) +--- + source3/lib/dbwrap/dbwrap_ctdb.c | 6 ++++-- + source3/lib/dbwrap/dbwrap_ctdb.h | 3 ++- + source3/lib/dbwrap/dbwrap_open.c | 2 +- + source3/torture/test_dbwrap_ctdb.c | 2 +- + 4 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/source3/lib/dbwrap/dbwrap_ctdb.c b/source3/lib/dbwrap/dbwrap_ctdb.c +index 5a473f9..af7a72f 100644 +--- a/source3/lib/dbwrap/dbwrap_ctdb.c ++++ b/source3/lib/dbwrap/dbwrap_ctdb.c +@@ -1498,7 +1498,8 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx, + const char *name, + int hash_size, int tdb_flags, + int open_flags, mode_t mode, +- enum dbwrap_lock_order lock_order) ++ enum dbwrap_lock_order lock_order, ++ uint64_t dbwrap_flags) + { + struct db_context *result; + struct db_ctdb_ctx *db_ctdb; +@@ -1624,7 +1625,8 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx, + const char *name, + int hash_size, int tdb_flags, + int open_flags, mode_t mode, +- enum dbwrap_lock_order lock_order) ++ enum dbwrap_lock_order lock_order, ++ uint64_t dbwrap_flags) + { + DEBUG(3, ("db_open_ctdb: no cluster support!\n")); + errno = ENOSYS; +diff --git a/source3/lib/dbwrap/dbwrap_ctdb.h b/source3/lib/dbwrap/dbwrap_ctdb.h +index bfbe3bd..3196b91 100644 +--- a/source3/lib/dbwrap/dbwrap_ctdb.h ++++ b/source3/lib/dbwrap/dbwrap_ctdb.h +@@ -31,6 +31,7 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx, + const char *name, + int hash_size, int tdb_flags, + int open_flags, mode_t mode, +- enum dbwrap_lock_order lock_order); ++ enum dbwrap_lock_order lock_order, ++ uint64_t dbwrap_flags); + + #endif /* __DBWRAP_CTDB_H__ */ +diff --git a/source3/lib/dbwrap/dbwrap_open.c b/source3/lib/dbwrap/dbwrap_open.c +index 6c9280c..61324f7 100644 +--- a/source3/lib/dbwrap/dbwrap_open.c ++++ b/source3/lib/dbwrap/dbwrap_open.c +@@ -104,7 +104,7 @@ struct db_context *db_open(TALLOC_CTX *mem_ctx, + if (lp_parm_bool(-1, "ctdb", partname, True)) { + result = db_open_ctdb(mem_ctx, partname, hash_size, + tdb_flags, open_flags, mode, +- lock_order); ++ lock_order, dbwrap_flags); + if (result == NULL) { + DEBUG(0,("failed to attach to ctdb %s\n", + partname)); +diff --git a/source3/torture/test_dbwrap_ctdb.c b/source3/torture/test_dbwrap_ctdb.c +index f7672ba..d7380b1 100644 +--- a/source3/torture/test_dbwrap_ctdb.c ++++ b/source3/torture/test_dbwrap_ctdb.c +@@ -32,7 +32,7 @@ bool run_local_dbwrap_ctdb(int dummy) + uint32_t val; + + db = db_open_ctdb(talloc_tos(), "torture.tdb", 0, TDB_DEFAULT, +- O_RDWR, 0755, DBWRAP_LOCK_ORDER_1); ++ O_RDWR, 0755, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (db == NULL) { + perror("db_open_ctdb failed"); + goto fail; +-- +1.9.3 + + +From 4f2d14112981d03000b533458e2e60a032d052de Mon Sep 17 00:00:00 2001 +From: Michael Adam +Date: Tue, 28 Jan 2014 11:31:44 +0100 +Subject: [PATCH 237/249] dbwrap: add DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS + +Signed-off-by: Michael Adam +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 56bd4040889dfe492ff820497b7a6d76624a6048) +--- + lib/dbwrap/dbwrap.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/dbwrap/dbwrap.h b/lib/dbwrap/dbwrap.h +index 4064ba2..02b4405 100644 +--- a/lib/dbwrap/dbwrap.h ++++ b/lib/dbwrap/dbwrap.h +@@ -33,6 +33,7 @@ enum dbwrap_lock_order { + #define DBWRAP_LOCK_ORDER_MAX DBWRAP_LOCK_ORDER_3 + + #define DBWRAP_FLAG_NONE 0x0000000000000000ULL ++#define DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS 0x0000000000000001ULL + + /* The following definitions come from lib/dbwrap.c */ + +-- +1.9.3 + + +From a007f8f7f627c4347f48bd2446637aab137e0608 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 28 Jan 2014 21:24:22 +0100 +Subject: [PATCH 238/249] dbwrap_ctdb: implement + DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS + +For non-persistent databases we try to use CTDB_CONTROL_SET_DB_READONLY +in order to make use of readonly records. + +Pair-Programmed-With: Michael Adam + +Signed-off-by: Stefan Metzmacher +Signed-off-by: Michael Adam +(cherry picked from commit a97b588b63f437d25c4344c76014326dbf0cbdb0) +--- + source3/lib/dbwrap/dbwrap_ctdb.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/source3/lib/dbwrap/dbwrap_ctdb.c b/source3/lib/dbwrap/dbwrap_ctdb.c +index af7a72f..3dc86d1 100644 +--- a/source3/lib/dbwrap/dbwrap_ctdb.c ++++ b/source3/lib/dbwrap/dbwrap_ctdb.c +@@ -1578,6 +1578,27 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx, + return NULL; + } + ++#ifdef HAVE_CTDB_WANT_READONLY_DECL ++ if (!result->persistent && ++ (dbwrap_flags & DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS)) ++ { ++ TDB_DATA indata; ++ ++ indata = make_tdb_data((uint8_t *)&db_ctdb->db_id, ++ sizeof(db_ctdb->db_id)); ++ ++ status = ctdbd_control_local( ++ conn, CTDB_CONTROL_SET_DB_READONLY, 0, 0, indata, ++ NULL, NULL, &cstatus); ++ if (!NT_STATUS_IS_OK(status) || (cstatus != 0)) { ++ DEBUG(1, ("CTDB_CONTROL_SET_DB_READONLY failed: " ++ "%s, %d\n", nt_errstr(status), cstatus)); ++ TALLOC_FREE(result); ++ return NULL; ++ } ++ } ++#endif ++ + lp_ctx = loadparm_init_s3(db_path, loadparm_s3_helpers()); + + db_ctdb->wtdb = tdb_wrap_open(db_ctdb, db_path, hash_size, tdb_flags, +-- +1.9.3 + + +From d1ea222d46a594d45422eacccbd655d7e488792a Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 28 Jan 2014 21:31:17 +0100 +Subject: [PATCH 239/249] dbwrap_open: add 'dbwrap_optimize_readonly:* = yes' + option + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Michael Adam +(cherry picked from commit a20c977c7a58a0c09d01bfa046c00fcd3f1462de) +--- + source3/lib/dbwrap/dbwrap_open.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/source3/lib/dbwrap/dbwrap_open.c b/source3/lib/dbwrap/dbwrap_open.c +index 61324f7..7f3cddf 100644 +--- a/source3/lib/dbwrap/dbwrap_open.c ++++ b/source3/lib/dbwrap/dbwrap_open.c +@@ -81,6 +81,31 @@ struct db_context *db_open(TALLOC_CTX *mem_ctx, + return NULL; + } + ++ if (tdb_flags & TDB_CLEAR_IF_FIRST) { ++ const char *base; ++ bool try_readonly = false; ++ ++ base = strrchr_m(name, '/'); ++ if (base != NULL) { ++ base += 1; ++ } else { ++ base = name; ++ } ++ ++ if (dbwrap_flags & DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS) { ++ try_readonly = true; ++ } ++ ++ try_readonly = lp_parm_bool(-1, "dbwrap_optimize_readonly", "*", try_readonly); ++ try_readonly = lp_parm_bool(-1, "dbwrap_optimize_readonly", base, try_readonly); ++ ++ if (try_readonly) { ++ dbwrap_flags |= DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS; ++ } else { ++ dbwrap_flags &= ~DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS; ++ } ++ } ++ + #ifdef CLUSTER_SUPPORT + sockname = lp_ctdbd_socket(); + +-- +1.9.3 + + +From ce06399f9fab90623a2166d69f1bbfc46f124d73 Mon Sep 17 00:00:00 2001 +From: Michael Adam +Date: Mon, 27 Jan 2014 16:21:14 +0100 +Subject: [PATCH 240/249] s3:rpc_client: optimize the netlogon_creds_cli.tdb + for read-only access + +Usually a record in this DB will be written once and then read +many times by winbindd processes on multiple nodes (when run in +a cluster). In order not to introduce a big performance penalty +with the increased correctness achieved by storing the netlogon +creds, in a cluster setup, we should activate ctdb's read only +record copies on this db. + +Signed-off-by: Michael Adam +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 020fab300d2f4f19301eff19ad810c71f77bbb78) +--- + source3/rpc_client/cli_netlogon.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index 9e3c1bd..746c7b6 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -70,7 +70,7 @@ NTSTATUS rpccli_pre_open_netlogon_creds(void) + global_db = db_open(talloc_autofree_context(), fname, + 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, + O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_2, +- DBWRAP_FLAG_NONE); ++ DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS); + if (global_db == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; +-- +1.9.3 + + +From e39b8c0e22e609db117285d47cdbd1d854fe8d02 Mon Sep 17 00:00:00 2001 +From: Ira Cooper +Date: Thu, 13 Feb 2014 14:45:23 -0500 +Subject: [PATCH 241/249] libcli: Overflow array index read possible, in auth + code. + +Changed the if condtion to detect when we'd improperly overflow. + +Coverity-Id: 1167990 +Signed-off-by: Ira Cooper +Reviewed-by: Stefan Metzmacher + +Autobuild-User(master): Ira Cooper +Autobuild-Date(master): Mon Feb 24 11:56:38 CET 2014 on sn-devel-104 + +(cherry picked from commit 8cd8aa6686c21e8c43a6d14c0ae1a21954d6e8cd) +--- + libcli/auth/netlogon_creds_cli.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c +index 88893ad..e3cf91c 100644 +--- a/libcli/auth/netlogon_creds_cli.c ++++ b/libcli/auth/netlogon_creds_cli.c +@@ -1769,7 +1769,7 @@ struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx + uint32_t ofs = 512 - len; + uint8_t *p; + +- if (ofs < 12) { ++ if (len > 500) { + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); + return tevent_req_post(req, ev); + } +-- +1.9.3 + + +From 4e15aa86c44e906ca30cfa4589e4f45f23625953 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Tue, 15 Jul 2014 08:28:42 +0200 +Subject: [PATCH 242/249] s3-rpc_client: return info3 in + rpccli_netlogon_password_logon(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Pair-Programmed-With: Andreas Schneider +Reviewed-by: Andreas Schneider +--- + source3/rpc_client/cli_netlogon.c | 103 +++++++++++++++++++++----------------- + source3/rpc_client/cli_netlogon.h | 4 +- + source3/rpcclient/cmd_netlogon.c | 5 +- + 3 files changed, 64 insertions(+), 48 deletions(-) + +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index 746c7b6..7063351 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -193,16 +193,65 @@ NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, + return NT_STATUS_OK; + } + ++static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx, ++ uint16_t validation_level, ++ union netr_Validation *validation, ++ struct netr_SamInfo3 **info3_p) ++{ ++ struct netr_SamInfo3 *info3; ++ NTSTATUS status; ++ ++ if (validation == NULL) { ++ return NT_STATUS_INVALID_PARAMETER; ++ } ++ ++ switch (validation_level) { ++ case 3: ++ if (validation->sam3 == NULL) { ++ return NT_STATUS_INVALID_PARAMETER; ++ } ++ ++ info3 = talloc_move(mem_ctx, &validation->sam3); ++ break; ++ case 6: ++ if (validation->sam6 == NULL) { ++ return NT_STATUS_INVALID_PARAMETER; ++ } ++ ++ info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); ++ if (info3 == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ status = copy_netr_SamBaseInfo(info3, &validation->sam6->base, &info3->base); ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(info3); ++ return status; ++ } ++ ++ info3->sidcount = validation->sam6->sidcount; ++ info3->sids = talloc_move(info3, &validation->sam6->sids); ++ break; ++ default: ++ return NT_STATUS_BAD_VALIDATION_CLASS; ++ } ++ ++ *info3_p = info3; ++ ++ return NT_STATUS_OK; ++} ++ + /* Logon domain user */ + + NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds, + struct dcerpc_binding_handle *binding_handle, ++ TALLOC_CTX *mem_ctx, + uint32_t logon_parameters, + const char *domain, + const char *username, + const char *password, + const char *workstation, +- enum netr_LogonInfoClass logon_type) ++ enum netr_LogonInfoClass logon_type, ++ struct netr_SamInfo3 **info3) + { + TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS status; +@@ -320,57 +369,19 @@ NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds + &validation, + &authoritative, + &flags); +- TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(frame); + return status; + } + +- return NT_STATUS_OK; +-} +- +-static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx, +- uint16_t validation_level, +- union netr_Validation *validation, +- struct netr_SamInfo3 **info3_p) +-{ +- struct netr_SamInfo3 *info3; +- NTSTATUS status; +- +- if (validation == NULL) { +- return NT_STATUS_INVALID_PARAMETER; +- } +- +- switch (validation_level) { +- case 3: +- if (validation->sam3 == NULL) { +- return NT_STATUS_INVALID_PARAMETER; +- } +- +- info3 = talloc_move(mem_ctx, &validation->sam3); +- break; +- case 6: +- if (validation->sam6 == NULL) { +- return NT_STATUS_INVALID_PARAMETER; +- } +- +- info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); +- if (info3 == NULL) { +- return NT_STATUS_NO_MEMORY; +- } +- status = copy_netr_SamBaseInfo(info3, &validation->sam6->base, &info3->base); +- if (!NT_STATUS_IS_OK(status)) { +- TALLOC_FREE(info3); +- return status; +- } +- +- info3->sidcount = validation->sam6->sidcount; +- info3->sids = talloc_move(info3, &validation->sam6->sids); +- break; +- default: +- return NT_STATUS_BAD_VALIDATION_CLASS; ++ status = map_validation_to_info3(mem_ctx, ++ validation_level, validation, ++ info3); ++ TALLOC_FREE(frame); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; + } + +- *info3_p = info3; + + return NT_STATUS_OK; + } +diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h +index 61fed4a..fee0801 100644 +--- a/source3/rpc_client/cli_netlogon.h ++++ b/source3/rpc_client/cli_netlogon.h +@@ -45,12 +45,14 @@ NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, + const struct samr_Password *previous_nt_hash); + NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds, + struct dcerpc_binding_handle *binding_handle, ++ TALLOC_CTX *mem_ctx, + uint32_t logon_parameters, + const char *domain, + const char *username, + const char *password, + const char *workstation, +- enum netr_LogonInfoClass logon_type); ++ enum netr_LogonInfoClass logon_type, ++ struct netr_SamInfo3 **info3); + NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds, + struct dcerpc_binding_handle *binding_handle, + TALLOC_CTX *mem_ctx, +diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c +index b637b3e..2d1c351 100644 +--- a/source3/rpcclient/cmd_netlogon.c ++++ b/source3/rpcclient/cmd_netlogon.c +@@ -778,6 +778,7 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, + const char *username, *password; + uint32 logon_param = 0; + const char *workstation = NULL; ++ struct netr_SamInfo3 *info3 = NULL; + + /* Check arguments */ + +@@ -803,12 +804,14 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, + + result = rpccli_netlogon_password_logon(rpcclient_netlogon_creds, + cli->binding_handle, ++ mem_ctx, + logon_param, + lp_workgroup(), + username, + password, + workstation, +- logon_type); ++ logon_type, ++ &info3); + if (!NT_STATUS_IS_OK(result)) + goto done; + +-- +1.9.3 + + +From 3459fada96951a57a787944aedc01caabe873c9d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Tue, 15 Jul 2014 08:29:55 +0200 +Subject: [PATCH 243/249] s3-winbindd: call interactive samlogon via + rpccli_netlogon_password_logon. + +Guenther + +Signed-off-by: Guenther Deschner +Pair-Programmed-With: Andreas Schneider +Reviewed-by: Andreas Schneider + +Conflicts: + source3/winbindd/winbindd_pam.c +--- + source3/winbindd/winbindd_pam.c | 45 +++++++++++++++++++++++++++++------------ + 1 file changed, 32 insertions(+), 13 deletions(-) + +diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c +index 3f3ec70..2a1b74a 100644 +--- a/source3/winbindd/winbindd_pam.c ++++ b/source3/winbindd/winbindd_pam.c +@@ -1214,11 +1214,13 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, + uint32_t logon_parameters, + const char *server, + const char *username, ++ const char *password, + const char *domainname, + const char *workstation, + const uint8_t chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, ++ bool interactive, + struct netr_SamInfo3 **info3) + { + int attempts = 0; +@@ -1278,19 +1280,32 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, + } + netr_attempts = 0; + +- result = rpccli_netlogon_network_logon(domain->conn.netlogon_creds, +- netlogon_pipe->binding_handle, +- mem_ctx, +- logon_parameters, +- username, +- domainname, +- workstation, +- chal, +- lm_response, +- nt_response, +- &authoritative, +- &flags, +- info3); ++ if (interactive && username != NULL && password != NULL) { ++ result = rpccli_netlogon_password_logon(domain->conn.netlogon_creds, ++ netlogon_pipe->binding_handle, ++ mem_ctx, ++ logon_parameters, ++ domainname, ++ username, ++ password, ++ workstation, ++ NetlogonInteractiveInformation, ++ info3); ++ } else { ++ result = rpccli_netlogon_network_logon(domain->conn.netlogon_creds, ++ netlogon_pipe->binding_handle, ++ mem_ctx, ++ logon_parameters, ++ username, ++ domainname, ++ workstation, ++ chal, ++ lm_response, ++ nt_response, ++ &authoritative, ++ &flags, ++ info3); ++ } + + /* + * we increment this after the "feature negotiation" +@@ -1433,11 +1448,13 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon(TALLOC_CTX *mem_ctx, + 0, + domain->dcname, + name_user, ++ pass, + name_domain, + lp_netbios_name(), + chal, + lm_resp, + nt_resp, ++ true, /* interactive */ + &my_info3); + if (!NT_STATUS_IS_OK(result)) { + goto done; +@@ -1856,12 +1873,14 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, + state->request->data.auth_crap.logon_parameters, + domain->dcname, + name_user, ++ NULL, /* password */ + name_domain, + /* Bug #3248 - found by Stefan Burkei. */ + workstation, /* We carefully set this above so use it... */ + state->request->data.auth_crap.chal, + lm_resp, + nt_resp, ++ false, /* interactive */ + &info3); + if (!NT_STATUS_IS_OK(result)) { + goto done; +-- +1.9.3 + + +From ad27b750ea3766581e528a41c132bb57927cc64c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Mon, 7 Jul 2014 17:14:37 +0200 +Subject: [PATCH 244/249] s3-winbindd: add wcache_query_user_fullname(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This helper function is used to query the full name of a cached user object (for +further gecos processing). + +Thanks to Matt Rogers . + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=10440 + +Guenther + +Pair-Programmed-With: Andreas Schneider +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider +--- + source3/winbindd/winbindd_cache.c | 34 ++++++++++++++++++++++++++++++++++ + source3/winbindd/winbindd_proto.h | 4 ++++ + 2 files changed, 38 insertions(+) + +diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c +index 59ce515..d1e10e6c 100644 +--- a/source3/winbindd/winbindd_cache.c ++++ b/source3/winbindd/winbindd_cache.c +@@ -2309,6 +2309,40 @@ NTSTATUS wcache_query_user(struct winbindd_domain *domain, + return status; + } + ++ ++/** ++* @brief Query a fullname from the username cache (for further gecos processing) ++* ++* @param domain A pointer to the winbindd_domain struct. ++* @param mem_ctx The talloc context. ++* @param user_sid The user sid. ++* @param full_name A pointer to the full_name string. ++* ++* @return NTSTATUS code ++*/ ++NTSTATUS wcache_query_user_fullname(struct winbindd_domain *domain, ++ TALLOC_CTX *mem_ctx, ++ const struct dom_sid *user_sid, ++ const char **full_name) ++{ ++ NTSTATUS status; ++ struct wbint_userinfo info; ++ ++ status = wcache_query_user(domain, mem_ctx, user_sid, &info); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ if (info.full_name != NULL) { ++ *full_name = talloc_strdup(mem_ctx, info.full_name); ++ if (*full_name == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ } ++ ++ return NT_STATUS_OK; ++} ++ + /* Lookup user information from a rid */ + static NTSTATUS query_user(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, +diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h +index cfc19d0..cfb7812 100644 +--- a/source3/winbindd/winbindd_proto.h ++++ b/source3/winbindd/winbindd_proto.h +@@ -105,6 +105,10 @@ NTSTATUS wcache_query_user(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const struct dom_sid *user_sid, + struct wbint_userinfo *info); ++NTSTATUS wcache_query_user_fullname(struct winbindd_domain *domain, ++ TALLOC_CTX *mem_ctx, ++ const struct dom_sid *user_sid, ++ const char **full_name); + NTSTATUS wcache_lookup_useraliases(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 num_sids, const struct dom_sid *sids, +-- +1.9.3 + + +From e89ca0b90887930a2f86dcaa4f6d3d05565f919c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Mon, 7 Jul 2014 17:16:32 +0200 +Subject: [PATCH 245/249] s3-winbindd: use wcache_query_user_fullname after + inspecting samlogon cache. + +The reason for this followup query is that very often the samlogon cache only +contains a info3 netlogon user structure that has been retrieved during a +netlogon samlogon authentication using "network" logon level. With that logon +level only a few info3 fields are filled in; the user's fullname is never filled +in that case. This is problematic when the cache is used to fill in the user's +gecos field (for NSS queries). When we have retrieved the user's fullname during +other queries, reuse it from the other caches. + +Thanks to Matt Rogers . + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=10440 + +Guenther + +Pair-Programmed-With: Andreas Schneider +Signed-off-by: Guenther Deschner +Reviewed-by: Andreas Schneider +--- + source3/winbindd/winbindd_ads.c | 8 ++++++++ + source3/winbindd/winbindd_msrpc.c | 8 ++++++++ + source3/winbindd/winbindd_pam.c | 20 ++++++++++++++++++++ + 3 files changed, 36 insertions(+) + +diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c +index 4c26389..a20fba5 100644 +--- a/source3/winbindd/winbindd_ads.c ++++ b/source3/winbindd/winbindd_ads.c +@@ -619,6 +619,14 @@ static NTSTATUS query_user(struct winbindd_domain *domain, + + TALLOC_FREE(user); + ++ if (info->full_name == NULL) { ++ /* this might fail so we dont check the return code */ ++ wcache_query_user_fullname(domain, ++ mem_ctx, ++ sid, ++ &info->full_name); ++ } ++ + return NT_STATUS_OK; + } + +diff --git a/source3/winbindd/winbindd_msrpc.c b/source3/winbindd/winbindd_msrpc.c +index 426d64c..c097bf3 100644 +--- a/source3/winbindd/winbindd_msrpc.c ++++ b/source3/winbindd/winbindd_msrpc.c +@@ -439,6 +439,14 @@ static NTSTATUS msrpc_query_user(struct winbindd_domain *domain, + user_info->full_name = talloc_strdup(user_info, + user->base.full_name.string); + ++ if (user_info->full_name == NULL) { ++ /* this might fail so we dont check the return code */ ++ wcache_query_user_fullname(domain, ++ mem_ctx, ++ user_sid, ++ &user_info->full_name); ++ } ++ + status = NT_STATUS_OK; + goto done; + } +diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c +index 2a1b74a..bf71d97 100644 +--- a/source3/winbindd/winbindd_pam.c ++++ b/source3/winbindd/winbindd_pam.c +@@ -1720,6 +1720,26 @@ process_result: + sid_compose(&user_sid, info3->base.domain_sid, + info3->base.rid); + ++ if (info3->base.full_name.string == NULL) { ++ struct netr_SamInfo3 *cached_info3; ++ ++ cached_info3 = netsamlogon_cache_get(state->mem_ctx, ++ &user_sid); ++ if (cached_info3 != NULL && ++ cached_info3->base.full_name.string != NULL) { ++ info3->base.full_name.string = ++ talloc_strdup(info3, ++ cached_info3->base.full_name.string); ++ } else { ++ ++ /* this might fail so we dont check the return code */ ++ wcache_query_user_fullname(domain, ++ info3, ++ &user_sid, ++ &info3->base.full_name.string); ++ } ++ } ++ + wcache_invalidate_samlogon(find_domain_from_name(name_domain), + &user_sid); + netsamlogon_cache_store(name_user, info3); +-- +1.9.3 + + +From aa042d490b2cccb7b6cc394e024004321a6c156c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 9 Jul 2014 13:36:06 +0200 +Subject: [PATCH 246/249] samlogon_cache: use a talloc_stackframe inside + netsamlogon_cache_store. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider +--- + source3/libsmb/samlogon_cache.c | 13 ++++--------- + 1 file changed, 4 insertions(+), 9 deletions(-) + +diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c +index b04cf0a..f7457ae 100644 +--- a/source3/libsmb/samlogon_cache.c ++++ b/source3/libsmb/samlogon_cache.c +@@ -125,7 +125,7 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) + bool result = false; + struct dom_sid user_sid; + time_t t = time(NULL); +- TALLOC_CTX *mem_ctx; ++ TALLOC_CTX *tmp_ctx = talloc_stackframe(); + DATA_BLOB blob; + enum ndr_err_code ndr_err; + struct netsamlogoncache_entry r; +@@ -149,11 +149,6 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) + + /* Prepare data */ + +- if (!(mem_ctx = talloc( NULL, int))) { +- DEBUG(0,("netsamlogon_cache_store: talloc() failed!\n")); +- return false; +- } +- + /* only Samba fills in the username, not sure why NT doesn't */ + /* so we fill it in since winbindd_getpwnam() makes use of it */ + +@@ -168,11 +163,11 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) + NDR_PRINT_DEBUG(netsamlogoncache_entry, &r); + } + +- ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &r, ++ ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, &r, + (ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n")); +- TALLOC_FREE(mem_ctx); ++ TALLOC_FREE(tmp_ctx); + return false; + } + +@@ -183,7 +178,7 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) + result = true; + } + +- TALLOC_FREE(mem_ctx); ++ TALLOC_FREE(tmp_ctx); + + return result; + } +-- +1.9.3 + + +From 8283d1acec0c0afd17197339a4986975d05abf29 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Thu, 3 Jul 2014 16:17:46 +0200 +Subject: [PATCH 247/249] samlogon_cache: avoid overwriting + info3->base.full_name.string. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This field servers as a source for the gecos field. We should not overwrite it +when a info3 struct from a samlogon network level gets saved in which case this +field is always NULL. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=10440 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner + +Autobuild-User(master): Günther Deschner +Autobuild-Date(master): Tue Jul 15 18:25:28 CEST 2014 on sn-devel-104 +--- + source3/libsmb/samlogon_cache.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c +index f7457ae..0a157d4 100644 +--- a/source3/libsmb/samlogon_cache.c ++++ b/source3/libsmb/samlogon_cache.c +@@ -149,6 +149,20 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) + + /* Prepare data */ + ++ if (info3->base.full_name.string == NULL) { ++ struct netr_SamInfo3 *cached_info3; ++ const char *full_name = NULL; ++ ++ cached_info3 = netsamlogon_cache_get(tmp_ctx, &user_sid); ++ if (cached_info3 != NULL) { ++ full_name = cached_info3->base.full_name.string; ++ } ++ ++ if (full_name != NULL) { ++ info3->base.full_name.string = talloc_strdup(info3, full_name); ++ } ++ } ++ + /* only Samba fills in the username, not sure why NT doesn't */ + /* so we fill it in since winbindd_getpwnam() makes use of it */ + +-- +1.9.3 + + +From fe9d7458001a952d1df23dcd584a1835df5d43d1 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Thu, 3 Jul 2014 16:19:42 +0200 +Subject: [PATCH 248/249] s3-winbind: Don't set the gecos field to NULL. + +The value is loaded from the cache anyway. So it will be set to NULL if +it is not available. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=10440 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner +--- + source3/winbindd/nss_info_template.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/source3/winbindd/nss_info_template.c b/source3/winbindd/nss_info_template.c +index 5fdfd9b..de93803 100644 +--- a/source3/winbindd/nss_info_template.c ++++ b/source3/winbindd/nss_info_template.c +@@ -48,7 +48,6 @@ static NTSTATUS nss_template_get_info( struct nss_domain_entry *e, + username */ + *homedir = talloc_strdup( ctx, lp_template_homedir() ); + *shell = talloc_strdup( ctx, lp_template_shell() ); +- *gecos = NULL; + + if ( !*homedir || !*shell ) { + return NT_STATUS_NO_MEMORY; +-- +1.9.3 + + +From d2f3347a264bb7b8b0335404348990f52320b672 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Mon, 14 Jul 2014 18:22:26 +0200 +Subject: [PATCH 249/249] s3-winbindd: prefer "displayName" over "name" in ads + user queries for the fullname. + +This makes use more consistent with security=domain as well where the gecos +field is also filled using the displayName field. + +Guenther + +Signed-off-by: Guenther Deschner +Pair-Programmed-With: Andreas Schneider +Reviewed-by: Andreas Schneider +--- + source3/winbindd/winbindd_ads.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c +index a20fba5..4b5b2fa 100644 +--- a/source3/winbindd/winbindd_ads.c ++++ b/source3/winbindd/winbindd_ads.c +@@ -327,7 +327,10 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, + } + + info->acct_name = ads_pull_username(ads, mem_ctx, msg); +- info->full_name = ads_pull_string(ads, mem_ctx, msg, "name"); ++ info->full_name = ads_pull_string(ads, mem_ctx, msg, "displayName"); ++ if (info->full_name == NULL) { ++ info->full_name = ads_pull_string(ads, mem_ctx, msg, "name"); ++ } + info->homedir = NULL; + info->shell = NULL; + info->primary_gid = (gid_t)-1; +@@ -592,7 +595,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, + struct netr_SamInfo3 *user = NULL; + gid_t gid = -1; + int ret; +- char *ads_name; ++ char *full_name; + + DEBUG(3,("ads: query_user\n")); + +@@ -704,7 +707,10 @@ static NTSTATUS query_user(struct winbindd_domain *domain, + * nss_get_info_cached call. nss_get_info_cached might destroy + * the ads struct, potentially invalidating the ldap message. + */ +- ads_name = ads_pull_string(ads, mem_ctx, msg, "name"); ++ full_name = ads_pull_string(ads, mem_ctx, msg, "displayName"); ++ if (full_name == NULL) { ++ full_name = ads_pull_string(ads, mem_ctx, msg, "name"); ++ } + + ads_msgfree(ads, msg); + msg = NULL; +@@ -720,9 +726,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain, + } + + if (info->full_name == NULL) { +- info->full_name = ads_name; ++ info->full_name = full_name; + } else { +- TALLOC_FREE(ads_name); ++ TALLOC_FREE(full_name); + } + + status = NT_STATUS_OK; +-- +1.9.3 + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/06-fix-nmbd-systemd-status-update.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/06-fix-nmbd-systemd-status-update.patch new file mode 100644 index 00000000..7a7bdf53 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/06-fix-nmbd-systemd-status-update.patch @@ -0,0 +1,97 @@ +From f73c906237aa0c9d45900d69d31c9b39261f062a Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 16 Sep 2014 18:02:30 +0200 +Subject: [PATCH 1/2] lib: Add daemon_status() to util library. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=10816 + +Signed-off-by: Andreas Schneider +Reviewed-by: Alexander Bokovoy +(cherry picked from commit 9f5f5fa8ebf845c53b7a92557d7aec56ed820320) +--- + lib/util/become_daemon.c | 11 +++++++++++ + lib/util/samba_util.h | 6 ++++++ + 2 files changed, 17 insertions(+) + +diff --git a/lib/util/become_daemon.c b/lib/util/become_daemon.c +index 35c8b32..688bedd 100644 +--- a/lib/util/become_daemon.c ++++ b/lib/util/become_daemon.c +@@ -135,3 +135,14 @@ _PUBLIC_ void daemon_ready(const char *daemon) + #endif + DEBUG(0, ("STATUS=daemon '%s' finished starting up and ready to serve connections", daemon)); + } ++ ++_PUBLIC_ void daemon_status(const char *name, const char *msg) ++{ ++ if (name == NULL) { ++ name = "Samba"; ++ } ++#ifdef HAVE_SYSTEMD ++ sd_notifyf(0, "\nSTATUS=%s: %s", name, msg); ++#endif ++ DEBUG(0, ("STATUS=daemon '%s' : %s", name, msg)); ++} +diff --git a/lib/util/samba_util.h b/lib/util/samba_util.h +index e3fe6a6..f4216d8 100644 +--- a/lib/util/samba_util.h ++++ b/lib/util/samba_util.h +@@ -853,6 +853,12 @@ _PUBLIC_ void exit_daemon(const char *msg, int error); + **/ + _PUBLIC_ void daemon_ready(const char *daemon); + ++/* ++ * Report the daemon status. For example if it is not ready to serve connections ++ * and is waiting for some event to happen. ++ */ ++_PUBLIC_ void daemon_status(const char *name, const char *msg); ++ + /** + * @brief Get a password from the console. + * +-- +2.1.0 + + +From 7fcd74039961fa0fb02934bc87ce41fd98234f1a Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 16 Sep 2014 18:03:51 +0200 +Subject: [PATCH 2/2] nmbd: Send waiting status to systemd. + +This tells the Administrator what's going on and we should log that IPv6 +is not supported. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=10816 + +Signed-off-by: Andreas Schneider +Reviewed-by: Alexander Bokovoy + +Autobuild-User(master): Andreas Schneider +Autobuild-Date(master): Wed Sep 17 13:16:43 CEST 2014 on sn-devel-104 + +(cherry picked from commit 2df601bff0d949e66c79366b8248b9d950c0b430) +--- + source3/nmbd/nmbd_subnetdb.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/source3/nmbd/nmbd_subnetdb.c b/source3/nmbd/nmbd_subnetdb.c +index 311a240..6c483af 100644 +--- a/source3/nmbd/nmbd_subnetdb.c ++++ b/source3/nmbd/nmbd_subnetdb.c +@@ -247,8 +247,11 @@ bool create_subnets(void) + + /* Only count IPv4, non-loopback interfaces. */ + if (iface_count_v4_nl() == 0) { +- DEBUG(0,("create_subnets: No local IPv4 non-loopback interfaces !\n")); +- DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n")); ++ daemon_status("nmbd", ++ "No local IPv4 non-loopback interfaces " ++ "available, waiting for interface ..."); ++ DEBUG(0,("NOTE: NetBIOS name resolution is not supported for " ++ "Internet Protocol Version 6 (IPv6).\n")); + } + + /* We only count IPv4, non-loopback interfaces here. */ +-- +2.1.0 + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/07-fix-idmap-ad-getgroups-without-gid.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/07-fix-idmap-ad-getgroups-without-gid.patch new file mode 100644 index 00000000..3215f2c8 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/07-fix-idmap-ad-getgroups-without-gid.patch @@ -0,0 +1,42 @@ +From 23dfa2e35bec9c0f6c3d579e7dc2e1d0ce636aa2 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Fri, 19 Sep 2014 13:33:10 +0200 +Subject: [PATCH] nsswitch: Skip groups we were not able to map. + +If we have configured the idmap_ad backend it is possible that the user +is in a group without a gid set. This will result in (uid_t)-1 as the +gid. We return this invalid gid to NSS which is wrong. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=10824 + +Signed-off-by: Andreas Schneider +Reviewed-by: David Disseldorp + +Autobuild-User(master): David Disseldorp +Autobuild-Date(master): Fri Sep 19 17:57:14 CEST 2014 on sn-devel-104 + +(cherry picked from commit 7f59711f076e98ece099f6b38ff6da8c80fa6d5e) +Signed-off-by: Andreas Schneider +--- + nsswitch/winbind_nss_linux.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/nsswitch/winbind_nss_linux.c b/nsswitch/winbind_nss_linux.c +index 8d66a74..70ede3e 100644 +--- a/nsswitch/winbind_nss_linux.c ++++ b/nsswitch/winbind_nss_linux.c +@@ -1101,6 +1101,11 @@ _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, + continue; + } + ++ /* Skip groups without a mapping */ ++ if (gid_list[i] == (uid_t)-1) { ++ continue; ++ } ++ + /* Filled buffer ? If so, resize. */ + + if (*start == *size) { +-- +2.1.0 + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/08-fix-idmap-ad-sfu-with-trusted-domains.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/08-fix-idmap-ad-sfu-with-trusted-domains.patch new file mode 100644 index 00000000..394a6400 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/08-fix-idmap-ad-sfu-with-trusted-domains.patch @@ -0,0 +1,44 @@ +From dc6b86b93c8f059b0cc96c364ffad05c88b7d92e Mon Sep 17 00:00:00 2001 +From: Christof Schmitt +Date: Fri, 22 Aug 2014 09:15:59 -0700 +Subject: [PATCH] s3-winbindd: Use correct realm for trusted domains in idmap child + +When authenticating users in a trusted domain, the idmap_ad module +always connects to a local DC instead of one in the trusted domain. + +Fix this by passing the correct realm to connect to. + +Also Comment parameters passed to ads_cached_connection_connect + +Signed-off-by: Christof Schmitt +Reviewed-by: Jeremy Allison +(cherry picked from commit c203c722e7e22f9146f2ecf6f42452c0e82042e4) +--- + source3/winbindd/winbindd_ads.c | 11 +++++++++-- + 1 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c +index 4c26389..e47613e 100644 +--- a/source3/winbindd/winbindd_ads.c ++++ b/source3/winbindd/winbindd_ads.c +@@ -187,8 +187,15 @@ ADS_STATUS ads_idmap_cached_connection(ADS_STRUCT **adsp, const char *dom_name) + } + } + +- status = ads_cached_connection_connect(adsp, realm, dom_name, ldap_server, +- password, realm, 0); ++ status = ads_cached_connection_connect( ++ adsp, /* Returns ads struct. */ ++ wb_dom->alt_name, /* realm to connect to. */ ++ dom_name, /* 'workgroup' name for ads_init */ ++ ldap_server, /* DNS name to connect to. */ ++ password, /* password for auth realm. */ ++ realm, /* realm used for krb5 ticket. */ ++ 0); /* renewable ticket time. */ ++ + SAFE_FREE(realm); + + return status; +-- +1.7.1 + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/09-fix-smbclient-echo-cmd-segfault.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/09-fix-smbclient-echo-cmd-segfault.patch new file mode 100644 index 00000000..a1b05b8c --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/09-fix-smbclient-echo-cmd-segfault.patch @@ -0,0 +1,35 @@ +From 0aab8ae3c137e5900d22160555bcef57cd62ca21 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Wed, 17 Sep 2014 15:17:50 +0200 +Subject: [PATCH 2/2] libcli: Fix a segfault calling smbXcli_req_set_pending() + on NULL. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=10817 + +Signed-off-by: Andreas Schneider +Reviewed-by: Jeremy Allison + +Autobuild-User(master): Jeremy Allison +Autobuild-Date(master): Tue Sep 23 04:23:05 CEST 2014 on sn-devel-104 + +(cherry picked from commit f92086f4a347dcc8fa948aa2614a2c12f1115e5a) +Signed-off-by: Andreas Schneider +--- + libcli/smb/smb1cli_echo.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/libcli/smb/smb1cli_echo.c b/libcli/smb/smb1cli_echo.c +index 4fb7c60..10dff2d 100644 +--- a/libcli/smb/smb1cli_echo.c ++++ b/libcli/smb/smb1cli_echo.c +@@ -96,7 +96,6 @@ static void smb1cli_echo_done(struct tevent_req *subreq) + NULL, /* pbytes_offset */ + NULL, /* pinbuf */ + expected, ARRAY_SIZE(expected)); +- TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; +-- +2.1.0 + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/10-improve-service-principal-guessing-in-net.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/10-improve-service-principal-guessing-in-net.patch new file mode 100644 index 00000000..35f4d8c4 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/10-improve-service-principal-guessing-in-net.patch @@ -0,0 +1,180 @@ +From 579901faf787d8d787c978324bdec87c349e3d9b Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 23 Sep 2014 14:09:41 +0200 +Subject: [PATCH] s3-libads: Improve service principle guessing. + +If the name passed to the net command with the -S options is the long +hostname of the domaincontroller and not the 15 char NetBIOS name we +should construct a FQDN with the realm to get a Kerberos ticket. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=10829 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner +(cherry picked from commit 83c62bd3f5945bbe295cbfbd153736d4c709b3a6) +--- + source3/libads/sasl.c | 124 +++++++++++++++++++++++++++----------------------- + 1 file changed, 66 insertions(+), 58 deletions(-) + +diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c +index 33f4e24..1450ff1 100644 +--- a/source3/libads/sasl.c ++++ b/source3/libads/sasl.c +@@ -714,88 +714,96 @@ static void ads_free_service_principal(struct ads_service_principal *p) + static ADS_STATUS ads_guess_service_principal(ADS_STRUCT *ads, + char **returned_principal) + { ++ ADS_STATUS status = ADS_ERROR(LDAP_NO_MEMORY); + char *princ = NULL; ++ TALLOC_CTX *frame; ++ char *server = NULL; ++ char *realm = NULL; ++ int rc; + +- if (ads->server.realm && ads->server.ldap_server) { +- char *server, *server_realm; +- +- server = SMB_STRDUP(ads->server.ldap_server); +- server_realm = SMB_STRDUP(ads->server.realm); +- +- if (!server || !server_realm) { +- SAFE_FREE(server); +- SAFE_FREE(server_realm); +- return ADS_ERROR(LDAP_NO_MEMORY); +- } ++ frame = talloc_stackframe(); ++ if (frame == NULL) { ++ return ADS_ERROR(LDAP_NO_MEMORY); ++ } + +- if (!strlower_m(server)) { +- SAFE_FREE(server); +- SAFE_FREE(server_realm); +- return ADS_ERROR(LDAP_NO_MEMORY); ++ if (ads->server.realm && ads->server.ldap_server) { ++ server = strlower_talloc(frame, ads->server.ldap_server); ++ if (server == NULL) { ++ goto out; + } + +- if (!strupper_m(server_realm)) { +- SAFE_FREE(server); +- SAFE_FREE(server_realm); +- return ADS_ERROR(LDAP_NO_MEMORY); ++ realm = strupper_talloc(frame, ads->server.realm); ++ if (realm == NULL) { ++ goto out; + } + +- if (asprintf(&princ, "ldap/%s@%s", server, server_realm) == -1) { +- SAFE_FREE(server); +- SAFE_FREE(server_realm); +- return ADS_ERROR(LDAP_NO_MEMORY); +- } ++ /* ++ * If we got a name which is bigger than a NetBIOS name, ++ * but isn't a FQDN, create one. ++ */ ++ if (strlen(server) > 15 && strstr(server, ".") == NULL) { ++ char *dnsdomain; + +- SAFE_FREE(server); +- SAFE_FREE(server_realm); ++ dnsdomain = strlower_talloc(frame, ads->server.realm); ++ if (dnsdomain == NULL) { ++ goto out; ++ } + +- if (!princ) { +- return ADS_ERROR(LDAP_NO_MEMORY); ++ server = talloc_asprintf(frame, ++ "%s.%s", ++ server, dnsdomain); ++ if (server == NULL) { ++ goto out; ++ } + } + } else if (ads->config.realm && ads->config.ldap_server_name) { +- char *server, *server_realm; +- +- server = SMB_STRDUP(ads->config.ldap_server_name); +- server_realm = SMB_STRDUP(ads->config.realm); +- +- if (!server || !server_realm) { +- SAFE_FREE(server); +- SAFE_FREE(server_realm); +- return ADS_ERROR(LDAP_NO_MEMORY); ++ server = strlower_talloc(frame, ads->config.ldap_server_name); ++ if (server == NULL) { ++ goto out; + } + +- if (!strlower_m(server)) { +- SAFE_FREE(server); +- SAFE_FREE(server_realm); +- return ADS_ERROR(LDAP_NO_MEMORY); ++ realm = strupper_talloc(frame, ads->config.realm); ++ if (realm == NULL) { ++ goto out; + } + +- if (!strupper_m(server_realm)) { +- SAFE_FREE(server); +- SAFE_FREE(server_realm); +- return ADS_ERROR(LDAP_NO_MEMORY); +- } +- if (asprintf(&princ, "ldap/%s@%s", server, server_realm) == -1) { +- SAFE_FREE(server); +- SAFE_FREE(server_realm); +- return ADS_ERROR(LDAP_NO_MEMORY); +- } ++ /* ++ * If we got a name which is bigger than a NetBIOS name, ++ * but isn't a FQDN, create one. ++ */ ++ if (strlen(server) > 15 && strstr(server, ".") == NULL) { ++ char *dnsdomain; + +- SAFE_FREE(server); +- SAFE_FREE(server_realm); ++ dnsdomain = strlower_talloc(frame, ads->server.realm); ++ if (dnsdomain == NULL) { ++ goto out; ++ } + +- if (!princ) { +- return ADS_ERROR(LDAP_NO_MEMORY); ++ server = talloc_asprintf(frame, ++ "%s.%s", ++ server, dnsdomain); ++ if (server == NULL) { ++ goto out; ++ } + } + } + +- if (!princ) { +- return ADS_ERROR(LDAP_PARAM_ERROR); ++ if (server == NULL || realm == NULL) { ++ goto out; ++ } ++ ++ rc = asprintf(&princ, "ldap/%s@%s", server, realm); ++ if (rc == -1 || princ == NULL) { ++ status = ADS_ERROR(LDAP_PARAM_ERROR); ++ goto out; + } + + *returned_principal = princ; + +- return ADS_SUCCESS; ++ status = ADS_SUCCESS; ++out: ++ TALLOC_FREE(frame); ++ return status; + } + + static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads, +-- +2.1.0 + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/11-fix-overwriting-of-spns-during-net-ads-join.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/11-fix-overwriting-of-spns-during-net-ads-join.patch new file mode 100644 index 00000000..5d309f11 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/11-fix-overwriting-of-spns-during-net-ads-join.patch @@ -0,0 +1,329 @@ +From 1925edc67e223d73d672af48c2ebd3e5865e01d9 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Wed, 24 Sep 2014 09:22:03 +0200 +Subject: [PATCH 1/4] s3-libads: Add a function to retrieve the SPNs of a + computer account. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=9984 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner +(cherry picked from commit 4eaa4ccbdf279f1ff6d8218b36d92aeea0114cd8) +--- + source3/libads/ads_proto.h | 6 +++++ + source3/libads/ldap.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 66 insertions(+) + +diff --git a/source3/libads/ads_proto.h b/source3/libads/ads_proto.h +index 17a84d1..6a22807 100644 +--- a/source3/libads/ads_proto.h ++++ b/source3/libads/ads_proto.h +@@ -87,6 +87,12 @@ ADS_STATUS ads_add_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods, + const char *name, const char **vals); + uint32 ads_get_kvno(ADS_STRUCT *ads, const char *account_name); + uint32_t ads_get_machine_kvno(ADS_STRUCT *ads, const char *machine_name); ++ ++ADS_STATUS ads_get_service_principal_names(TALLOC_CTX *mem_ctx, ++ ADS_STRUCT *ads, ++ const char *machine_name, ++ char ***spn_array, ++ size_t *num_spns); + ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machine_name); + ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_name, + const char *my_fqdn, const char *spn); +diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c +index fb99132..51a0883 100644 +--- a/source3/libads/ldap.c ++++ b/source3/libads/ldap.c +@@ -1927,6 +1927,66 @@ ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machin + } + + /** ++ * @brief This gets the service principal names of an existing computer account. ++ * ++ * @param[in] mem_ctx The memory context to use to allocate the spn array. ++ * ++ * @param[in] ads The ADS context to use. ++ * ++ * @param[in] machine_name The NetBIOS name of the computer, which is used to ++ * identify the computer account. ++ * ++ * @param[in] spn_array A pointer to store the array for SPNs. ++ * ++ * @param[in] num_spns The number of principals stored in the array. ++ * ++ * @return 0 on success, or a ADS error if a failure occured. ++ */ ++ADS_STATUS ads_get_service_principal_names(TALLOC_CTX *mem_ctx, ++ ADS_STRUCT *ads, ++ const char *machine_name, ++ char ***spn_array, ++ size_t *num_spns) ++{ ++ ADS_STATUS status; ++ LDAPMessage *res = NULL; ++ char *dn; ++ int count; ++ ++ status = ads_find_machine_acct(ads, ++ &res, ++ machine_name); ++ if (!ADS_ERR_OK(status)) { ++ DEBUG(1,("Host Account for %s not found... skipping operation.\n", ++ machine_name)); ++ return status; ++ } ++ ++ count = ads_count_replies(ads, res); ++ if (count != 1) { ++ status = ADS_ERROR(LDAP_NO_SUCH_OBJECT); ++ goto done; ++ } ++ ++ dn = ads_get_dn(ads, mem_ctx, res); ++ if (dn == NULL) { ++ status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); ++ goto done; ++ } ++ ++ *spn_array = ads_pull_strings(ads, ++ mem_ctx, ++ res, ++ "servicePrincipalName", ++ num_spns); ++ ++done: ++ ads_msgfree(ads, res); ++ ++ return status; ++} ++ ++/** + * This adds a service principal name to an existing computer account + * (found by hostname) in AD. + * @param ads An initialized ADS_STRUCT +-- +2.1.0 + + +From ed3b6536e1027a26d7983942f62677aa2bc0e93c Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Wed, 24 Sep 2014 09:23:58 +0200 +Subject: [PATCH 2/4] s3-libads: Add function to search for an element in an + array. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=9984 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner +(cherry picked from commit e1ee4c8bc7018db7787dd9a0be6d3aa40a477ee2) +--- + source3/libads/ads_proto.h | 2 ++ + source3/libads/ldap.c | 31 +++++++++++++++++++++++++++++++ + 2 files changed, 33 insertions(+) + +diff --git a/source3/libads/ads_proto.h b/source3/libads/ads_proto.h +index 6a22807..1e34247 100644 +--- a/source3/libads/ads_proto.h ++++ b/source3/libads/ads_proto.h +@@ -88,6 +88,8 @@ ADS_STATUS ads_add_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods, + uint32 ads_get_kvno(ADS_STRUCT *ads, const char *account_name); + uint32_t ads_get_machine_kvno(ADS_STRUCT *ads, const char *machine_name); + ++bool ads_element_in_array(const char **el_array, size_t num_el, const char *el); ++ + ADS_STATUS ads_get_service_principal_names(TALLOC_CTX *mem_ctx, + ADS_STRUCT *ads, + const char *machine_name, +diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c +index 51a0883..8d104c2 100644 +--- a/source3/libads/ldap.c ++++ b/source3/libads/ldap.c +@@ -1927,6 +1927,37 @@ ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machin + } + + /** ++ * @brief Search for an element in a string array. ++ * ++ * @param[in] el_array The string array to search. ++ * ++ * @param[in] num_el The number of elements in the string array. ++ * ++ * @param[in] el The string to search. ++ * ++ * @return True if found, false if not. ++ */ ++bool ads_element_in_array(const char **el_array, size_t num_el, const char *el) ++{ ++ size_t i; ++ ++ if (el_array == NULL || num_el == 0 || el == NULL) { ++ return false; ++ } ++ ++ for (i = 0; i < num_el && el_array[i] != NULL; i++) { ++ int cmp; ++ ++ cmp = strcasecmp_m(el_array[i], el); ++ if (cmp == 0) { ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++/** + * @brief This gets the service principal names of an existing computer account. + * + * @param[in] mem_ctx The memory context to use to allocate the spn array. +-- +2.1.0 + + +From 11700f1398d6197a99c686f1a43b45d6305ceae8 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Fri, 26 Sep 2014 03:09:08 +0200 +Subject: [PATCH 3/4] s3-libnet: Add libnet_join_get_machine_spns(). + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=9984 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner +(cherry picked from commit 7e0b8fcce5572c88d50993a1dbd90f65638ba90f) +--- + source3/libnet/libnet_join.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c +index 1418385..3611cc7 100644 +--- a/source3/libnet/libnet_join.c ++++ b/source3/libnet/libnet_join.c +@@ -358,6 +358,26 @@ static ADS_STATUS libnet_join_find_machine_acct(TALLOC_CTX *mem_ctx, + return status; + } + ++static ADS_STATUS libnet_join_get_machine_spns(TALLOC_CTX *mem_ctx, ++ struct libnet_JoinCtx *r, ++ char ***spn_array, ++ size_t *num_spns) ++{ ++ ADS_STATUS status; ++ ++ if (r->in.machine_name == NULL) { ++ return ADS_ERROR_SYSTEM(EINVAL); ++ } ++ ++ status = ads_get_service_principal_names(mem_ctx, ++ r->in.ads, ++ r->in.machine_name, ++ spn_array, ++ num_spns); ++ ++ return status; ++} ++ + /**************************************************************** + Set a machines dNSHostName and servicePrincipalName attributes + ****************************************************************/ +-- +2.1.0 + + +From 472256e27ad5cb5e7657efaece71744269ca8d16 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 26 Sep 2014 03:35:43 +0200 +Subject: [PATCH 4/4] s3-libnet: Make sure we do not overwrite precreated SPNs. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=9984 + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider + +Autobuild-User(master): Günther Deschner +Autobuild-Date(master): Fri Sep 26 08:22:45 CEST 2014 on sn-devel-104 + +(cherry picked from commit 0aacbe78bb40d76b65087c2a197c92b0101e625e) +--- + source3/libnet/libnet_join.c | 39 ++++++++++++++++++++++++++++++++++++--- + 1 file changed, 36 insertions(+), 3 deletions(-) + +diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c +index 3611cc7..aa7b5cb 100644 +--- a/source3/libnet/libnet_join.c ++++ b/source3/libnet/libnet_join.c +@@ -388,8 +388,10 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, + ADS_STATUS status; + ADS_MODLIST mods; + fstring my_fqdn; +- const char *spn_array[3] = {NULL, NULL, NULL}; ++ const char **spn_array = NULL; ++ size_t num_spns = 0; + char *spn = NULL; ++ bool ok; + + /* Find our DN */ + +@@ -398,6 +400,14 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, + return status; + } + ++ status = libnet_join_get_machine_spns(mem_ctx, ++ r, ++ discard_const_p(char **, &spn_array), ++ &num_spns); ++ if (!ADS_ERR_OK(status)) { ++ DEBUG(5, ("Retrieving the servicePrincipalNames failed.\n")); ++ } ++ + /* Windows only creates HOST/shortname & HOST/fqdn. */ + + spn = talloc_asprintf(mem_ctx, "HOST/%s", r->in.machine_name); +@@ -407,7 +417,15 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, + if (!strupper_m(spn)) { + return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + } +- spn_array[0] = spn; ++ ++ ok = ads_element_in_array(spn_array, num_spns, spn); ++ if (!ok) { ++ ok = add_string_to_array(spn_array, spn, ++ &spn_array, (int *)&num_spns); ++ if (!ok) { ++ return ADS_ERROR_LDAP(LDAP_NO_MEMORY); ++ } ++ } + + if (!name_to_fqdn(my_fqdn, r->in.machine_name) + || (strchr(my_fqdn, '.') == NULL)) { +@@ -424,8 +442,23 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, + if (!spn) { + return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + } +- spn_array[1] = spn; ++ ++ ok = ads_element_in_array(spn_array, num_spns, spn); ++ if (!ok) { ++ ok = add_string_to_array(spn_array, spn, ++ &spn_array, (int *)&num_spns); ++ if (!ok) { ++ return ADS_ERROR_LDAP(LDAP_NO_MEMORY); ++ } ++ } ++ } ++ ++ /* make sure to NULL terminate the array */ ++ spn_array = talloc_realloc(mem_ctx, spn_array, const char *, num_spns + 1); ++ if (spn_array == NULL) { ++ return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + } ++ spn_array[num_spns] = NULL; + + mods = ads_init_mods(mem_ctx); + if (!mods) { +-- +2.1.0 + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/12-add-precreated-spns-from-AD-during-keytab-generation.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/12-add-precreated-spns-from-AD-during-keytab-generation.patch new file mode 100644 index 00000000..2174e153 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/12-add-precreated-spns-from-AD-during-keytab-generation.patch @@ -0,0 +1,159 @@ +From 3516236ec6eb42f29eda42542b109fa10217e68c Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Wed, 24 Sep 2014 10:51:33 +0200 +Subject: [PATCH] s3-libads: Add all machine account principals to the keytab. + +This adds all SPNs defined in the DC for the computer account to the +keytab using 'net ads keytab create -P'. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=9985 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner +(cherry picked from commit 5d58b92f8fcbc509f4fe2bd3617bcaeada1806b6) +--- + source3/libads/kerberos_keytab.c | 74 ++++++++++++++++++++++++++++------------ + 1 file changed, 52 insertions(+), 22 deletions(-) + +diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c +index 83df088..d13625b 100644 +--- a/source3/libads/kerberos_keytab.c ++++ b/source3/libads/kerberos_keytab.c +@@ -507,20 +507,57 @@ int ads_keytab_create_default(ADS_STRUCT *ads) + krb5_kt_cursor cursor; + krb5_keytab_entry kt_entry; + krb5_kvno kvno; +- int i, found = 0; ++ size_t found = 0; + char *sam_account_name, *upn; + char **oldEntries = NULL, *princ_s[26]; +- TALLOC_CTX *tmpctx = NULL; ++ TALLOC_CTX *frame; + char *machine_name; ++ char **spn_array; ++ size_t num_spns; ++ size_t i; ++ ADS_STATUS status; + +- /* these are the main ones we need */ +- ret = ads_keytab_add_entry(ads, "host"); +- if (ret != 0) { +- DEBUG(1, (__location__ ": ads_keytab_add_entry failed while " +- "adding 'host' principal.\n")); +- return ret; ++ frame = talloc_stackframe(); ++ if (frame == NULL) { ++ ret = -1; ++ goto done; ++ } ++ ++ status = ads_get_service_principal_names(frame, ++ ads, ++ lp_netbios_name(), ++ &spn_array, ++ &num_spns); ++ if (!ADS_ERR_OK(status)) { ++ ret = -1; ++ goto done; + } + ++ for (i = 0; i < num_spns; i++) { ++ char *srv_princ; ++ char *p; ++ ++ srv_princ = strlower_talloc(frame, spn_array[i]); ++ if (srv_princ == NULL) { ++ ret = -1; ++ goto done; ++ } ++ ++ p = strchr_m(srv_princ, '/'); ++ if (p == NULL) { ++ continue; ++ } ++ p[0] = '\0'; ++ ++ /* Add the SPNs found on the DC */ ++ ret = ads_keytab_add_entry(ads, srv_princ); ++ if (ret != 0) { ++ DEBUG(1, ("ads_keytab_add_entry failed while " ++ "adding '%s' principal.\n", ++ spn_array[i])); ++ goto done; ++ } ++ } + + #if 0 /* don't create the CIFS/... keytab entries since no one except smbd + really needs them and we will fall back to verifying against +@@ -543,24 +580,17 @@ int ads_keytab_create_default(ADS_STRUCT *ads) + if (ret) { + DEBUG(1, (__location__ ": could not krb5_init_context: %s\n", + error_message(ret))); +- return ret; +- } +- +- tmpctx = talloc_init(__location__); +- if (!tmpctx) { +- DEBUG(0, (__location__ ": talloc_init() failed!\n")); +- ret = -1; + goto done; + } + +- machine_name = talloc_strdup(tmpctx, lp_netbios_name()); ++ machine_name = talloc_strdup(frame, lp_netbios_name()); + if (!machine_name) { + ret = -1; + goto done; + } + + /* now add the userPrincipalName and sAMAccountName entries */ +- sam_account_name = ads_get_samaccountname(ads, tmpctx, machine_name); ++ sam_account_name = ads_get_samaccountname(ads, frame, machine_name); + if (!sam_account_name) { + DEBUG(0, (__location__ ": unable to determine machine " + "account's name in AD!\n")); +@@ -584,7 +614,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads) + } + + /* remember that not every machine account will have a upn */ +- upn = ads_get_upn(ads, tmpctx, machine_name); ++ upn = ads_get_upn(ads, frame, machine_name); + if (upn) { + ret = ads_keytab_add_entry(ads, upn); + if (ret != 0) { +@@ -596,7 +626,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads) + + /* Now loop through the keytab and update any other existing entries */ + kvno = (krb5_kvno)ads_get_machine_kvno(ads, machine_name); +- if (kvno == -1) { ++ if (kvno == (krb5_kvno)-1) { + DEBUG(1, (__location__ ": ads_get_machine_kvno() failed to " + "determine the system's kvno.\n")); + goto done; +@@ -629,12 +659,12 @@ int ads_keytab_create_default(ADS_STRUCT *ads) + * have a race condition where someone else could add entries after + * we've counted them. Re-open asap to minimise the race. JRA. + */ +- DEBUG(3, (__location__ ": Found %d entries in the keytab.\n", found)); ++ DEBUG(3, (__location__ ": Found %zd entries in the keytab.\n", found)); + if (!found) { + goto done; + } + +- oldEntries = talloc_array(tmpctx, char *, found); ++ oldEntries = talloc_array(frame, char *, found); + if (!oldEntries) { + DEBUG(1, (__location__ ": Failed to allocate space to store " + "the old keytab entries (talloc failed?).\n")); +@@ -708,7 +738,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads) + + done: + TALLOC_FREE(oldEntries); +- TALLOC_FREE(tmpctx); ++ TALLOC_FREE(frame); + + { + krb5_keytab_entry zero_kt_entry; +-- +2.1.0 + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/13-fix-aes-enctype.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/13-fix-aes-enctype.patch new file mode 100644 index 00000000..a939e706 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/13-fix-aes-enctype.patch @@ -0,0 +1,988 @@ +From cbef7b5e10f4477d9f2e648ac6c654eef1165b82 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 24 Sep 2014 22:16:20 +0200 +Subject: [PATCH 1/4] s3-net: add "net ads enctypes {list,set,delete}". +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider +Reviewed-by: Stefan Metzmacher +--- + source3/utils/net_ads.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 308 insertions(+) + +diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c +index 8b8e719..5f18bf4 100644 +--- a/source3/utils/net_ads.c ++++ b/source3/utils/net_ads.c +@@ -2860,6 +2860,306 @@ int net_ads_kerberos(struct net_context *c, int argc, const char **argv) + return net_run_function(c, argc, argv, "net ads kerberos", func); + } + ++static int net_ads_enctype_lookup_account(struct net_context *c, ++ ADS_STRUCT *ads, ++ const char *account, ++ LDAPMessage **res, ++ const char **enctype_str) ++{ ++ const char *filter; ++ const char *attrs[] = { ++ "msDS-SupportedEncryptionTypes", ++ NULL ++ }; ++ int count; ++ int ret = -1; ++ ADS_STATUS status; ++ ++ filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))", ++ account); ++ if (filter == NULL) { ++ goto done; ++ } ++ ++ status = ads_search(ads, res, filter, attrs); ++ if (!ADS_ERR_OK(status)) { ++ d_printf(_("no account found with filter: %s\n"), filter); ++ goto done; ++ } ++ ++ count = ads_count_replies(ads, *res); ++ switch (count) { ++ case 1: ++ break; ++ case 0: ++ d_printf(_("no account found with filter: %s\n"), filter); ++ goto done; ++ default: ++ d_printf(_("multiple accounts found with filter: %s\n"), filter); ++ goto done; ++ } ++ ++ if (enctype_str) { ++ *enctype_str = ads_pull_string(ads, c, *res, ++ "msDS-SupportedEncryptionTypes"); ++ if (*enctype_str == NULL) { ++ d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n")); ++ goto done; ++ } ++ } ++ ++ ret = 0; ++ done: ++ return ret; ++} ++ ++static void net_ads_enctype_dump_enctypes(const char *username, ++ const char *enctype_str) ++{ ++ int enctypes; ++ ++ d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\":\n"), username); ++ ++ enctypes = atoi(enctype_str); ++ ++ printf("[%s] 0x%08x DES-CBC-CRC\n", ++ enctypes & ENC_CRC32 ? "X" : " ", ++ ENC_CRC32); ++ printf("[%s] 0x%08x DES-CBC-MD5\n", ++ enctypes & ENC_RSA_MD5 ? "X" : " ", ++ ENC_RSA_MD5); ++ printf("[%s] 0x%08x RC4-HMAC\n", ++ enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ", ++ ENC_RC4_HMAC_MD5); ++ printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n", ++ enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ", ++ ENC_HMAC_SHA1_96_AES128); ++ printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n", ++ enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ", ++ ENC_HMAC_SHA1_96_AES256); ++} ++ ++static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv) ++{ ++ int ret = -1; ++ ADS_STATUS status; ++ ADS_STRUCT *ads = NULL; ++ LDAPMessage *res = NULL; ++ const char *str = NULL; ++ ++ if (c->display_usage || (argc < 1)) { ++ d_printf( "%s\n" ++ "net ads enctypes list\n" ++ " %s\n", ++ _("Usage:"), ++ _("List supported enctypes")); ++ return 0; ++ } ++ ++ status = ads_startup(c, false, &ads); ++ if (!ADS_ERR_OK(status)) { ++ printf("startup failed\n"); ++ return ret; ++ } ++ ++ ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str); ++ if (ret) { ++ goto done; ++ } ++ ++ net_ads_enctype_dump_enctypes(argv[0], str); ++ ++ ret = 0; ++ done: ++ ads_msgfree(ads, res); ++ ads_destroy(&ads); ++ ++ return ret; ++} ++ ++static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv) ++{ ++ int ret = -1; ++ ADS_STATUS status; ++ ADS_STRUCT *ads; ++ LDAPMessage *res = NULL; ++ const char *etype_list_str; ++ const char *dn; ++ ADS_MODLIST mods; ++ uint32_t etype_list; ++ const char *str; ++ ++ if (c->display_usage || argc < 1) { ++ d_printf( "%s\n" ++ "net ads enctypes set [enctypes]\n" ++ " %s\n", ++ _("Usage:"), ++ _("Set supported enctypes")); ++ return 0; ++ } ++ ++ status = ads_startup(c, false, &ads); ++ if (!ADS_ERR_OK(status)) { ++ printf("startup failed\n"); ++ return ret; ++ } ++ ++ ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL); ++ if (ret) { ++ goto done; ++ } ++ ++ dn = ads_get_dn(ads, c, res); ++ if (dn == NULL) { ++ goto done; ++ } ++ ++ etype_list = ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5; ++#ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96 ++ etype_list |= ENC_HMAC_SHA1_96_AES128; ++#endif ++#ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96 ++ etype_list |= ENC_HMAC_SHA1_96_AES256; ++#endif ++ ++ if (argv[1] != NULL) { ++ sscanf(argv[1], "%i", &etype_list); ++ } ++ ++ etype_list_str = talloc_asprintf(c, "%d", etype_list); ++ if (!etype_list_str) { ++ goto done; ++ } ++ ++ mods = ads_init_mods(c); ++ if (!mods) { ++ goto done; ++ } ++ ++ status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes", ++ etype_list_str); ++ if (!ADS_ERR_OK(status)) { ++ goto done; ++ } ++ ++ status = ads_gen_mod(ads, dn, mods); ++ if (!ADS_ERR_OK(status)) { ++ d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"), ++ ads_errstr(status)); ++ goto done; ++ } ++ ++ ads_msgfree(ads, res); ++ ++ ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str); ++ if (ret) { ++ goto done; ++ } ++ ++ net_ads_enctype_dump_enctypes(argv[0], str); ++ ++ ret = 0; ++ done: ++ ads_msgfree(ads, res); ++ ads_destroy(&ads); ++ ++ return ret; ++} ++ ++static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv) ++{ ++ int ret = -1; ++ ADS_STATUS status; ++ ADS_STRUCT *ads; ++ LDAPMessage *res = NULL; ++ const char *dn; ++ ADS_MODLIST mods; ++ ++ if (c->display_usage || argc < 1) { ++ d_printf( "%s\n" ++ "net ads enctypes delete \n" ++ " %s\n", ++ _("Usage:"), ++ _("Delete supported enctypes")); ++ return 0; ++ } ++ ++ status = ads_startup(c, false, &ads); ++ if (!ADS_ERR_OK(status)) { ++ printf("startup failed\n"); ++ return ret; ++ } ++ ++ ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL); ++ if (ret) { ++ goto done; ++ } ++ ++ dn = ads_get_dn(ads, c, res); ++ if (dn == NULL) { ++ goto done; ++ } ++ ++ mods = ads_init_mods(c); ++ if (!mods) { ++ goto done; ++ } ++ ++ status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes", NULL); ++ if (!ADS_ERR_OK(status)) { ++ goto done; ++ } ++ ++ status = ads_gen_mod(ads, dn, mods); ++ if (!ADS_ERR_OK(status)) { ++ d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"), ++ ads_errstr(status)); ++ goto done; ++ } ++ ++ ret = 0; ++ ++ done: ++ ads_msgfree(ads, res); ++ ads_destroy(&ads); ++ return ret; ++} ++ ++static int net_ads_enctypes(struct net_context *c, int argc, const char **argv) ++{ ++ struct functable func[] = { ++ { ++ "list", ++ net_ads_enctypes_list, ++ NET_TRANSPORT_ADS, ++ N_("List the supported encryption types"), ++ N_("net ads enctypes list\n" ++ " List the supported encryption types") ++ }, ++ { ++ "set", ++ net_ads_enctypes_set, ++ NET_TRANSPORT_ADS, ++ N_("Set the supported encryption types"), ++ N_("net ads enctypes set\n" ++ " Set the supported encryption types") ++ }, ++ { ++ "delete", ++ net_ads_enctypes_delete, ++ NET_TRANSPORT_ADS, ++ N_("Delete the supported encryption types"), ++ N_("net ads enctypes delete\n" ++ " Delete the supported encryption types") ++ }, ++ ++ {NULL, NULL, 0, NULL, NULL} ++ }; ++ ++ return net_run_function(c, argc, argv, "net ads enctypes", func); ++} ++ ++ + int net_ads(struct net_context *c, int argc, const char **argv) + { + struct functable func[] = { +@@ -3015,6 +3315,14 @@ int net_ads(struct net_context *c, int argc, const char **argv) + N_("net ads kerberos\n" + " Manage kerberos keytab") + }, ++ { ++ "enctypes", ++ net_ads_enctypes, ++ NET_TRANSPORT_ADS, ++ N_("List/modify supported encryption types"), ++ N_("net ads enctypes\n" ++ " List/modify enctypes") ++ }, + {NULL, NULL, 0, NULL, NULL} + }; + +-- +1.9.3 + + +From a19f1e51bd7d48b238ad22ec9e27af53dfa5bf44 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 24 Sep 2014 23:36:19 +0200 +Subject: [PATCH 2/4] s3-net: add manpage documentation for "net ads enctypes". +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider +Reviewed-by: Stefan Metzmacher +--- + docs-xml/manpages/net.8.xml | 53 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + +diff --git a/docs-xml/manpages/net.8.xml b/docs-xml/manpages/net.8.xml +index f39b420..9e982e3 100644 +--- a/docs-xml/manpages/net.8.xml ++++ b/docs-xml/manpages/net.8.xml +@@ -1339,6 +1339,59 @@ to show in the result. + + + ++ ADS ENCTYPES ++ ++ ++ List, modify or delete the value of the "msDS-SupportedEncryptionTypes" attribute of an account in AD. ++ ++ ++ ++ This attribute allows to control which Kerberos encryption types are used for the generation of initial and service tickets. The value consists of an integer bitmask with the following values: ++ ++ ++0x00000001 DES-CBC-CRC ++0x00000002 DES-CBC-MD5 ++0x00000004 RC4-HMAC ++0x00000008 AES128-CTS-HMAC-SHA1-96 ++0x00000010 AES256-CTS-HMAC-SHA1-96 ++ ++ ++ ++ ++ ADS ENCTYPES LIST <replaceable><ACCOUNTNAME></replaceable> ++ ++ ++ List the value of the "msDS-SupportedEncryptionTypes" attribute of a given account. ++ ++ ++Example: net ads enctypes list Computername ++ ++ ++ ++ ++ ADS ENCTYPES SET <replaceable><ACCOUNTNAME></replaceable> <replaceable>[enctypes]</replaceable> ++ ++ ++ Set the value of the "msDS-SupportedEncryptionTypes" attribute of the LDAP object of ACCOUNTNAME to a given value. If the value is ommitted, the value is set to 31 which enables all the currently supported encryption types. ++ ++ ++Example: net ads enctypes set Computername 24 ++ ++ ++ ++ ++ ADS ENCTYPES DELETE <replaceable><ACCOUNTNAME></replaceable> ++ ++ ++ Deletes the "msDS-SupportedEncryptionTypes" attribute of the LDAP object of ACCOUNTNAME. ++ ++ ++Example: net ads enctypes set Computername 24 ++ ++ ++ ++ ++ + SAM CREATEBUILTINGROUP <NAME> + + +-- +1.9.3 + + +From 0f42d123afde57ee74d89bdc742185cef718cf0f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 23 Nov 2012 12:34:27 +0100 +Subject: [PATCH 3/4] s3-libnet: set list of allowed krb5 encryption types in + AD >= 2008. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andreas Schneider +Reviewed-by: Stefan Metzmacher +--- + source3/libnet/libnet_join.c | 65 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 65 insertions(+) + +diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c +index 381a59c..e70e11a 100644 +--- a/source3/libnet/libnet_join.c ++++ b/source3/libnet/libnet_join.c +@@ -605,6 +605,52 @@ static ADS_STATUS libnet_join_set_os_attributes(TALLOC_CTX *mem_ctx, + /**************************************************************** + ****************************************************************/ + ++static ADS_STATUS libnet_join_set_etypes(TALLOC_CTX *mem_ctx, ++ struct libnet_JoinCtx *r) ++{ ++ ADS_STATUS status; ++ ADS_MODLIST mods; ++ uint32_t etype_list = ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5; ++ const char *etype_list_str; ++ ++#ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96 ++ etype_list |= ENC_HMAC_SHA1_96_AES128; ++#endif ++#ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96 ++ etype_list |= ENC_HMAC_SHA1_96_AES256; ++#endif ++ ++ etype_list_str = talloc_asprintf(mem_ctx, "%d", etype_list); ++ if (!etype_list_str) { ++ return ADS_ERROR(LDAP_NO_MEMORY); ++ } ++ ++ /* Find our DN */ ++ ++ status = libnet_join_find_machine_acct(mem_ctx, r); ++ if (!ADS_ERR_OK(status)) { ++ return status; ++ } ++ ++ /* now do the mods */ ++ ++ mods = ads_init_mods(mem_ctx); ++ if (!mods) { ++ return ADS_ERROR(LDAP_NO_MEMORY); ++ } ++ ++ status = ads_mod_str(mem_ctx, &mods, "msDS-SupportedEncryptionTypes", ++ etype_list_str); ++ if (!ADS_ERR_OK(status)) { ++ return status; ++ } ++ ++ return ads_gen_mod(r->in.ads, r->out.dn, mods); ++} ++ ++/**************************************************************** ++****************************************************************/ ++ + static bool libnet_join_create_keytab(TALLOC_CTX *mem_ctx, + struct libnet_JoinCtx *r) + { +@@ -679,6 +725,7 @@ static ADS_STATUS libnet_join_post_processing_ads(TALLOC_CTX *mem_ctx, + struct libnet_JoinCtx *r) + { + ADS_STATUS status; ++ uint32_t func_level = 0; + + if (!r->in.ads) { + status = libnet_join_connect_ads(mem_ctx, r); +@@ -713,6 +760,24 @@ static ADS_STATUS libnet_join_post_processing_ads(TALLOC_CTX *mem_ctx, + return status; + } + ++ status = ads_domain_func_level(r->in.ads, &func_level); ++ if (!ADS_ERR_OK(status)) { ++ libnet_join_set_error_string(mem_ctx, r, ++ "failed to query domain controller functional level: %s", ++ ads_errstr(status)); ++ return status; ++ } ++ ++ if (func_level >= DS_DOMAIN_FUNCTION_2008) { ++ status = libnet_join_set_etypes(mem_ctx, r); ++ if (!ADS_ERR_OK(status)) { ++ libnet_join_set_error_string(mem_ctx, r, ++ "failed to set machine kerberos encryption types: %s", ++ ads_errstr(status)); ++ return status; ++ } ++ } ++ + if (!libnet_join_derive_salting_principal(mem_ctx, r)) { + return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); + } +-- +1.9.3 + + +From adb206481ac56c8f438e70f7b9e986aeba9586b1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Fri, 26 Sep 2014 21:06:38 +0200 +Subject: [PATCH 4/4] s4-auth/kerberos: fix salting principal, make sure + hostname is lowercase. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Found at MS interop event while working on AES kerberos key support. + +Guenther + +Signed-off-by: Günther Deschner +Reviewed-by: Andrew Bartlett +--- + source4/auth/kerberos/srv_keytab.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source4/auth/kerberos/srv_keytab.c b/source4/auth/kerberos/srv_keytab.c +index d81e27d..3baba14 100644 +--- a/source4/auth/kerberos/srv_keytab.c ++++ b/source4/auth/kerberos/srv_keytab.c +@@ -143,7 +143,7 @@ static krb5_error_code salt_principal(TALLOC_CTX *parent_ctx, + return ENOMEM; + } + +- machine_username = talloc_strdup(tmp_ctx, samAccountName); ++ machine_username = strlower_talloc(tmp_ctx, samAccountName); + if (!machine_username) { + *error_string = "Cannot duplicate samAccountName"; + talloc_free(tmp_ctx); +-- +1.9.3 + +From d423e8b759af2e0a7cdce39d3f7a6c8d9c1764b4 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Mon, 16 Jun 2014 22:49:29 -0700 +Subject: [PATCH 1/5] s3: auth: Add some const to the struct netr_SamInfo3 * + arguments of copy_netr_SamInfo3() and make_server_info_info3() + +Both functions only read from the struct netr_SamInfo3 * argument. + +Signed-off-by: Jeremy Allison +Reviewed-by: Richard Sharpe +Reviewed-by: Simo Sorce + +Conflicts: + source3/auth/proto.h + source3/auth/server_info.c +--- + source3/auth/auth_util.c | 2 +- + source3/auth/proto.h | 4 ++-- + source3/auth/server_info.c | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c +index ceaa706..afa78ec 100644 +--- a/source3/auth/auth_util.c ++++ b/source3/auth/auth_util.c +@@ -1369,7 +1369,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, + const char *sent_nt_username, + const char *domain, + struct auth_serversupplied_info **server_info, +- struct netr_SamInfo3 *info3) ++ const struct netr_SamInfo3 *info3) + { + static const char zeros[16] = {0, }; + +diff --git a/source3/auth/proto.h b/source3/auth/proto.h +index 76661fc..6ec206e 100644 +--- a/source3/auth/proto.h ++++ b/source3/auth/proto.h +@@ -232,7 +232,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, + const char *sent_nt_username, + const char *domain, + struct auth_serversupplied_info **server_info, +- struct netr_SamInfo3 *info3); ++ const struct netr_SamInfo3 *info3); + struct wbcAuthUserInfo; + NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx, + const char *sent_nt_username, +@@ -287,7 +287,7 @@ NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx, + const struct passwd *pwd, + struct netr_SamInfo3 **pinfo3); + struct netr_SamInfo3 *copy_netr_SamInfo3(TALLOC_CTX *mem_ctx, +- struct netr_SamInfo3 *orig); ++ const struct netr_SamInfo3 *orig); + struct netr_SamInfo3 *wbcAuthUserInfo_to_netr_SamInfo3(TALLOC_CTX *mem_ctx, + const struct wbcAuthUserInfo *info); + +diff --git a/source3/auth/server_info.c b/source3/auth/server_info.c +index d2b7d6e..066b9a8 100644 +--- a/source3/auth/server_info.c ++++ b/source3/auth/server_info.c +@@ -445,7 +445,7 @@ NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx, + } } while(0) + + struct netr_SamInfo3 *copy_netr_SamInfo3(TALLOC_CTX *mem_ctx, +- struct netr_SamInfo3 *orig) ++ const struct netr_SamInfo3 *orig) + { + struct netr_SamInfo3 *info3; + unsigned int i; +-- +1.9.3 + + +From cab0cda9df0bb0eda2d7957c0bb8dbcb51ba7ef7 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Mon, 16 Jun 2014 22:54:45 -0700 +Subject: [PATCH 2/5] s3: auth: Change make_server_info_info3() to take a const + struct netr_SamInfo3 pointer instead of a struct PAC_LOGON_INFO. + +make_server_info_info3() only reads from the info3 pointer. + +Signed-off-by: Jeremy Allison +Reviewed-by: Richard Sharpe +Reviewed-by: Simo Sorce +--- + source3/auth/auth_generic.c | 2 +- + source3/auth/proto.h | 2 +- + source3/auth/user_krb5.c | 8 ++++---- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c +index a2ba4e3..2880bc9 100644 +--- a/source3/auth/auth_generic.c ++++ b/source3/auth/auth_generic.c +@@ -112,7 +112,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + + status = make_session_info_krb5(mem_ctx, + ntuser, ntdomain, username, pw, +- logon_info, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, ++ &logon_info->info3, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, + session_info); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n", +diff --git a/source3/auth/proto.h b/source3/auth/proto.h +index 6ec206e..75d1097 100644 +--- a/source3/auth/proto.h ++++ b/source3/auth/proto.h +@@ -357,7 +357,7 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, + char *ntdomain, + char *username, + struct passwd *pw, +- struct PAC_LOGON_INFO *logon_info, ++ const struct netr_SamInfo3 *info3, + bool mapped_to_guest, bool username_was_mapped, + DATA_BLOB *session_key, + struct auth_session_info **session_info); +diff --git a/source3/auth/user_krb5.c b/source3/auth/user_krb5.c +index 974a8aa..0a538b4 100644 +--- a/source3/auth/user_krb5.c ++++ b/source3/auth/user_krb5.c +@@ -186,7 +186,7 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, + char *ntdomain, + char *username, + struct passwd *pw, +- struct PAC_LOGON_INFO *logon_info, ++ const struct netr_SamInfo3 *info3, + bool mapped_to_guest, bool username_was_mapped, + DATA_BLOB *session_key, + struct auth_session_info **session_info) +@@ -202,14 +202,14 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, + return status; + } + +- } else if (logon_info) { ++ } else if (info3) { + /* pass the unmapped username here since map_username() + will be called again in make_server_info_info3() */ + + status = make_server_info_info3(mem_ctx, + ntuser, ntdomain, + &server_info, +- &logon_info->info3); ++ info3); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("make_server_info_info3 failed: %s!\n", + nt_errstr(status))); +@@ -299,7 +299,7 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, + char *ntdomain, + char *username, + struct passwd *pw, +- struct PAC_LOGON_INFO *logon_info, ++ const struct netr_SamInfo3 *info3, + bool mapped_to_guest, bool username_was_mapped, + DATA_BLOB *session_key, + struct auth_session_info **session_info) +-- +1.9.3 + + +From 102335441aaa7967367abcc5690fe7229807546a Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Mon, 16 Jun 2014 23:11:58 -0700 +Subject: [PATCH 3/5] s3: auth: Add create_info3_from_pac_logon_info() to + create a new info3 and merge resource group SIDs into it. + +Originally written by Richard Sharpe Richard Sharpe . + +Signed-off-by: Jeremy Allison +Reviewed-by: Richard Sharpe +Reviewed-by: Simo Sorce +--- + source3/auth/proto.h | 3 ++ + source3/auth/server_info.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 80 insertions(+) + +diff --git a/source3/auth/proto.h b/source3/auth/proto.h +index 75d1097..cc51698 100644 +--- a/source3/auth/proto.h ++++ b/source3/auth/proto.h +@@ -281,6 +281,9 @@ NTSTATUS serverinfo_to_SamInfo3(const struct auth_serversupplied_info *server_in + struct netr_SamInfo3 *sam3); + NTSTATUS serverinfo_to_SamInfo6(struct auth_serversupplied_info *server_info, + struct netr_SamInfo6 *sam6); ++NTSTATUS create_info3_from_pac_logon_info(TALLOC_CTX *mem_ctx, ++ const struct PAC_LOGON_INFO *logon_info, ++ struct netr_SamInfo3 **pp_info3); + NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx, + struct samu *samu, + const char *login_server, +diff --git a/source3/auth/server_info.c b/source3/auth/server_info.c +index 066b9a8..dc84794 100644 +--- a/source3/auth/server_info.c ++++ b/source3/auth/server_info.c +@@ -252,6 +252,83 @@ static NTSTATUS group_sids_to_info3(struct netr_SamInfo3 *info3, + return NT_STATUS_OK; + } + ++/* ++ * Merge resource SIDs, if any, into the passed in info3 structure. ++ */ ++ ++static NTSTATUS merge_resource_sids(const struct PAC_LOGON_INFO *logon_info, ++ struct netr_SamInfo3 *info3) ++{ ++ uint32_t i = 0; ++ ++ if (!(logon_info->info3.base.user_flags & NETLOGON_RESOURCE_GROUPS)) { ++ return NT_STATUS_OK; ++ } ++ ++ /* ++ * If there are any resource groups (SID Compression) add ++ * them to the extra sids portion of the info3 in the PAC. ++ * ++ * This makes the info3 look like it would if we got the info ++ * from the DC rather than the PAC. ++ */ ++ ++ /* ++ * Construct a SID for each RID in the list and then append it ++ * to the info3. ++ */ ++ for (i = 0; i < logon_info->res_groups.count; i++) { ++ NTSTATUS status; ++ struct dom_sid new_sid; ++ uint32_t attributes = logon_info->res_groups.rids[i].attributes; ++ ++ sid_compose(&new_sid, ++ logon_info->res_group_dom_sid, ++ logon_info->res_groups.rids[i].rid); ++ ++ DEBUG(10, ("Adding SID %s to extra SIDS\n", ++ sid_string_dbg(&new_sid))); ++ ++ status = append_netr_SidAttr(info3, &info3->sids, ++ &info3->sidcount, ++ &new_sid, ++ attributes); ++ if (!NT_STATUS_IS_OK(status)) { ++ DEBUG(1, ("failed to append SID %s to extra SIDS: %s\n", ++ sid_string_dbg(&new_sid), ++ nt_errstr(status))); ++ return status; ++ } ++ } ++ ++ return NT_STATUS_OK; ++} ++ ++/* ++ * Create a copy of an info3 struct from the struct PAC_LOGON_INFO, ++ * then merge resource SIDs, if any, into it. If successful return ++ * the created info3 struct. ++ */ ++ ++NTSTATUS create_info3_from_pac_logon_info(TALLOC_CTX *mem_ctx, ++ const struct PAC_LOGON_INFO *logon_info, ++ struct netr_SamInfo3 **pp_info3) ++{ ++ NTSTATUS status; ++ struct netr_SamInfo3 *info3 = copy_netr_SamInfo3(mem_ctx, ++ &logon_info->info3); ++ if (info3 == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ status = merge_resource_sids(logon_info, info3); ++ if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(info3); ++ return status; ++ } ++ *pp_info3 = info3; ++ return NT_STATUS_OK; ++} ++ + #define RET_NOMEM(ptr) do { \ + if (!ptr) { \ + TALLOC_FREE(info3); \ +-- +1.9.3 + + +From fda9cefd3d4a0808af67595631dd755d5b73aacf Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Mon, 16 Jun 2014 23:15:21 -0700 +Subject: [PATCH 4/5] s3: auth: Change auth3_generate_session_info_pac() to use + a copy of the info3 struct from the struct PAC_LOGON_INFO. + +Call create_info3_from_pac_logon_info() to add in any resource SIDs +from the struct PAC_LOGON_INFO to the info3. + +Signed-off-by: Jeremy Allison +Reviewed-by: Richard Sharpe +Reviewed-by: Simo Sorce +--- + source3/auth/auth_generic.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c +index 2880bc9..f841f0c 100644 +--- a/source3/auth/auth_generic.c ++++ b/source3/auth/auth_generic.c +@@ -44,6 +44,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + { + TALLOC_CTX *tmp_ctx; + struct PAC_LOGON_INFO *logon_info = NULL; ++ struct netr_SamInfo3 *info3_copy = NULL; + bool is_mapped; + bool is_guest; + char *ntuser; +@@ -101,7 +102,13 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + + /* save the PAC data if we have it */ + if (logon_info) { +- netsamlogon_cache_store(ntuser, &logon_info->info3); ++ status = create_info3_from_pac_logon_info(tmp_ctx, ++ logon_info, ++ &info3_copy); ++ if (!NT_STATUS_IS_OK(status)) { ++ goto done; ++ } ++ netsamlogon_cache_store(ntuser, info3_copy); + } + + /* setup the string used by %U */ +@@ -112,7 +119,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + + status = make_session_info_krb5(mem_ctx, + ntuser, ntdomain, username, pw, +- &logon_info->info3, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, ++ info3_copy, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, + session_info); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n", +-- +1.9.3 + + +From 9ed711f88685fc2d4860c9d6b7fa651bd2a52558 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Mon, 16 Jun 2014 23:27:35 -0700 +Subject: [PATCH 5/5] s3: auth: Fix winbindd_pam_auth_pac_send() to create a + new info3 and merge in resource groups from a trusted PAC. + +Based on a patch from Richard Sharpe . + +Signed-off-by: Jeremy Allison +Reviewed-by: Richard Sharpe +Reviewed-by: Simo Sorce + +Autobuild-User(master): Jeremy Allison +Autobuild-Date(master): Wed Jun 18 03:30:36 CEST 2014 on sn-devel-104 +--- + source3/winbindd/winbindd_pam.c | 24 ++++++++++++++++++++++-- + 1 file changed, 22 insertions(+), 2 deletions(-) + +diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c +index c356686..0f1ca28 100644 +--- a/source3/winbindd/winbindd_pam.c ++++ b/source3/winbindd/winbindd_pam.c +@@ -2421,6 +2421,7 @@ NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state, + struct winbindd_request *req = state->request; + DATA_BLOB pac_blob; + struct PAC_LOGON_INFO *logon_info = NULL; ++ struct netr_SamInfo3 *info3_copy = NULL; + NTSTATUS result; + + pac_blob = data_blob_const(req->extra_data.data, req->extra_len); +@@ -2434,7 +2435,13 @@ NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state, + + if (logon_info) { + /* Signature verification succeeded, trust the PAC */ +- netsamlogon_cache_store(NULL, &logon_info->info3); ++ result = create_info3_from_pac_logon_info(state->mem_ctx, ++ logon_info, ++ &info3_copy); ++ if (!NT_STATUS_IS_OK(result)) { ++ return result; ++ } ++ netsamlogon_cache_store(NULL, info3_copy); + + } else { + /* Try without signature verification */ +@@ -2446,9 +2453,22 @@ NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state, + nt_errstr(result))); + return result; + } ++ if (logon_info) { ++ /* ++ * Don't strictly need to copy here, ++ * but it makes it explicit we're ++ * returning a copy talloc'ed off ++ * the state->mem_ctx. ++ */ ++ info3_copy = copy_netr_SamInfo3(state->mem_ctx, ++ &logon_info->info3); ++ if (info3_copy == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ } + } + +- *info3 = &logon_info->info3; ++ *info3 = info3_copy; + + return NT_STATUS_OK; + } +-- +1.9.3 + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/14-fix-dnsupdate.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/14-fix-dnsupdate.patch new file mode 100644 index 00000000..071069b9 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/14-fix-dnsupdate.patch @@ -0,0 +1,51 @@ +From 3bf805a38a1b901a55b08118ec04097d9787497c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Mon, 29 Sep 2014 17:16:15 +0200 +Subject: [PATCH] s3-net: Force libkrb5 locator to use the same KDC for join + and DNS update. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Guenther + +Signed-off-by: Günther Deschner +--- + source3/utils/net_ads.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c +index e96377f..efbc3d2 100644 +--- a/source3/utils/net_ads.c ++++ b/source3/utils/net_ads.c +@@ -1566,6 +1566,27 @@ int net_ads_join(struct net_context *c, int argc, const char **argv) + * If the dns update fails, we still consider the join + * operation as succeeded if we came this far. + */ ++ ++ if (r->out.dns_domain_name != NULL) { ++ ++ /* Avoid potential libkrb5 issues finding a good KDC when we ++ * already found one during the join. When the locator plugin is ++ * installed (but winbind is not yet running) make sure we can ++ * force libkrb5 to reuse that KDC. - gd */ ++ ++ char *env; ++ ++ env = talloc_asprintf_strupper_m(r, ++ "WINBINDD_LOCATOR_KDC_ADDRESS_%s", ++ r->out.dns_domain_name); ++ if (env == NULL) { ++ return -1; ++ } ++ ++ setenv(env, r->in.ads->auth.kdc_server, 0); ++ setenv("_NO_WINBINDD", "1", 0); ++ } ++ + _net_ads_join_dns_updates(c, ctx, r); + + TALLOC_FREE(r); +-- +1.9.3 + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/15-fix-netbios-name-truncation.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/15-fix-netbios-name-truncation.patch new file mode 100644 index 00000000..9721afa1 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/15-fix-netbios-name-truncation.patch @@ -0,0 +1,154 @@ +From 170166b8a0076089c6a8505f53a22f5b72c15786 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Tue, 28 Oct 2014 11:55:30 -0700 +Subject: [PATCH] s3-nmbd: Fix netbios name truncation. + +Try and cope with truncation more intelligently. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=10896 + +Signed-off-by: Jeremy Allison +Reviewed-by: Andreas Schneider +(cherry picked from commit 6adcc7bffd5e1474ecba04d2328955c0b208cabc) +Signed-off-by: Andreas Schneider +--- + source3/nmbd/nmbd_nameregister.c | 76 +++++++++++++++++++++++++++++++++++----- + 1 file changed, 68 insertions(+), 8 deletions(-) + +diff --git a/source3/nmbd/nmbd_nameregister.c b/source3/nmbd/nmbd_nameregister.c +index 71c4751..8b078e6 100644 +--- a/source3/nmbd/nmbd_nameregister.c ++++ b/source3/nmbd/nmbd_nameregister.c +@@ -482,17 +482,77 @@ void register_name(struct subnet_record *subrec, + { + struct nmb_name nmbname; + nstring nname; ++ size_t converted_size; + + errno = 0; +- push_ascii_nstring(nname, name); +- if (errno == E2BIG) { +- unstring tname; +- pull_ascii_nstring(tname, sizeof(tname), nname); +- DEBUG(0,("register_name: NetBIOS name %s is too long. Truncating to %s\n", +- name, tname)); +- make_nmb_name(&nmbname, tname, type); +- } else { ++ converted_size = push_ascii_nstring(nname, name); ++ if (converted_size != (size_t)-1) { ++ /* Success. */ + make_nmb_name(&nmbname, name, type); ++ } else if (errno == E2BIG) { ++ /* ++ * Name converted to CH_DOS is too large. ++ * try to truncate. ++ */ ++ char *converted_str_dos = NULL; ++ char *converted_str_unix = NULL; ++ bool ok; ++ ++ converted_size = 0; ++ ++ ok = convert_string_talloc(talloc_tos(), ++ CH_UNIX, ++ CH_DOS, ++ name, ++ strlen(name)+1, ++ &converted_str_dos, ++ &converted_size); ++ if (!ok) { ++ DEBUG(0,("register_name: NetBIOS name %s cannot be " ++ "converted. Failing to register name.\n", ++ name)); ++ return; ++ } ++ ++ /* ++ * As it's now CH_DOS codepage ++ * we truncate by writing '\0' at ++ * MAX_NETBIOSNAME_LEN-1 and then ++ * convert back to CH_UNIX which we ++ * need for the make_nmb_name() call. ++ */ ++ if (converted_size >= MAX_NETBIOSNAME_LEN) { ++ converted_str_dos[MAX_NETBIOSNAME_LEN-1] = '\0'; ++ } ++ ++ ok = convert_string_talloc(talloc_tos(), ++ CH_DOS, ++ CH_UNIX, ++ converted_str_dos, ++ strlen(converted_str_dos)+1, ++ &converted_str_unix, ++ &converted_size); ++ if (!ok) { ++ DEBUG(0,("register_name: NetBIOS name %s cannot be " ++ "converted back to CH_UNIX. " ++ "Failing to register name.\n", ++ converted_str_dos)); ++ TALLOC_FREE(converted_str_dos); ++ return; ++ } ++ ++ make_nmb_name(&nmbname, converted_str_unix, type); ++ ++ TALLOC_FREE(converted_str_dos); ++ TALLOC_FREE(converted_str_unix); ++ } else { ++ /* ++ * Generic conversion error. Fail to register. ++ */ ++ DEBUG(0,("register_name: NetBIOS name %s cannot be " ++ "converted (%s). Failing to register name.\n", ++ name, strerror(errno))); ++ return; + } + + /* Always set the NB_ACTIVE flag on the name we are +-- +2.1.2 + +From 653a1c312e6b85f1d8113beec52a27e0ba71ef79 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Fri, 31 Oct 2014 11:01:26 -0700 +Subject: [PATCH] s3: nmbd: Ensure NetBIOS names are only 15 characters stored. + +This screws up if the name is greater than MAX_NETBIOSNAME_LEN-1 in the +unix charset, but less than or equal to MAX_NETBIOSNAME_LEN-1 in the DOS +charset, but this is so old we have to live with that. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=10920 + +Signed-off-by: Jeremy Allison +Reviewed-by: Andreas Schneider + +(cherry picked from commit 7467f6e72cba214eeca75c34e9d9fba354c7ef31) +Signed-off-by: Andreas Schneider +--- + source3/lib/util_names.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/source3/lib/util_names.c b/source3/lib/util_names.c +index cf54a0e..1392b48 100644 +--- a/source3/lib/util_names.c ++++ b/source3/lib/util_names.c +@@ -60,7 +60,15 @@ static bool set_my_netbios_names(const char *name, int i) + { + SAFE_FREE(smb_my_netbios_names[i]); + +- smb_my_netbios_names[i] = SMB_STRDUP(name); ++ /* ++ * Don't include space for terminating '\0' in strndup, ++ * it is automatically added. This screws up if the name ++ * is greater than MAX_NETBIOSNAME_LEN-1 in the unix ++ * charset, but less than or equal to MAX_NETBIOSNAME_LEN-1 ++ * in the DOS charset, but this is so old we have to live ++ * with that. ++ */ ++ smb_my_netbios_names[i] = SMB_STRNDUP(name, MAX_NETBIOSNAME_LEN-1); + if (!smb_my_netbios_names[i]) + return False; + return strupper_m(smb_my_netbios_names[i]); +-- +2.1.2 + diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/16-do-not-check-xsltproc-manpages.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/16-do-not-check-xsltproc-manpages.patch new file mode 100644 index 00000000..447e243b --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/16-do-not-check-xsltproc-manpages.patch @@ -0,0 +1,52 @@ +Don't check xsltproc manpages + +Signed-off-by: Bian Naimeng + +diff -Nurp samba-4.1.12.orig/lib/ldb/wscript samba-4.1.12/lib/ldb/wscript +--- samba-4.1.12.orig/lib/ldb/wscript 2014-07-28 16:13:45.000000000 +0900 ++++ samba-4.1.12/lib/ldb/wscript 2015-04-23 17:08:45.277000225 +0900 +@@ -56,7 +56,7 @@ def configure(conf): + conf.define('USING_SYSTEM_PYLDB_UTIL', 1) + + if conf.env.standalone_ldb: +- conf.CHECK_XSLTPROC_MANPAGES() ++ #conf.CHECK_XSLTPROC_MANPAGES() + + # we need this for the ldap backend + if conf.CHECK_FUNCS_IN('ber_flush ldap_open ldap_initialize', 'lber ldap', headers='lber.h ldap.h'): +diff -Nurp samba-4.1.12.orig/lib/ntdb/wscript samba-4.1.12/lib/ntdb/wscript +--- samba-4.1.12.orig/lib/ntdb/wscript 2013-12-05 18:16:48.000000000 +0900 ++++ samba-4.1.12/lib/ntdb/wscript 2015-04-23 17:09:17.680000274 +0900 +@@ -121,7 +121,7 @@ def configure(conf): + Logs.warn('Disabling pyntdb as python devel libs not found') + conf.env.disable_python = True + +- conf.CHECK_XSLTPROC_MANPAGES() ++ #conf.CHECK_XSLTPROC_MANPAGES() + + # This make #include work. + conf.ADD_EXTRA_INCLUDES('''#lib''') +diff -Nurp samba-4.1.12.orig/lib/talloc/wscript samba-4.1.12/lib/talloc/wscript +--- samba-4.1.12.orig/lib/talloc/wscript 2013-12-05 18:16:48.000000000 +0900 ++++ samba-4.1.12/lib/talloc/wscript 2015-04-23 17:08:21.781000339 +0900 +@@ -55,7 +55,7 @@ def configure(conf): + if conf.env.standalone_talloc: + conf.env.TALLOC_COMPAT1 = Options.options.TALLOC_COMPAT1 + +- conf.CHECK_XSLTPROC_MANPAGES() ++ #conf.CHECK_XSLTPROC_MANPAGES() + + if not conf.env.disable_python: + # also disable if we don't have the python libs installed +diff -Nurp samba-4.1.12.orig/lib/tdb/wscript samba-4.1.12/lib/tdb/wscript +--- samba-4.1.12.orig/lib/tdb/wscript 2013-12-05 18:16:48.000000000 +0900 ++++ samba-4.1.12/lib/tdb/wscript 2015-04-23 17:09:02.538000343 +0900 +@@ -43,7 +43,7 @@ def configure(conf): + + conf.env.disable_python = getattr(Options.options, 'disable_python', False) + +- conf.CHECK_XSLTPROC_MANPAGES() ++ #conf.CHECK_XSLTPROC_MANPAGES() + + if not conf.env.disable_python: + # also disable if we don't have the python libs installed diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/17-execute-prog-by-qemu.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/17-execute-prog-by-qemu.patch new file mode 100644 index 00000000..1a31e0d0 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/17-execute-prog-by-qemu.patch @@ -0,0 +1,22 @@ +samba: execute prog on target directly is impossible. + +Signed-off-by: Bian Naimeng + +diff -Nurp samba-4.1.12.orig/lib/ccan/wscript samba-4.1.12/lib/ccan/wscript +--- samba-4.1.12.orig/lib/ccan/wscript 2013-06-13 18:21:02.000000000 +0900 ++++ samba-4.1.12/lib/ccan/wscript 2015-04-27 14:26:25.123000238 +0900 +@@ -127,10 +127,10 @@ def configure(conf): + # Only check for FILE_OFFSET_BITS=64 if off_t is normally small: + # use raw routines because wrappers include previous _GNU_SOURCE + # or _FILE_OFFSET_BITS defines. +- conf.check(fragment="""#include +- int main(void) { return !(sizeof(off_t) < 8); }""", +- execute=True, msg='Checking for small off_t', +- define_name='SMALL_OFF_T') ++ conf.CHECK_CODE("""#include ++ int main(void) { return !(sizeof(off_t) < 8); }""", ++ link=True, execute=True, addmain=False, msg='Checking for small off_t', ++ define='HAVE_SMALL_OFF_T') + # Unreliable return value above, hence use define. + if conf.CONFIG_SET('SMALL_OFF_T'): + conf.check(fragment="""#include diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/18-avoid-get-config-by-native-ncurses.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/18-avoid-get-config-by-native-ncurses.patch new file mode 100644 index 00000000..83c42eb6 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/18-avoid-get-config-by-native-ncurses.patch @@ -0,0 +1,22 @@ +waf trys to get package's configuration by native ncurses6-config. +it will make native header files and library be used. + +Signed-off-by: Bian Naimeng + +--- samba-4.1.12.orig/source3/wscript_configure_system_ncurses 2013-12-05 18:16:48.000000000 +0900 ++++ samba-4.1.12/source3/wscript_configure_system_ncurses 2015-04-29 16:12:22.619000250 +0900 +@@ -2,14 +2,6 @@ import Logs, Options, sys + + Logs.info("Looking for ncurses features") + +-conf.find_program('ncurses5-config', var='NCURSES_CONFIG') +-if not conf.env.NCURSES_CONFIG: +- conf.find_program('ncurses6-config', var='NCURSES_CONFIG') +- +-if conf.env.NCURSES_CONFIG: +- conf.check_cfg(path=conf.env.NCURSES_CONFIG, args="--cflags --libs", +- package="", uselib_store="NCURSES") +- + conf.CHECK_HEADERS('ncurses.h menu.h panel.h form.h', lib='ncurses') + + conf.CHECK_FUNCS_IN('initscr', 'ncurses') diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/19-systemd-daemon-is-contained-by-libsystemd.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/19-systemd-daemon-is-contained-by-libsystemd.patch new file mode 100644 index 00000000..8c4e2ad5 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/19-systemd-daemon-is-contained-by-libsystemd.patch @@ -0,0 +1,42 @@ +systemd-daemon is contained by libsystemd, so we just need link libsystemd to +obtain the implementation of systemd-daemon's function. + +Signed-off-by: Bian Naimeng + +diff -Nurp samba-4.1.12.orig/lib/util/wscript_build samba-4.1.12/lib/util/wscript_build +--- samba-4.1.12.orig/lib/util/wscript_build 2014-09-08 18:26:14.000000000 +0900 ++++ samba-4.1.12/lib/util/wscript_build 2015-04-29 16:16:58.303000207 +0900 +@@ -10,7 +10,7 @@ bld.SAMBA_LIBRARY('samba-util', + server_id.c dprintf.c parmlist.c bitmap.c pidfile.c + tevent_debug.c util_process.c memcache.c''', + deps='DYNCONFIG', +- public_deps='talloc tevent execinfo uid_wrapper pthread LIBCRYPTO charset util_setid systemd-daemon', ++ public_deps='talloc tevent execinfo uid_wrapper pthread LIBCRYPTO charset util_setid systemd', + public_headers='debug.h attr.h byteorder.h data_blob.h memory.h safe_string.h time.h talloc_stack.h xfile.h dlinklist.h samba_util.h string_wrappers.h', + header_path= [ ('dlinklist.h samba_util.h', '.'), ('*', 'util') ], + local_include=False, +diff -Nurp samba-4.1.12.orig/wscript samba-4.1.12/wscript +--- samba-4.1.12.orig/wscript 2014-07-28 16:13:45.000000000 +0900 ++++ samba-4.1.12/wscript 2015-04-29 16:17:52.338000264 +0900 +@@ -183,16 +183,16 @@ def configure(conf): + conf.env['ENABLE_PIE'] = True + + if Options.options.enable_systemd != False: +- conf.check_cfg(package='libsystemd-daemon', args='--cflags --libs', +- msg='Checking for libsystemd-daemon', uselib_store="SYSTEMD-DAEMON") +- conf.CHECK_HEADERS('systemd/sd-daemon.h', lib='systemd-daemon') +- conf.CHECK_LIB('systemd-daemon', shlib=True) ++ conf.check_cfg(package='libsystemd', args='--cflags --libs', ++ msg='Checking for libsystemd', uselib_store="SYSTEMD-DAEMON") ++ conf.CHECK_HEADERS('systemd/sd-daemon.h', lib='systemd') ++ conf.CHECK_LIB('systemd', shlib=True) + + if conf.CONFIG_SET('HAVE_SYSTEMD_SD_DAEMON_H'): + conf.DEFINE('HAVE_SYSTEMD', '1') + conf.env['ENABLE_SYSTEMD'] = True + else: +- conf.SET_TARGET_TYPE('systemd-daemon', 'EMPTY') ++ conf.SET_TARGET_TYPE('systemd', 'EMPTY') + conf.undefine('HAVE_SYSTEMD') + + conf.SAMBA_CONFIG_H('include/config.h') diff --git a/meta-oe/recipes-connectivity/samba/samba-4.1.12/20-do-not-import-target-module-in-configure.patch b/meta-oe/recipes-connectivity/samba/samba-4.1.12/20-do-not-import-target-module-in-configure.patch new file mode 100644 index 00000000..bf6b2902 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba-4.1.12/20-do-not-import-target-module-in-configure.patch @@ -0,0 +1,28 @@ +--- samba-4.1.12.orig/buildtools/wafsamba/samba_bundled.py 2013-06-13 18:21:02.000000000 +0900 ++++ samba-4.1.12/buildtools/wafsamba/samba_bundled.py 2015-06-15 10:57:52.064000328 +0900 +@@ -1,7 +1,7 @@ + # functions to support bundled libraries + + from Configure import conf +-import sys, Logs ++import sys, Logs, imp + from samba_utils import * + + def PRIVATE_NAME(bld, name, private_extension, private_library): +@@ -232,6 +232,16 @@ def CHECK_BUNDLED_SYSTEM_PYTHON(conf, li + m = __import__(modulename) + except ImportError: + found = False ++ ++ build_arch = os.environ["BUILD_ARCH"] ++ host_arch = os.environ["HOST_ARCH"] ++ if build_arch != host_arch: ++ # Some modules maybe can not be imported while cross compile ++ # We just check whether the module exist ++ stuff = imp.find_module(modulename, [os.environ["PYTHONPATH"]]) ++ if stuff != None: ++ Logs.warn('Cross module[%s] has been found, but can not be loaded.' % (stuff[1])) ++ found = True + else: + try: + version = m.__version__ diff --git a/meta-oe/recipes-connectivity/samba/samba-basic.inc b/meta-oe/recipes-connectivity/samba/samba-basic.inc deleted file mode 100644 index 9393c2c1..00000000 --- a/meta-oe/recipes-connectivity/samba/samba-basic.inc +++ /dev/null @@ -1,71 +0,0 @@ -SRC_URI += "file://config-lfs.patch \ - file://quota.patch;striplevel=0 \ -" - -EXTRA_OECONF += "\ - --enable-nss-wrapper \ - --without-ads \ - --with-winbind \ - --without-ldap \ - --without-krb5" - -PACKAGES =+ "libwbclient libwinbind libwinbind-dbg libnss-winbind winbind winbind-dbg \ - libnetapi libtdb libtevent libsmbsharemodes libsmbclient libsmbclient-dev \ - cifs cifs-doc swat ${PN}-base" - -RDEPENDS_${PN} += "${PN}-base" - -FILES_${PN}-base = "${sbindir}/nmbd \ - ${sbindir}/smbd \ - ${sysconfdir}/default \ - ${sysconfdir}/samba \ - ${sysconfdir}/init.d/samba \ - ${localstatedir}/lib/samba \ - ${localstatedir}/log/samba \ - ${localstatedir}/nmbd \ - ${localstatedir}/spool/samba \ -" - -FILES_winbind-dbg = "${libdir}/idmap/.debug/*.so \ - ${libdir}/security/.debug/pam_winbind.so \ -" - -FILES_${PN} += "${libdir}/vfs/*.so \ - ${libdir}/charset/*.so \ - ${libdir}/*.dat \ - ${libdir}/auth/*.so \ - ${libdir}/security/pam_smbpass.so \ -" - -FILES_${PN}-dbg += "${libdir}/vfs/.debug/*.so \ - ${libdir}/charset/.debug/*.so \ - ${libdir}/auth/.debug/*.so \ - ${libdir}/security/.debug/pam_smbpass.so \ -" - -FILES_libwbclient = "${libdir}/libwbclient.so.*" -FILES_libnetapi = "${libdir}/libnetapi.so.*" -FILES_libsmbsharemodes = "${libdir}/libsmbsharemodes.so.*" -FILES_libtdb = "${libdir}/libtdb.so.*" -FILES_libtevent = "${libdir}/libtevent.so.*" -FILES_cifs = "${base_sbindir}/mount.cifs ${base_sbindir}/umount.cifs" -FILES_cifs-doc = "${mandir}/man8/mount.cifs.8 ${mandir}/man8/umount.cifs.8" -FILES_libsmbclient = "${libdir}/libsmbclient.so.*" -FILES_libsmbclient-dev = "${libdir}/libsmbclient.so ${includedir}" -FILES_winbind = "${sbindir}/winbindd \ - ${bindir}/wbinfo \ - ${bindir}/ntlm_auth \ - ${sysconfdir}/init.d/winbind \ - ${systemd_unitdir}/system/winbind.service \ -" -FILES_libwinbind = "${libdir}/idmap/*.so \ - ${libdir}/pdb \ - ${libdir}/gpext \ - ${libdir}/perfcount \ - ${libdir}/security/pam_winbind.so \ -" - -FILES_libnss-winbind = "${libdir}/libnss_*${SOLIBS} \ - ${libdir}/nss_info" - -FILES_swat = "${sbindir}/swat ${datadir}/swat ${libdir}/*.msg" diff --git a/meta-oe/recipes-connectivity/samba/samba.inc b/meta-oe/recipes-connectivity/samba/samba.inc deleted file mode 100644 index eba58750..00000000 --- a/meta-oe/recipes-connectivity/samba/samba.inc +++ /dev/null @@ -1,161 +0,0 @@ -SECTION = "console/network" -LICENSE = "GPL-3.0" -DEPENDS = "readline virtual/libiconv zlib popt" - -SAMBA_MIRROR = "http://samba.org/samba/ftp" - -MIRRORS += "\ -${SAMBA_MIRROR} http://mirror.internode.on.net/pub/samba \n \ -${SAMBA_MIRROR} http://www.mirrorservice.org/sites/ftp.samba.org \n \ -" - -SRC_URI = "${SAMBA_MIRROR}/stable/samba-${PV}.tar.gz \ - file://volatiles.03_samba \ - file://smb.conf \ - file://init.samba \ - file://init.winbind \ - file://tdb.pc \ - file://nmb.service \ - file://smb.service \ - file://winbind.service \ -" - -S = "${WORKDIR}/samba-${PV}/source" - -inherit autotools-brokensep update-rc.d systemd - -SYSTEMD_PACKAGES = "${PN}-base winbind" -SYSTEMD_SERVICE_${PN}-base = "nmb.service smb.service" -SYSTEMD_SERVICE_winbind = "winbind.service" - -SAMBAMMAP = "no" -SAMBAMMAP_libc-glibc = "yes" - -# The file system settings --foodir=dirfoo and overridden unconditionally -# in the samba config by --with-foodir=dirfoo - even if the --with is not -# specified! Fix that here. Set the privatedir to /etc/samba/private. -EXTRA_OECONF='--disable-cups \ - --with-readline=${STAGING_LIBDIR}/.. \ - --with-libiconv=${STAGING_LIBDIR}/.. \ - --without-automount \ - --with-configdir=${sysconfdir}/samba \ - --with-privatedir=${sysconfdir}/samba/private \ - --with-lockdir=${localstatedir}/lock \ - --with-piddir=${localstatedir}/run \ - --with-logfilebase=${localstatedir}/log/samba \ - --libdir=${libdir} \ - --with-mandir=${mandir} \ - --with-swatdir=${datadir}/swat \ - --with-aio-support \ - --with-winbind \ - --with-wbclient \ - --without-acl-support \ - --disable-avahi \ - samba_cv_struct_timespec=yes \ - libreplace_cv_HAVE_MMAP=${SAMBAMMAP}' - -PACKAGECONFIG = "${@base_contains('DISTRO_FEATURES', 'pam', 'pam', '', d)}" -PACKAGECONFIG[pam] = "--with-pam,--without-pam,libpam" -PACKAGECONFIG[fam] = "--enable-fam,--disable-fam,gamin" -PACKAGECONFIG[talloc] = "--enable-external-libtalloc --with-libtalloc, --disable-external-libtalloc --without-libtalloc, talloc" -PACKAGECONFIG[valgrind] = "ac_cv_header_valgrind_valgrind_h=yes ac_cv_header_valgrind_memcheck_h=yes, \ - ac_cv_header_valgrind_valgrind_h=no ac_cv_header_valgrind_memcheck_h=no, valgrind" - -INITSCRIPT_PACKAGES = "${PN}-base winbind" -INITSCRIPT_NAME_${PN}-base = "samba" -INITSCRIPT_NAME_winbind = "winbind" -# No dependencies, goes in at level 20 (NOTE: take care with the -# level, later levels put the shutdown later too - see the links -# in rc6.d, the shutdown must precede network shutdown). -INITSCRIPT_PARAMS = "defaults" -CONFFILES_${PN}-base = "${sysconfdir}/samba/smb.conf" - -do_configure_prepend () { - ./script/mkversion.sh - if [ ! -e acinclude.m4 ]; then - touch aclocal.m4 - cat aclocal.m4 > acinclude.m4 - fi -} - -do_compile () { - oe_runmake proto_exists - base_do_compile -} - -do_install_append() { - install -d ${D}${libdir}/pkgconfig/ - cp ${WORKDIR}/tdb.pc ${D}${libdir}/pkgconfig/ - mv ${D}${libdir}/libsmbclient.so ${D}${libdir}/libsmbclient.so.0 || true - ln -sf libsmbclient.so.0 ${D}${libdir}/libsmbclient.so - mkdir -p ${D}${base_sbindir} - rm -f ${D}${bindir}/*.old - rm -f ${D}${sbindir}/*.old - [ -f ${D}${sbindir}/mount.cifs ] && mv ${D}${sbindir}/mount.cifs ${D}${base_sbindir}/ - [ -f ${D}${sbindir}/umount.cifs ] && mv ${D}${sbindir}/umount.cifs ${D}${base_sbindir}/ - - # This is needed for < 3.2.4 - rm -f ${D}${sbindir}/mount.smbfs ${D}${base_sbindir}/mount.smbfs - if [ -f ${D}${bindir}/smbmount ]; then - ln -sf ${bindir}/smbmount ${D}${base_sbindir}/mount.smb - ln -sf ${bindir}/smbmount ${D}${base_sbindir}/mount.smbfs - fi - - install -D -m 755 ${WORKDIR}/init.samba ${D}${sysconfdir}/init.d/samba - install -D -m 755 ${WORKDIR}/init.winbind ${D}${sysconfdir}/init.d/winbind - install -D -m 644 ${WORKDIR}/smb.conf ${D}${sysconfdir}/samba/smb.conf - install -D -m 644 ${WORKDIR}/volatiles.03_samba ${D}${sysconfdir}/default/volatiles/volatiles.03_samba - install -d ${D}/var/log/samba - install -d ${D}/var/spool/samba - - # Install other stuff not installed by "make install" - if [ -d ${WORKDIR}/${PN}-${PV}/nsswitch ]; then - install -m 0644 ${WORKDIR}/${PN}-${PV}/nsswitch/libnss_winbind.so ${D}${libdir}/libnss_winbind.so.2 - install -m 0644 ${WORKDIR}/${PN}-${PV}/nsswitch/libnss_wins.so ${D}${libdir}/libnss_wins.so.2 - fi - - rmdir --ignore-fail-on-non-empty ${D}${base_sbindir} - sed -i -e '1s,#!.*perl,#!${USRBINPATH}/env perl,' ${D}${bindir}/findsmb - - # usershare mount place - mkdir -p ${D}${localstatedir}/lib/samba/usershares - - # Remove sysinit script if sysvinit is not in DISTRO_FEATURES - if ${@bb.utils.contains('DISTRO_FEATURES', 'sysvinit', 'false', 'true', d)}; then - rm -rf ${D}${sysconfdir}/init.d/ - fi - - install -d ${D}${systemd_unitdir}/system - for i in nmb smb winbind; do - install -m 0644 ${WORKDIR}/$i.service ${D}${systemd_unitdir}/system - done - sed -e 's,@BASE_BINDIR@,${base_bindir},g' \ - -e 's,@SBINDIR@,${sbindir},g' \ - -i ${D}${systemd_unitdir}/system/*.service - - if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then - install -d ${D}${sysconfdir}/tmpfiles.d - echo "d ${localstatedir}/log/samba 0755 root root -" \ - > ${D}${sysconfdir}/tmpfiles.d/99-${BPN}.conf - fi -} - -DEPENDS_append = " ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd-systemctl-native', '', d)}" -pkg_postinst_${PN}-base () { - if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd sysvinit', 'true', 'false', d)}; then - if [ -n "$D" ]; then - OPTS="--root=$D" - fi - systemctl $OPTS mask samba.service - fi -} - -pkg_postinst_libnss-winbind () { - # add wins to the list of resolvers - ns=$D${sysconfdir}/nsswitch.conf - if ! grep "hosts:.*wins" $ns > /dev/null; then - hosts="`grep '^hosts:' $ns`" - hosts=`echo "$hosts" | sed 's/\[/\\\\[/g; s/\]/\\\\]/g'` - sed -i "s/$hosts/$hosts wins/" "$ns" - fi -} diff --git a/meta-oe/recipes-connectivity/samba/samba/0001-PIDL-fix-parsing-linemarkers-in-preprocessor-output.patch b/meta-oe/recipes-connectivity/samba/samba/0001-PIDL-fix-parsing-linemarkers-in-preprocessor-output.patch deleted file mode 100644 index 586867d8..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/0001-PIDL-fix-parsing-linemarkers-in-preprocessor-output.patch +++ /dev/null @@ -1,68 +0,0 @@ -Upstream-Status: Backport - -From b07ade6e6fcc8b844cf1fb8b6038617281c4c2d0 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Wed, 6 Feb 2013 10:17:57 +0200 -Subject: [PATCH] PIDL: fix parsing linemarkers in preprocessor output - -Commit b07ade6e6fcc8b844cf1fb8b6038617281c4c2d0 v3-6-stable - -When PIDL calls out to C preprocessor to expand IDL files -and parse the output, it filters out linemarkers and line control -information as described in http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html -and http://gcc.gnu.org/onlinedocs/cpp/Line-Control.html#Line-Control - -With gcc 4.8 stdc-predef.h is included automatically and linemarker for the -file has extended flags that PIDL couldn't parse ('system header that needs to -be extern "C" protected for C++') - -Thanks to Jakub Jelinek for explanation of the linemarker format. - -Fixes https://bugzilla.redhat.com/show_bug.cgi?id=906517 - -Reviewed-by: Andreas Schneider -(cherry picked from commit 6ba7ab5c14801aecae96373d5a9db7ab82957526) - -Signed-off-by: Andreas Schneider - -Fix bug #9636 - pidl can't parse new linemarkers in preprocessor output. -(cherry picked from commit 643571470f2e4cd2f58bd60ac7189abb826d33cc) -(cherry picked from commit b5a8afd6550e9091d169d3010751913bb483fc4b) ---- - pidl/idl.yp | 4 +++- - pidl/lib/Parse/Pidl/IDL.pm | 4 +++- - 2 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/pidl/idl.yp b/pidl/idl.yp -index b5c5185..c8a65f6 100644 ---- a/pidl/idl.yp -+++ b/pidl/idl.yp -@@ -610,7 +610,9 @@ again: - - for ($parser->YYData->{INPUT}) { - if (/^\#/) { -- if (s/^\# (\d+) \"(.*?)\"( \d+|)//) { -+ # Linemarker format is described at -+ # http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html -+ if (s/^\# (\d+) \"(.*?)\"(( \d+){1,4}|)//) { - $parser->YYData->{LINE} = $1-1; - $parser->YYData->{FILE} = $2; - goto again; -diff --git a/pidl/lib/Parse/Pidl/IDL.pm b/pidl/lib/Parse/Pidl/IDL.pm -index d4820ff..6927c89 100644 ---- a/pidl/lib/Parse/Pidl/IDL.pm -+++ b/pidl/lib/Parse/Pidl/IDL.pm -@@ -2576,7 +2576,9 @@ again: - - for ($parser->YYData->{INPUT}) { - if (/^\#/) { -- if (s/^\# (\d+) \"(.*?)\"( \d+|)//) { -+ # Linemarker format is described at -+ # http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html -+ if (s/^\# (\d+) \"(.*?)\"(( \d+){1,4}|)//) { - $parser->YYData->{LINE} = $1-1; - $parser->YYData->{FILE} = $2; - goto again; --- -1.7.5.4 - diff --git a/meta-oe/recipes-connectivity/samba/samba/Managing-Samba.txt b/meta-oe/recipes-connectivity/samba/samba/Managing-Samba.txt deleted file mode 100644 index 01f75928..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/Managing-Samba.txt +++ /dev/null @@ -1,40 +0,0 @@ -This device is running a bare-bone Samba server which allows easy -transfer of files and directories between any networked desktop PC and -your networked PDA. - -Since it is generally a bad idea to allow everyone read and write access -to your PDA, you will have to configure at least one user to get access to -any shared folder. - -How to create a Samba user with password: - -- If you haven't already created a non-root user, do so now: - root@poodle:/usr/bin# adduser testuser - Changing password for testuser - Enter the new password (minimum of 5, maximum of 8 characters) - Please use a combination of upper and lower case letters and numbers. - Enter new password: - Bad password: too short. - - Warning: weak password (continuing). - Re-enter new password: - Password changed. - root@poodle:/usr/bin# - -- Note that the password you entered will _not_ be your samba password. - Samba uses its own password database. - -- Add a Samba password for your user: - root@poodle:/usr/bin# smbpasswd -a testuser - New SMB password: - Retype new SMB password: - Added user testuser. - root@poodle:/usr/bin# - -- After you have added your new samba user, you'll have to restart the samba - server by running "/etc/init.d/samba restart" or by rebooting the device - -- Use the newly created username / password combination to access your network - shares. Please note the the Samba username must also exist as a unix username! - - diff --git a/meta-oe/recipes-connectivity/samba/samba/cifs.patch b/meta-oe/recipes-connectivity/samba/samba/cifs.patch deleted file mode 100644 index ee6dab56..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/cifs.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- source/client/mount.cifs.c.old 2004-11-28 02:33:52.000000000 +1030 -+++ source/client/mount.cifs.c 2004-11-28 02:33:59.000000000 +1030 -@@ -36,6 +36,7 @@ - #include - #include - #include -+#include - - #define MOUNT_CIFS_VERSION_MAJOR "1" - #define MOUNT_CIFS_VERSION_MINOR "2" diff --git a/meta-oe/recipes-connectivity/samba/samba/config-h.patch b/meta-oe/recipes-connectivity/samba/samba/config-h.patch deleted file mode 100644 index eeb22684..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/config-h.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -urN source.old//include/config.h.in source//include/config.h.in ---- source.old//include/config.h.in 2008-11-20 14:45:04.000000000 +0000 -+++ source//include/config.h.in 2008-11-30 21:04:17.990008933 +0000 -@@ -2672,7 +2672,7 @@ - #undef USE_SETEUID - - /* Whether setresuid() is available */ --#undef USE_SETRESUID -+#define USE_SETRESUID 1 - - /* Whether setreuid() is available */ - #undef USE_SETREUID diff --git a/meta-oe/recipes-connectivity/samba/samba/config-lfs.patch b/meta-oe/recipes-connectivity/samba/samba/config-lfs.patch deleted file mode 100644 index b37ed690..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/config-lfs.patch +++ /dev/null @@ -1,47 +0,0 @@ -Cache the check for Linux LFS support, so it can be prepopulated from -the site cache for configure variables for cross-compiling. Without this, -samba gets the idea that it can use dirent64 and friends without defining -the flags it needs to get it, such as _GNU_SOURCE and _LARGEFILE64_SOURCE. - -Symptoms of getting the configuration wrong on cross-compile inculde -warnings such as - - smbd/trans2.c: In function `get_lanman2_dir_entry': - smbd/trans2.c:1065: warning: right shift count >= width of type - -and errors like - - smbd/vfs.c:630: error: dereferencing pointer to incomplete type - -(when trying to dereference dirent64.) - ---- source/configure.in.orig 2005-05-29 14:46:18.000000000 -0700 -+++ source/configure.in 2005-05-29 14:51:57.000000000 -0700 -@@ -588,7 +588,7 @@ - # Tests for linux LFS support. Need kernel 2.4 and glibc2.2 or greater support. - # - *linux*) -- AC_MSG_CHECKING([for LFS support]) -+ AC_CACHE_CHECK([for LFS support], samba_cv_LINUX_LFS_SUPPORT,[ - old_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="-D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE $CPPFLAGS" - AC_TRY_RUN([ -@@ -627,15 +627,14 @@ - exit(1); - #endif - } --], [LINUX_LFS_SUPPORT=yes], [LINUX_LFS_SUPPORT=no], [LINUX_LFS_SUPPORT=cross]) -- CPPFLAGS="$old_CPPFLAGS" -- if test x$LINUX_LFS_SUPPORT = xyes ; then -+], [samba_cv_LINUX_LFS_SUPPORT=yes], [samba_cv_LINUX_LFS_SUPPORT=no], [samba_cv_LINUX_LFS_SUPPORT=cross]) -+ CPPFLAGS="$old_CPPFLAGS"]) -+ if test x"$samba_cv_LINUX_LFS_SUPPORT" = x"yes" ; then - CPPFLAGS="-D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE $CPPFLAGS" - AC_DEFINE(_LARGEFILE64_SOURCE, 1, [Whether to enable large file support]) - AC_DEFINE(_FILE_OFFSET_BITS, 64, [File offset bits]) - AC_DEFINE(_GNU_SOURCE, 1, [Whether to use GNU libc extensions]) - fi -- AC_MSG_RESULT([$LINUX_LFS_SUPPORT]) - ;; - - # diff --git a/meta-oe/recipes-connectivity/samba/samba/configure-3.3.0.patch b/meta-oe/recipes-connectivity/samba/samba/configure-3.3.0.patch deleted file mode 100644 index 19fb9864..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/configure-3.3.0.patch +++ /dev/null @@ -1,85 +0,0 @@ -diff -urN source.old//configure source//configure ---- source.old//configure 2009-01-27 07:53:11.000000000 +0000 -+++ source//configure 2009-01-31 21:07:25.811887936 +0000 -@@ -43860,13 +43860,7 @@ - *linux*) - # glibc <= 2.3.2 has a broken getgrouplist - if test "$cross_compiling" = yes; then -- { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 --$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} --{ { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling --See \`config.log' for more details." >&5 --$as_echo "$as_me: error: cannot run test program while cross compiling --See \`config.log' for more details." >&2;} -- { (exit 1); exit 1; }; }; } -+linux_getgrouplist_ok=no - else - cat >conftest.$ac_ext <<_ACEOF - /* confdefs.h. */ -diff -urN source.old//configure.in source//configure.in ---- source.old//configure.in 2009-01-26 13:56:34.000000000 +0000 -+++ source//configure.in 2009-01-31 21:04:39.051889949 +0000 -@@ -280,6 +280,8 @@ - fi - AC_SUBST(BROKEN_CC) - -+AC_TRY_COMPILE([],[(void)sizeof(char[-1])],AC_MSG_ERROR([configure's compilation assert doesn't work with $CC])) -+ - dnl Check if the C compiler understands -Werror - AC_CACHE_CHECK([that the C compiler understands -Werror],samba_cv_HAVE_Werror, [ - AC_TRY_RUN_STRICT([ -@@ -330,25 +332,11 @@ - # a runtime test is needed here - AC_SUBST(PIDL_ARGS) - AC_CACHE_CHECK([that the C compiler understands negative enum values],samba_cv_CC_NEGATIVE_ENUM_VALUES, [ -- AC_TRY_RUN( -+ AC_TRY_COMPILE([], - [ -- #include - enum negative_values { NEGATIVE_VALUE = 0xFFFFFFFF }; -- int main(void) { -- enum negative_values v1 = NEGATIVE_VALUE; -- unsigned v2 = NEGATIVE_VALUE; -- -- if (v1 != 0xFFFFFFFF) { -- printf("%u != 0xFFFFFFFF\n", v1); -- return 1; -- } -- if (v2 != 0xFFFFFFFF) { -- printf("%u != 0xFFFFFFFF\n", v2); -- return 1; -- } -- -- return 0; -- } -+ (void)sizeof(char[1-2*( (unsigned)NEGATIVE_VALUE != 0xFFFFFFFF)]); -+ (void)sizeof(char[1-2*((enum negative_values)NEGATIVE_VALUE != 0xFFFFFFFF)]); - ], - samba_cv_CC_NEGATIVE_ENUM_VALUES=yes,samba_cv__CC_NEGATIVE_ENUM_VALUES=no)]) - if test x"$samba_cv_CC_NEGATIVE_ENUM_VALUES" != x"yes"; then -@@ -1224,22 +1212,12 @@ - case "$host_os" in - *linux*) - # glibc <= 2.3.2 has a broken getgrouplist -- AC_TRY_RUN([ --#include -+ AC_TRY_COMPILE([ - #include --main() { -- /* glibc up to 2.3 has a broken getgrouplist */ -+],[ - #if defined(__GLIBC__) && defined(__GLIBC_MINOR__) -- int libc_major = __GLIBC__; -- int libc_minor = __GLIBC_MINOR__; -- -- if (libc_major < 2) -- exit(1); -- if ((libc_major == 2) && (libc_minor <= 3)) -- exit(1); -+ (void)sizeof(char[1-2*(__GLIBC__ < 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)]); - #endif -- exit(0); --} - ], [linux_getgrouplist_ok=yes], [linux_getgrouplist_ok=no]) - if test x"$linux_getgrouplist_ok" = x"yes"; then - AC_DEFINE(HAVE_GETGROUPLIST, 1, [Have good getgrouplist]) diff --git a/meta-oe/recipes-connectivity/samba/samba/init.samba b/meta-oe/recipes-connectivity/samba/samba/init.samba deleted file mode 100644 index 6a44ac46..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/init.samba +++ /dev/null @@ -1,58 +0,0 @@ -#! /bin/sh -# -# This is an init script for openembedded -# Copy it to /etc/init.d/samba and type -# > update-rc.d samba defaults 60 -# - - -smbd=/usr/sbin/smbd -test -x "$smbd" || exit 0 -nmbd=/usr/sbin/nmbd -test -x "$nmbd" || exit 0 - - -case "$1" in - start) - echo -n "Starting Samba: smbd" - start-stop-daemon --start --quiet --exec $smbd - echo -n " nmbd" - start-stop-daemon --start --quiet --exec $nmbd - echo "." - ;; - stop) - echo -n "Stopping Samba: smbd" - start-stop-daemon --stop --quiet --pidfile /var/run/smbd.pid - echo -n " nmbd" - start-stop-daemon --stop --quiet --pidfile /var/run/nmbd.pid - echo "." - ;; - reload|force-reload) - start-stop-daemon --stop --quiet --signal 1 --exec $smbd - start-stop-daemon --stop --quiet --signal 1 --exec $nmbd - ;; - restart) - echo -n "Stopping Samba: smbd" - start-stop-daemon --stop --quiet --pidfile /var/run/smbd.pid - echo -n " nmbd" - start-stop-daemon --stop --quiet --pidfile /var/run/nmbd.pid - echo "" - echo -n "Waiting for samba processes to die off" - for i in 1 2 3 ; - do - sleep 1 - echo -n "." - done - echo "" - echo -n "Starting Samba: smbd" - start-stop-daemon --start --quiet --exec $smbd - echo -n " nmbd" - start-stop-daemon --start --quiet --exec $nmbd - echo "." - ;; - *) - echo "Usage: /etc/init.d/samba {start|stop|reload|restart|force-reload}" - exit 1 -esac - -exit 0 diff --git a/meta-oe/recipes-connectivity/samba/samba/init.winbind b/meta-oe/recipes-connectivity/samba/samba/init.winbind deleted file mode 100644 index 53de2eec..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/init.winbind +++ /dev/null @@ -1,38 +0,0 @@ -#! /bin/sh - -### BEGIN INIT INFO -# Provides: winbind -# Required-Start: $network $remote_fs $syslog -# Required-Stop: $network $remote_fs $syslog -# Should-Start: samba -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: start Winbind daemon -### END INIT INFO - -winbind=/usr/sbin/winbindd -test -x "$winbind" || exit 0 - -case "$1" in - start) - echo -n "Starting Winbind... " - start-stop-daemon --start --quiet --exec $winbind - echo "done" - ;; - stop) - echo -n "Stopping Winbind... " - start-stop-daemon --stop --quiet --pidfile /var/run/winbind.pid - echo "done" - ;; - reload|force-reload) - start-stop-daemon --stop --quiet --signal 1 --exec $winbind - ;; - restart) - $0 stop && sleep 2 && $0 start - ;; - *) - echo "Usage: /etc/init.d/winbind {start|stop|reload|restart|force-reload}" - exit 1 -esac - -exit 0 diff --git a/meta-oe/recipes-connectivity/samba/samba/mtab.patch b/meta-oe/recipes-connectivity/samba/samba/mtab.patch deleted file mode 100644 index 2ee8ba09..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/mtab.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -urN source/client/mtab.c samba-3.2.7//source/client/mtab.c ---- source/client/mtab.c 2008-12-19 13:57:33.000000000 +0000 -+++ source/client/mtab.c 2009-01-09 23:14:00.717671075 +0000 -@@ -32,6 +32,7 @@ - #include - #include - #include -+#include - #include - #include - #include diff --git a/meta-oe/recipes-connectivity/samba/samba/nmb.service b/meta-oe/recipes-connectivity/samba/samba/nmb.service deleted file mode 100644 index 91b99753..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/nmb.service +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=Samba NMB Daemon -After=syslog.target network.target - -[Service] -Type=forking -PIDFile=/var/run/nmbd.pid -ExecStart=@SBINDIR@/nmbd -ExecReload=@BASE_BINDIR@/kill -HUP $MAINPID - -[Install] -WantedBy=multi-user.target diff --git a/meta-oe/recipes-connectivity/samba/samba/quota.patch b/meta-oe/recipes-connectivity/samba/samba/quota.patch deleted file mode 100644 index 6f42ff86..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/quota.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- lib/sysquotas_4A.c.old 2005-07-03 17:16:00.000000000 +0200 -+++ lib/sysquotas_4A.c 2005-07-03 17:10:09.000000000 +0200 -@@ -28,6 +28,8 @@ - /* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */ - /* this is used by: HPUX,IRIX */ - -+ #define _LINUX_QUOTA_VERSION 1 -+ - #ifdef HAVE_SYS_TYPES_H - #include - #endif diff --git a/meta-oe/recipes-connectivity/samba/samba/smb.conf b/meta-oe/recipes-connectivity/samba/samba/smb.conf deleted file mode 100644 index f07e3e4e..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/smb.conf +++ /dev/null @@ -1,266 +0,0 @@ -# This is the main Samba configuration file. You should read the -# smb.conf(5) manual page in order to understand the options listed -# here. Samba has a huge number of configurable options (perhaps too -# many!) most of which are not shown in this example -# -# For a step to step guide on installing, configuring and using samba, -# read the Samba-HOWTO-Collection. This may be obtained from: -# http://www.samba.org/samba/docs/Samba-HOWTO-Collection.pdf -# -# Many working examples of smb.conf files can be found in the -# Samba-Guide which is generated daily and can be downloaded from: -# http://www.samba.org/samba/docs/Samba-Guide.pdf -# -# Any line which starts with a ; (semi-colon) or a # (hash) -# is a comment and is ignored. In this example we will use a # -# for commentry and a ; for parts of the config file that you -# may wish to enable -# -# NOTE: Whenever you modify this file you should run the command "testparm" -# to check that you have not made any basic syntactic errors. -# -#======================= Global Settings ===================================== -[global] - -# workgroup = NT-Domain-Name or Workgroup-Name, eg: MIDEARTH - workgroup = MYGROUP - -# server string is the equivalent of the NT Description field - server string = Samba Server - -# Security mode. Defines in which mode Samba will operate. Possible -# values are share, user, server, domain and ads. Most people will want -# user level security. See the Samba-HOWTO-Collection for details. - security = user - -# This option is important for security. It allows you to restrict -# connections to machines which are on your local network. The -# following example restricts access to two C class networks and -# the "loopback" interface. For more examples of the syntax see -# the smb.conf man page -; hosts allow = 192.168.1. 192.168.2. 127. - -# If you want to automatically load your printer list rather -# than setting them up individually then you'll need this - load printers = yes - -# you may wish to override the location of the printcap file -; printcap name = /etc/printcap - -# on SystemV system setting printcap name to lpstat should allow -# you to automatically obtain a printer list from the SystemV spool -# system -; printcap name = lpstat - -# It should not be necessary to specify the print system type unless -# it is non-standard. Currently supported print systems include: -# bsd, cups, sysv, plp, lprng, aix, hpux, qnx -; printing = cups - -# Uncomment this if you want a guest account, you must add this to /etc/passwd -# otherwise the user "nobody" is used -; guest account = pcguest - -# this tells Samba to use a separate log file for each machine -# that connects - log file = /var/log/samba/log.%m - -# Put a capping on the size of the log files (in Kb). - max log size = 50 - -# Use password server option only with security = server -# The argument list may include: -# password server = My_PDC_Name [My_BDC_Name] [My_Next_BDC_Name] -# or to auto-locate the domain controller/s -# password server = * -; password server = - -# Use the realm option only with security = ads -# Specifies the Active Directory realm the host is part of -; realm = MY_REALM - -# Backend to store user information in. New installations should -# use either tdbsam or ldapsam. smbpasswd is available for backwards -# compatibility. tdbsam requires no further configuration. -; passdb backend = tdbsam - -# Using the following line enables you to customise your configuration -# on a per machine basis. The %m gets replaced with the netbios name -# of the machine that is connecting. -# Note: Consider carefully the location in the configuration file of -# this line. The included file is read at that point. -; include = /usr/local/samba/lib/smb.conf.%m - -# Configure Samba to use multiple interfaces -# If you have multiple network interfaces then you must list them -# here. See the man page for details. -; interfaces = 192.168.12.2/24 192.168.13.2/24 - -# Browser Control Options: -# set local master to no if you don't want Samba to become a master -# browser on your network. Otherwise the normal election rules apply -; local master = no - -# OS Level determines the precedence of this server in master browser -# elections. The default value should be reasonable -; os level = 33 - -# Domain Master specifies Samba to be the Domain Master Browser. This -# allows Samba to collate browse lists between subnets. Don't use this -# if you already have a Windows NT domain controller doing this job -; domain master = yes - -# Preferred Master causes Samba to force a local browser election on startup -# and gives it a slightly higher chance of winning the election -; preferred master = yes - -# Enable this if you want Samba to be a domain logon server for -# Windows95 workstations. -; domain logons = yes - -# if you enable domain logons then you may want a per-machine or -# per user logon script -# run a specific logon batch file per workstation (machine) -; logon script = %m.bat -# run a specific logon batch file per username -; logon script = %U.bat - -# Where to store roving profiles (only for Win95 and WinNT) -# %L substitutes for this servers netbios name, %U is username -# You must uncomment the [Profiles] share below -; logon path = \\%L\Profiles\%U - -# Windows Internet Name Serving Support Section: -# WINS Support - Tells the NMBD component of Samba to enable it's WINS Server -; wins support = yes - -# WINS Server - Tells the NMBD components of Samba to be a WINS Client -# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both -; wins server = w.x.y.z - -# WINS Proxy - Tells Samba to answer name resolution queries on -# behalf of a non WINS capable client, for this to work there must be -# at least one WINS Server on the network. The default is NO. -; wins proxy = yes - -# DNS Proxy - tells Samba whether or not to try to resolve NetBIOS names -# via DNS nslookups. The default is NO. - dns proxy = no - -# These scripts are used on a domain controller or stand-alone -# machine to add or delete corresponding unix accounts -; add user script = /usr/sbin/useradd %u -; add group script = /usr/sbin/groupadd %g -; add machine script = /usr/sbin/adduser -n -g machines -c Machine -d /dev/null -s /bin/false %u -; delete user script = /usr/sbin/userdel %u -; delete user from group script = /usr/sbin/deluser %u %g -; delete group script = /usr/sbin/groupdel %g - - -#============================ Share Definitions ============================== -[homes] - comment = Home Directories - browseable = yes - writable = yes - -# Un-comment the following and create the netlogon directory for Domain Logons -; [netlogon] -; comment = Network Logon Service -; path = /usr/local/samba/lib/netlogon -; guest ok = yes -; writable = no -; share modes = no - - -# Un-comment the following to provide a specific roving profile share -# the default is to use the user's home directory -;[Profiles] -; path = /usr/local/samba/profiles -; browseable = no -; guest ok = yes - - -# NOTE: If you have a BSD-style print system there is no need to -# specifically define each individual printer -[printers] - comment = All Printers - path = /var/spool/samba - browseable = no -# Set public = yes to allow user 'guest account' to print - guest ok = no - writable = no - printable = yes - -# This one is useful for people to share files -;[tmp] -; comment = Temporary file space -; path = /tmp -; read only = no -; public = yes - -# A publicly accessible directory, but read only, except for people in -# the "staff" group -;[public] -; comment = Public Stuff -; path = /home/samba -; public = yes -; writable = yes -; printable = no -; write list = @staff - -# Other examples. -# -# A private printer, usable only by fred. Spool data will be placed in fred's -# home directory. Note that fred must have write access to the spool directory, -# wherever it is. -;[fredsprn] -; comment = Fred's Printer -; valid users = fred -; path = /homes/fred -; printer = freds_printer -; public = no -# A private directory, usable only by fred. Note that fred requires write -# access to the directory. -;[fredsdir] -; comment = Fred's Service -; path = /usr/somewhere/private -; valid users = fred -; public = no -; writable = yes -; printable = no - -# a service which has a different directory for each machine that connects -# this allows you to tailor configurations to incoming machines. You could -# also use the %U option to tailor it by user name. -# The %m gets replaced with the machine name that is connecting. -;[pchome] -; comment = PC Directories -; path = /usr/pc/%m -; public = no -; writable = yes - -# A publicly accessible directory, read/write to all users. Note that all files -# created in the directory by users will be owned by the default user, so -# any user with access can delete any other user's files. Obviously this -# directory must be writable by the default user. Another user could of course -# be specified, in which case all files would be owned by that user instead. -;[public] -; path = /usr/somewhere/else/public -; public = yes -; only guest = yes -; writable = yes -; printable = no - -# The following two entries demonstrate how to share a directory so that two -# users can place files there that will be owned by the specific users. In this -# setup, the directory should be writable by both users and should have the -# sticky bit set on it to prevent abuse. Obviously this could be extended to -# as many users as required. -;[myshare] -; comment = Mary's and Fred's stuff -; path = /usr/somewhere/shared -; valid users = mary fred -; public = no -; writable = yes -; printable = no -; create mask = 0765 diff --git a/meta-oe/recipes-connectivity/samba/samba/smb.service b/meta-oe/recipes-connectivity/samba/samba/smb.service deleted file mode 100644 index bc0707a3..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/smb.service +++ /dev/null @@ -1,13 +0,0 @@ -[Unit] -Description=Samba SMB Daemon -After=syslog.target network.target nmb.service winbind.service - -[Service] -Type=forking -PIDFile=/var/run/smbd.pid -LimitNOFILE=16384 -ExecStart=@SBINDIR@/smbd -ExecReload=@BASE_BINDIR@/kill -HUP $MAINPID - -[Install] -WantedBy=multi-user.target diff --git a/meta-oe/recipes-connectivity/samba/samba/tdb.pc b/meta-oe/recipes-connectivity/samba/samba/tdb.pc deleted file mode 100644 index 6307a20a..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/tdb.pc +++ /dev/null @@ -1,11 +0,0 @@ -prefix=/usr -exec_prefix=/usr -libdir=/usr/lib -includedir=/usr/include - -Name: tdb -Description: A trivial database -Version: 1.1.2 -Libs: -L${libdir} -ltdb -Cflags: -I${includedir} -URL: http://tdb.samba.org/ diff --git a/meta-oe/recipes-connectivity/samba/samba/tdbheaderfix.patch b/meta-oe/recipes-connectivity/samba/samba/tdbheaderfix.patch deleted file mode 100644 index e37c9b0d..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/tdbheaderfix.patch +++ /dev/null @@ -1,14 +0,0 @@ -Index: source/lib/tdb/include/tdb.h -=================================================================== ---- source.orig/lib/tdb/include/tdb.h 2009-05-17 17:42:41.000000000 +0100 -+++ source/lib/tdb/include/tdb.h 2009-05-17 17:42:46.000000000 +0100 -@@ -1,6 +1,9 @@ - #ifndef __TDB_H__ - #define __TDB_H__ - -+#include -+ -+ - /* - Unix SMB/CIFS implementation. - diff --git a/meta-oe/recipes-connectivity/samba/samba/volatiles.03_samba b/meta-oe/recipes-connectivity/samba/samba/volatiles.03_samba deleted file mode 100644 index 469bc9e7..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/volatiles.03_samba +++ /dev/null @@ -1,2 +0,0 @@ -# -d root root 0755 /var/log/samba none diff --git a/meta-oe/recipes-connectivity/samba/samba/winbind.service b/meta-oe/recipes-connectivity/samba/samba/winbind.service deleted file mode 100644 index bff6fb8e..00000000 --- a/meta-oe/recipes-connectivity/samba/samba/winbind.service +++ /dev/null @@ -1,12 +0,0 @@ -i[Unit] -Description=Samba Winbind Daemon -After=syslog.target network.target nmb.service - -[Service] -Type=forking -PIDFile=/var/run/winbindd.pid -ExecStart=@SBINDIR@/winbindd -ExecReload=@BASE_BINDIR@/kill -HUP $MAINPID - -[Install] -WantedBy=multi-user.target diff --git a/meta-oe/recipes-connectivity/samba/samba_3.6.25.bb b/meta-oe/recipes-connectivity/samba/samba_3.6.25.bb deleted file mode 100644 index 01861fb9..00000000 --- a/meta-oe/recipes-connectivity/samba/samba_3.6.25.bb +++ /dev/null @@ -1,67 +0,0 @@ -require samba.inc -require samba-basic.inc -LICENSE = "GPLv3" -LIC_FILES_CHKSUM = "file://../COPYING;md5=d32239bcb673463ab874e80d47fae504" - -SRC_URI += "\ - file://config-h.patch \ - file://documentation.patch;patchdir=.. \ - file://documentation2.patch;patchdir=.. \ - file://fhs-filespaths.patch;patchdir=.. \ - file://installswat.sh.patch;patchdir=.. \ - file://pam-examples.patch;patchdir=.. \ - file://smbclient-pager.patch;patchdir=.. \ - file://undefined-symbols.patch;patchdir=.. \ - file://usershare.patch;patchdir=.. \ - file://smbtar-bashism.patch;patchdir=.. \ - file://dont-build-VFS-examples.patch;patchdir=.. \ - file://bug_221618_precise-64bit-prototype.patch;patchdir=.. \ - file://bug_598313_upstream_7499-nss_wins-dont-clobber-daemons-logs.patch;patchdir=.. \ - file://bug_387266_upstream_4104_mention-kerberos-in-smbspool-manpage.patch;patchdir=.. \ - file://bug_604768_upstream_7826_drop-using-samba-link.patch;patchdir=.. \ - file://bug_604768_upstream_7826_fix-WHATSNEW-link.patch;patchdir=.. \ - file://waf-as-source.patch;patchdir=.. \ - file://smbtorture-manpage.patch;patchdir=.. \ - file://libutil_drop_AI_ADDRCONFIG.patch;patchdir=.. \ - file://shadow_copy2_backport.patch;patchdir=.. \ - file://only_export_public_symbols.patch;patchdir=.. \ - file://configure-disable-getaddrinfo-cross.patch;patchdir=.. \ - file://configure-disable-core_pattern-cross-check.patch;patchdir=.. \ - file://configure-libunwind.patch;patchdir=.. \ -" -SRC_URI[md5sum] = "76da2fa64edd94a0188531e7ecb27c4e" -SRC_URI[sha256sum] = "8f2c8a7f2bd89b0dfd228ed917815852f7c625b2bc0936304ac3ed63aaf83751" - -S = "${WORKDIR}/samba-${PV}/source3" - -PACKAGECONFIG ??= "" -PACKAGECONFIG[libunwind] = "--enable-libunwind,--disable-libunwind,libunwind" - -EXTRA_OECONF += "\ - ac_cv_path_PYTHON=/not/exist \ - ac_cv_path_PYTHON_CONFIG=/not/exist \ - SMB_BUILD_CC_NEGATIVE_ENUM_VALUES=yes \ - samba_cv_CC_NEGATIVE_ENUM_VALUES=yes \ - linux_getgrouplist_ok=no \ - samba_cv_HAVE_BROKEN_GETGROUPS=no \ - samba_cv_HAVE_FTRUNCATE_EXTEND=yes \ - samba_cv_have_setresuid=yes \ - samba_cv_have_setresgid=yes \ - samba_cv_HAVE_WRFILE_KEYTAB=yes \ - samba_cv_linux_getgrouplist_ok=yes \ -" - -do_configure() { - gnu-configize --force - oe_runconf -} - -do_compile () { - base_do_compile -} - -do_install_append() { - rmdir "${D}${localstatedir}/lock" - rmdir "${D}${localstatedir}/run" - rmdir --ignore-fail-on-non-empty "${D}${localstatedir}" -} diff --git a/meta-oe/recipes-connectivity/samba/samba_4.1.12.bb b/meta-oe/recipes-connectivity/samba/samba_4.1.12.bb new file mode 100644 index 00000000..51ac6556 --- /dev/null +++ b/meta-oe/recipes-connectivity/samba/samba_4.1.12.bb @@ -0,0 +1,155 @@ +SECTION = "console/network" + +LICENSE = "GPL-3.0+ & LGPL-3.0+ & GPL-2.0+" +LIC_FILES_CHKSUM = "file://COPYING;md5=d32239bcb673463ab874e80d47fae504 \ + file://${COREBASE}/meta/files/common-licenses/LGPL-3.0;md5=bfccfe952269fff2b407dd11f2f3083b \ + file://${COREBASE}/meta/files/common-licenses/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6 " + +SAMBA_MIRROR = "http://samba.org/samba/ftp" +MIRRORS += "\ +${SAMBA_MIRROR} http://mirror.internode.on.net/pub/samba \n \ +${SAMBA_MIRROR} http://www.mirrorservice.org/sites/ftp.samba.org \n \ +" + +SRC_URI = "${SAMBA_MIRROR}/stable/samba-${PV}.tar.gz \ + file://00-fix-typos-in-man-pages.patch \ + file://01-fix-force-user-sec-ads.patch \ + file://02-fix-ipv6-join.patch \ + file://03-net-ads-kerberos-pac.patch \ + file://04-ipv6-workaround.patch \ + file://05-fix-gecos-field-with-samlogon.patch \ + file://06-fix-nmbd-systemd-status-update.patch \ + file://07-fix-idmap-ad-getgroups-without-gid.patch \ + file://08-fix-idmap-ad-sfu-with-trusted-domains.patch \ + file://09-fix-smbclient-echo-cmd-segfault.patch \ + file://10-improve-service-principal-guessing-in-net.patch \ + file://11-fix-overwriting-of-spns-during-net-ads-join.patch \ + file://12-add-precreated-spns-from-AD-during-keytab-generation.patch \ + file://13-fix-aes-enctype.patch \ + file://14-fix-dnsupdate.patch \ + file://15-fix-netbios-name-truncation.patch \ + file://16-do-not-check-xsltproc-manpages.patch \ + file://17-execute-prog-by-qemu.patch \ + file://18-avoid-get-config-by-native-ncurses.patch \ + file://19-systemd-daemon-is-contained-by-libsystemd.patch \ + file://20-do-not-import-target-module-in-configure.patch \ + " + +SRC_URI[md5sum] = "232016d7581a1ba11e991ec2674553c4" +SRC_URI[sha256sum] = "033604674936bf5c77d7df299b0626052b84a41505a6a6afe902f6274fc29898" + +inherit systemd waf-samba + +DEPENDS += "readline virtual/libiconv zlib popt talloc libtdb libtevent libldb krb5 ctdb" + +PACKAGECONFIG = "${@base_contains('DISTRO_FEATURES', 'pam', 'pam', '', d)}" +PACKAGECONFIG += "${@base_contains('DISTRO_FEATURES', 'systemd', 'systemd', '', d)}" + +PACKAGECONFIG[pam] = "--with-pam,--without-pam,libpam" +PACKAGECONFIG[fam] = "--with-fam,--without-fam,gamin" +PACKAGECONFIG[systemd] = "--with-systemd,--without-systemd,systemd" + +SAMBA4_IDMAP_MODULES="idmap_ad,idmap_rid,idmap_adex,idmap_hash,idmap_tdb2" +SAMBA4_PDB_MODULES="pdb_tdbsam,pdb_ldap,pdb_ads,pdb_smbpasswd,pdb_wbc_sam,pdb_samba4" +SAMBA4_AUTH_MODULES="auth_unix,auth_wbc,auth_server,auth_netlogond,auth_script,auth_samba4" +SAMBA4_MODULES="${SAMBA4_IDMAP_MODULES},${SAMBA4_PDB_MODULES},${SAMBA4_AUTH_MODULES}" + +SAMBA4_LIBS="heimdal,!zlib,!popt,!talloc,!pytalloc,!pytalloc-util,!tevent,!pytevent,!tdb,!pytdb,!ldb,!pyldb" + +PERL_VERNDORLIB="${datadir}/perl5/vendor_perl/" + +EXTRA_OECONF += "--enable-fhs \ + --with-piddir=${localstatedir}/run \ + --with-sockets-dir=${localstatedir}/run/samba \ + --with-modulesdir=${libdir}/samba \ + --with-pammodulesdir=${libdir}/security \ + --with-lockdir=${localstatedir}/lib/samba \ + --with-cachedir=${localstatedir}/lib/samba \ + --with-perl-lib-install-dir=${PERL_VERNDORLIB} \ + --disable-gnutls \ + --disable-rpath-install \ + --with-shared-modules=${SAMBA4_MODULES} \ + --bundled-libraries=${SAMBA4_LIBS} \ + --with-system-mitkrb5 \ + --without-ad-dc \ + ${@base_conditional('TARGET_ARCH', 'x86_64', '', '--disable-glusterfs', d)} \ + --with-cluster-support \ + --enable-old-ctdb \ + --with-profiling-data \ + --with-libiconv=${STAGING_DIR_HOST}${prefix} \ + " + +LDFLAGS += "-Wl,-z,relro,-z,now" + +do_install_append() { + rmdir --ignore-fail-on-non-empty "${D}/${localstatedir}/run" + + if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then + install -d ${D}${systemd_unitdir}/system + for i in nmb smb winbind; do + install -m 0644 packaging/systemd/$i.service ${D}${systemd_unitdir}/system + done + sed -e 's,@BASE_BINDIR@,${base_bindir},g' \ + -e 's,@SBINDIR@,${sbindir},g' \ + -i ${D}${systemd_unitdir}/system/*.service + + install -d ${D}${sysconfdir}/tmpfiles.d + echo "d ${localstatedir}/log/samba 0755 root root -" \ + > ${D}${sysconfdir}/tmpfiles.d/99-${BPN}.conf + fi + + install -d ${D}${sysconfdir}/samba + echo "127.0.0.1 localhost" > ${D}${sysconfdir}/samba/lmhosts + install -m644 packaging/LSB/smb.conf ${D}${sysconfdir}/samba/smb.conf + + install -d ${D}${libdir}/tmpfiles.d + install -m644 packaging/systemd/samba.conf.tmp ${D}${libdir}/tmpfiles.d/samba.conf + + install -d ${D}${sysconfdir}/sysconfig/ + install -m644 packaging/systemd/samba.sysconfig ${D}${sysconfdir}/sysconfig/samba +} + +PACKAGES += "${PN}-python ${PN}-python-dbg ${PN}-pidl libwinbind libwinbind-dbg libwinbind-krb5-locator" + +FILES_${PN} += "/run \ + ${libdir}/security/pam_smbpass.so \ + ${libdir}/tmpfiles.d/* \ + " + +SMB_SERVICE="${systemd_unitdir}/system/nmb.service ${systemd_unitdir}/system/smb.service" +FILES_${PN} +="${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${SMB_SERVICE}', '', d)}" + +FILES_${PN}-dbg += "${libdir}/samba/idmap/.debug/* \ + ${libdir}/samba/pdb/.debug/* \ + ${libdir}/samba/auth/.debug/* \ + ${libdir}/samba/nss_info/.debug/* \ + ${libdir}/samba/ldb/.debug/* \ + ${libdir}/samba/vfs/.debug/* \ + ${libdir}/security/.debug/pam_smbpass.so \ + " + +FILES_libwinbind = "${libdir}/security/pam_winbind.so" +FILES_libwinbind += "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${systemd_unitdir}/system/winbind.service', '', d)}" +FILES_libwinbind-dbg = "${libdir}/security/.debug/pam_winbind.so" +FILES_libwinbind-krb5-locator = "${libdir}/winbind_krb5_locator.so" + +FILES_${PN}-python = "${libdir}/python${PYTHON_BASEVERSION}/site-packages/*.so \ + ${libdir}/python${PYTHON_BASEVERSION}/site-packages/samba/*.py \ + ${libdir}/python${PYTHON_BASEVERSION}/site-packages/samba/*.so \ + ${libdir}/python${PYTHON_BASEVERSION}/site-packages/samba/dcerpc/*.so \ + ${libdir}/python${PYTHON_BASEVERSION}/site-packages/samba/dcerpc/*.py \ + ${libdir}/python${PYTHON_BASEVERSION}/site-packages/samba/external/* \ + ${libdir}/python${PYTHON_BASEVERSION}/site-packages/samba/netcmd/*.py \ + ${libdir}/python${PYTHON_BASEVERSION}/site-packages/samba/provision/*.py \ + ${libdir}/python${PYTHON_BASEVERSION}/site-packages/samba/samba3/*.py \ + ${libdir}/python${PYTHON_BASEVERSION}/site-packages/samba/samba3/*.so \ + ${libdir}/python${PYTHON_BASEVERSION}/site-packages/samba/tests/* \ + ${libdir}/python${PYTHON_BASEVERSION}/site-packages/samba/web_server/* \ + " +FILES_${PN}-python-dbg = "${libdir}/python${PYTHON_BASEVERSION}/site-packages/.debug/* \ + ${libdir}/python${PYTHON_BASEVERSION}/site-packages/samba/.debug/* \ + ${libdir}/python${PYTHON_BASEVERSION}/site-packages/samba/samba3/.debug/* \ + ${libdir}/python${PYTHON_BASEVERSION}/site-packages/samba/dcerpc/.debug/* \ + " + +FILES_${PN}-pidl = "${datadir}/perl5/vendor_perl/*"