This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to...
authorcvs2svn Import User <samba-bugs@samba.org>
Sun, 14 Jul 2002 22:15:21 +0000 (22:15 +0000)
committercvs2svn Import User <samba-bugs@samba.org>
Sun, 14 Jul 2002 22:15:21 +0000 (22:15 +0000)
34 files changed:
docs/faq/README [new file with mode: 0644]
examples/LDAP/samba-schema-netscapeds4.x [new file with mode: 0644]
examples/LDAP/samba-schema-netscapeds5.x [new file with mode: 0644]
examples/LDAP/samba-schema.IBMSecureWay [new file with mode: 0644]
source3/lib/data_blob.c [new file with mode: 0644]
source3/lib/server_mutex.c [new file with mode: 0644]
source3/libads/kerberos_verify.c [new file with mode: 0644]
source3/libsmb/cli_spoolss_notify.c [new file with mode: 0644]
source3/libsmb/libsmb_cache.c [new file with mode: 0644]
source3/libsmb/libsmb_compat.c [new file with mode: 0644]
source3/nsswitch/winbindd_dual.c [new file with mode: 0644]
source3/pam_smbpass/INSTALL [new file with mode: 0644]
source3/passdb/pdb_compat.c [new file with mode: 0644]
source3/passdb/pdb_unix.c [new file with mode: 0644]
source3/passdb/util_sam_sid.c [new file with mode: 0644]
source3/printing/notify.c [new file with mode: 0644]
source3/python/py_common.h [new file with mode: 0644]
source3/python/py_lsa.h [new file with mode: 0644]
source3/python/py_lsa_proto.h [new file with mode: 0644]
source3/python/py_ntsec.c [new file with mode: 0644]
source3/python/py_samr.h [new file with mode: 0644]
source3/python/py_spoolss.h [new file with mode: 0644]
source3/python/py_spoolss_forms_conv.c [new file with mode: 0644]
source3/python/py_spoolss_jobs_conv.c [new file with mode: 0644]
source3/python/py_spoolss_ports.c [new file with mode: 0644]
source3/python/py_tdb.c [new file with mode: 0644]
source3/python/py_tdb.h [new file with mode: 0644]
source3/python/py_winreg.c [new file with mode: 0644]
source3/python/py_winreg.h [new file with mode: 0644]
source3/rpc_server/srv_samr_util.c [new file with mode: 0644]
source3/script/findsmb.in [new file with mode: 0755]
source3/script/findstatic.pl [new file with mode: 0755]
source3/tdb/tdbutil.h [new file with mode: 0644]
source3/utils/.cvsignore [new file with mode: 0644]

diff --git a/docs/faq/README b/docs/faq/README
new file mode 100644 (file)
index 0000000..f4f0e8a
--- /dev/null
@@ -0,0 +1,8 @@
+This directory contains the old Samba FAQ.
+It is now horribly outdated and unmaintained.
+It is being left here in case there is some
+useful information within. 
+
+
+--jerry@samba.org
+
diff --git a/examples/LDAP/samba-schema-netscapeds4.x b/examples/LDAP/samba-schema-netscapeds4.x
new file mode 100644 (file)
index 0000000..c5a11b8
--- /dev/null
@@ -0,0 +1,54 @@
+#
+# LDAP Schema file for SAMBA attribute storage 
+# This file is suitable for usage with Netscape Directory Server 4.1x
+# Adapted by Scott Lawson with help from Ron Creamer
+#
+
+attribute       lmPassword              1.3.6.1.4.1.7165.2.1.1  cis single
+attribute       ntPassword              1.3.6.1.4.1.7165.2.1.2  cis single
+attribute       acctFlags               1.3.6.1.4.1.7165.2.1.4  cis single
+attribute       pwdLastSet              1.3.6.1.4.1.7165.2.1.3  int single
+attribute       logonTime               1.3.6.1.4.1.7165.2.1.5  int single
+attribute       logoffTime              1.3.6.1.4.1.7165.2.1.6  int single
+attribute       kickoffTime             1.3.6.1.4.1.7165.2.1.7  int single
+attribute       pwdCanChange            1.3.6.1.4.1.7165.2.1.8  int single
+attribute       pwdMustChange           1.3.6.1.4.1.7165.2.1.9  int single
+attribute       homedrive               1.3.6.1.4.1.7165.2.1.10 cis single
+attribute       scriptPath              1.3.6.1.4.1.7165.2.1.11 cis single
+attribute       profilePath             1.3.6.1.4.1.7165.2.1.12 cis single
+attribute       userWorkstations        1.3.6.1.4.1.7165.2.1.13 cis single
+attribute       rid                     1.3.6.1.4.1.7165.2.1.14 int single
+attribute       primaryGroupID          1.3.6.1.4.1.7165.2.1.15 int single
+attribute       smbHome                 1.3.6.1.4.1.7165.2.1.17 cis single
+attribute       domain                  1.3.6.1.4.1.7165.2.1.18 cis single
+
+objectclass sambaAccount
+       oid
+               1.3.1.5.1.4.1.7165.2.2.2
+       superior
+               top
+       requires
+               objectClass,
+               uid,
+               rid
+       allows
+               cn,
+               lmPassword,
+               ntPassword,
+               pwdLastSet,
+               logonTime,
+               logoffTime,
+               KickoffTime,
+               pwdCanChange,
+               pwdMustChange,
+               acctFlags,
+               displayName,
+               smbHome,
+               homeDrive,
+               scriptPath,
+               profilePath,
+               description,
+               userWorkstations,
+               primaryGroupID,
+               domain
+
diff --git a/examples/LDAP/samba-schema-netscapeds5.x b/examples/LDAP/samba-schema-netscapeds5.x
new file mode 100644 (file)
index 0000000..0abc9d8
--- /dev/null
@@ -0,0 +1,74 @@
+##\r
+## submitted by Martin.Dehn@comparex.de\r
+##\r
+## Experiement sambaAccount schema file Netscape DS 5.0\r
+##\r
+## INSTALL-DIRECTORY/slapd-your_name/config/schema/samba-schema-netscapeds5.ldif\r
+##\r
+dn: cn=schema\r
+objectClass: top\r
+objectClass: ldapSubentry\r
+objectClass: subschema\r
+cn: schema\r
+aci: (target="ldap:///cn=schema")(targetattr !="aci")(version 3.0;acl "anonymo\r
+ us, no acis"; allow (read, search, compare) userdn = "ldap:///anyone";)\r
+aci: (targetattr = "*")(version 3.0; acl "Configuration Administrator"; allow \r
+ (all) userdn = "ldap:///uid=admin,ou=Administrators, ou=TopologyManagement, \r
+ o=NetscapeRoot";)\r
+aci: (targetattr = "*")(version 3.0; acl "Local Directory Administrators Group\r
+ "; allow (all) groupdn = "ldap:///cn=Directory Administrators, dc=samba,dc=org";)\r
+aci: (targetattr = "*")(version 3.0; acl "SIE Group"; allow (all)groupdn = "ld\r
+ ap:///cn=slapd-sambaldap, cn=iPlanet Directory Server, cn=Server Group, cn=iPlanetDirectory.samba.org, ou=samba.org, o=NetscapeRoot";)\r
+modifiersName: cn=directory manager\r
+modifyTimestamp: 20020322124844Z\r
+objectClasses: ( 1.3.1.5.1.4.1.7165.2.2.2 NAME 'sambaAccount' SUP top STRUCTUR\r
+ AL MAY ( acctFlags $ domain $ homeDrive $ kickoffTime $ lmPassword $ logofft\r
+ ime $ logonTime $ ntPassword $ primaryGroupID $ profilePath $ pwdCanChange $\r
+  pwdLastSet $ pwdMustChange $ rid $ scriptPath $ smbHome $ userWorkstations \r
+ ) X-ORIGIN 'user defined' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.11 NAME 'scriptPath' DESC 'NT script pa\r
+ th' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined\r
+ ' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.5 NAME 'logonTime' DESC 'NT logon time'\r
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.12 NAME 'profilePath' DESC 'NT profile \r
+ path' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defin\r
+ ed' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.8 NAME 'pwdCanChange' DESC 'NT passwd c\r
+ an change' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user \r
+ defined' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.17 NAME 'smbHome' DESC 'smbHome' SYNTAX\r
+  1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.3 NAME 'pwdLastSet'  SYNTAX 1.3.6.1.4.1\r
+ .1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.18 NAME 'domain' DESC 'Windows NT domai\r
+ n Samba' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user de\r
+ fined' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.10 NAME 'homeDrive' DESC 'NT home drive\r
+ ' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined' \r
+ )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.6 NAME 'logofftime' DESC 'logoff Time' \r
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.15 NAME 'primaryGroupID' DESC 'NT Group\r
+  RID' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defin\r
+ ed' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.1 NAME 'lmPassword' DESC 'LanManager Pa\r
+ sswd' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defin\r
+ ed' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.9 NAME 'pwdMustChange' DESC 'NT pwdmust\r
+ chnage' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user def\r
+ ined' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.4 NAME 'acctFlags' DESC 'Account Flags'\r
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.13 NAME 'userWorkstations' DESC 'userWo\r
+ rkstations' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user\r
+  defined' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.7 NAME 'kickoffTime' DESC 'NT kickoff T\r
+ ime' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user define\r
+ d' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.14 NAME 'rid' DESC 'rid' SYNTAX 1.3.6.1\r
+ .4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )\r
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.2 NAME 'ntPassword' DESC 'NT Passwd' SY\r
+ NTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined' )\r
+nsSchemaCSN: 3c9b282c000000000000\r
+\r
diff --git a/examples/LDAP/samba-schema.IBMSecureWay b/examples/LDAP/samba-schema.IBMSecureWay
new file mode 100644 (file)
index 0000000..1fca4a7
--- /dev/null
@@ -0,0 +1,43 @@
+##
+## Submitted by Dirk Kastens <Dirk.Kastens@Uni-Osnabrueck.de>
+##
+## I translated the samba.schema to be used with IBM
+## SecureWay directoy server 3.2.2. You have to load
+## it in your slapd32.conf with:
+##
+## dn: cn=IBM SecureWay, cn=Schemas, cn=Configuration
+## cn: IBM SecureWay
+## ibm-slapdIncludeSchema: /etc/lapschema/samba.schema
+##
+objectClasses {
+( 1.3.1.5.1.4.1.7165.2.2.2 NAME 'sambaAccount' DESC 'Samba Account' SUP top MUST uid $ rid MAY ( acctFlags $ cn $ description $ displayName $ homeDrive $ kickoffTime $ lmPassword $ logoffTime $ logonTime $ ntPassword $ primaryGroupID $ profilePath $ pwdCanChange $ pwdLastSet $ pwdMustChange $ scriptPath $ smbHome $ userWorkstations ) )
+}
+
+attributeTypes {
+( 1.3.6.1.4.1.7165.2.1.1 NAME 'lmPassword' DESC 'LanManager Passwd' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.10 NAME 'homeDrive' DESC 'NT homeDrive' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{4} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.11 NAME 'scriptPath' DESC 'NT scriptPath' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.12 NAME 'profilePath' DESC 'NT profilePath' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.13 NAME 'userWorkstations' DESC 'userWorkstations' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.14 NAME 'rid' DESC 'NT rid' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.15 NAME 'primaryGroupID' DESC 'NT Group RID' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.17 NAME 'smbHome' DESC 'smbHome' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} )
+( 1.3.6.1.4.1.7165.2.1.2 NAME 'ntPassword' DESC 'NT Passwd' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.3 NAME 'pwdLastSet' DESC 'NT pwdLastSet' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.4 NAME 'acctFlags' DESC 'Account Flags' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.5 NAME 'logonTime' DESC 'NT logonTime' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.6 NAME 'logoffTime' DESC 'NT logoffTime' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.7 NAME 'kickoffTime' DESC 'NT kickoffTime' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.8 NAME 'pwdCanChange' DESC 'NT pwdCanChange' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.9 NAME 'pwdMustChange' DESC 'NT pwdMustChange' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+}
+
+IBMattributeTypes {
+}
+
+ldapSyntaxes {
+}
+
+matchingRules {
+}
+
diff --git a/source3/lib/data_blob.c b/source3/lib/data_blob.c
new file mode 100644 (file)
index 0000000..d690cd0
--- /dev/null
@@ -0,0 +1,109 @@
+/* 
+   Unix SMB/CIFS implementation.
+   Easy management of byte-length data
+   Copyright (C) Andrew Tridgell 2001
+   Copyright (C) Andrew Bartlett 2001
+   
+   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"
+
+/*******************************************************************
+ free() a data blob
+*******************************************************************/
+static void free_data_blob(DATA_BLOB *d)
+{
+       if ((d) && (d->free)) {
+               SAFE_FREE(d->data);
+       }
+}
+
+/*******************************************************************
+ construct a data blob, must be freed with data_blob_free()
+ you can pass NULL for p and get a blank data blob
+*******************************************************************/
+DATA_BLOB data_blob(const void *p, size_t length)
+{
+       DATA_BLOB ret;
+
+       if (!length) {
+               ZERO_STRUCT(ret);
+               return ret;
+       }
+
+       if (p) {
+               ret.data = smb_xmemdup(p, length);
+       } else {
+               ret.data = smb_xmalloc(length);
+       }
+       ret.length = length;
+       ret.free = free_data_blob;
+       return ret;
+}
+
+/*******************************************************************
+ construct a data blob, using supplied TALLOC_CTX
+*******************************************************************/
+DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length)
+{
+       DATA_BLOB ret;
+
+       if (!p || !length) {
+               ZERO_STRUCT(ret);
+               return ret;
+       }
+
+       ret.data = talloc_memdup(mem_ctx, p, length);
+       if (ret.data == NULL)
+               smb_panic("data_blob_talloc: talloc_memdup failed.\n");
+
+       ret.length = length;
+       ret.free = NULL;
+       return ret;
+}
+
+/*******************************************************************
+free a data blob
+*******************************************************************/
+void data_blob_free(DATA_BLOB *d)
+{
+       if (d) {
+               if (d->free) {
+                       (d->free)(d);
+               }
+               ZERO_STRUCTP(d);
+       }
+}
+
+/*******************************************************************
+clear a DATA_BLOB's contents
+*******************************************************************/
+static void data_blob_clear(DATA_BLOB *d)
+{
+       if (d->data) {
+               memset(d->data, 0, d->length);
+       }
+}
+
+/*******************************************************************
+free a data blob and clear its contents
+*******************************************************************/
+void data_blob_clear_free(DATA_BLOB *d)
+{
+       data_blob_clear(d);
+       data_blob_free(d);
+}
+
diff --git a/source3/lib/server_mutex.c b/source3/lib/server_mutex.c
new file mode 100644 (file)
index 0000000..416d775
--- /dev/null
@@ -0,0 +1,57 @@
+/* 
+   Unix SMB/CIFS implementation.
+   Authenticate against a remote domain
+   Copyright (C) Andrew Tridgell 1992-2002
+   Copyright (C) Andrew Bartlett 2002
+   
+   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"
+
+/* For reasons known only to MS, many of their NT/Win2k versions
+   need serialised access only.  Two connections at the same time
+   may (in certain situations) cause connections to be reset,
+   or access to be denied.
+
+   This locking allows smbd's mutlithread architecture to look
+   like the single-connection that NT makes. */
+
+static char *mutex_server_name;
+
+BOOL grab_server_mutex(const char *name)
+{
+       mutex_server_name = strdup(name);
+       if (!mutex_server_name) {
+               DEBUG(0,("grab_server_mutex: malloc failed for %s\n", name));
+               return False;
+       }
+       if (!message_named_mutex(mutex_server_name, 20)) {
+               DEBUG(10,("grab_server_mutex: failed for %s\n", name));
+               SAFE_FREE(mutex_server_name);
+               return False;
+       }
+
+       return True;
+}
+
+void release_server_mutex(void)
+{
+       if (mutex_server_name) {
+               message_named_mutex_release(mutex_server_name);
+               SAFE_FREE(mutex_server_name);
+       }
+}
+
diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c
new file mode 100644 (file)
index 0000000..dac9090
--- /dev/null
@@ -0,0 +1,151 @@
+/* 
+   Unix SMB/CIFS implementation.
+   kerberos utility library
+   Copyright (C) Andrew Tridgell 2001
+   Copyright (C) Remus Koos 2001
+   
+   
+   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"
+
+#ifdef HAVE_KRB5
+
+/*
+  verify an incoming ticket and parse out the principal name and 
+  authorization_data if available 
+*/
+NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, 
+                          char **principal, DATA_BLOB *auth_data)
+{
+       krb5_context context;
+       krb5_auth_context auth_context = NULL;
+       krb5_keytab keytab = NULL;
+       krb5_data packet;
+       krb5_ticket *tkt = NULL;
+       krb5_data salt;
+       krb5_encrypt_block eblock;
+       int ret;
+       krb5_keyblock * key;
+       krb5_principal host_princ;
+       char *host_princ_s;
+       extern pstring global_myname;
+       fstring myname;
+       char *password_s;
+       krb5_data password;
+
+       if (!secrets_init()) {
+               DEBUG(1,("secrets_init failed\n"));
+               return NT_STATUS_LOGON_FAILURE;
+       }
+
+       password_s = secrets_fetch_machine_password();
+       if (!password_s) {
+               DEBUG(1,("failed to fetch machine password\n"));
+               return NT_STATUS_LOGON_FAILURE;
+       }
+
+       password.data = password_s;
+       password.length = strlen(password_s);
+
+       ret = krb5_init_context(&context);
+       if (ret) {
+               DEBUG(1,("krb5_init_context failed (%s)\n", error_message(ret)));
+               return NT_STATUS_LOGON_FAILURE;
+       }
+
+       ret = krb5_set_default_realm(context, ads->realm);
+       if (ret) {
+               DEBUG(1,("krb5_set_default_realm failed (%s)\n", error_message(ret)));
+               ads_destroy(&ads);
+               return NT_STATUS_LOGON_FAILURE;
+       }
+
+       /* this whole process is far more complex than I would
+           like. We have to go through all this to allow us to store
+           the secret internally, instead of using /etc/krb5.keytab */
+       ret = krb5_auth_con_init(context, &auth_context);
+       if (ret) {
+               DEBUG(1,("krb5_auth_con_init failed (%s)\n", error_message(ret)));
+               return NT_STATUS_LOGON_FAILURE;
+       }
+
+       fstrcpy(myname, global_myname);
+       strlower(myname);
+       asprintf(&host_princ_s, "HOST/%s@%s", myname, lp_realm());
+       ret = krb5_parse_name(context, host_princ_s, &host_princ);
+       if (ret) {
+               DEBUG(1,("krb5_parse_name(%s) failed (%s)\n", host_princ_s, error_message(ret)));
+               return NT_STATUS_LOGON_FAILURE;
+       }
+
+       ret = krb5_principal2salt(context, host_princ, &salt);
+       if (ret) {
+               DEBUG(1,("krb5_principal2salt failed (%s)\n", error_message(ret)));
+               return NT_STATUS_LOGON_FAILURE;
+       }
+    
+       if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       
+       krb5_use_enctype(context, &eblock, ENCTYPE_DES_CBC_MD5);
+       
+       ret = krb5_string_to_key(context, &eblock, key, &password, &salt);
+       if (ret) {
+               DEBUG(1,("krb5_string_to_key failed (%s)\n", error_message(ret)));
+               return NT_STATUS_LOGON_FAILURE;
+       }
+
+       krb5_auth_con_setuseruserkey(context, auth_context, key);
+
+       packet.length = ticket->length;
+       packet.data = (krb5_pointer)ticket->data;
+
+#if 0
+       file_save("/tmp/ticket.dat", ticket->data, ticket->length);
+#endif
+
+       if ((ret = krb5_rd_req(context, &auth_context, &packet, 
+                              NULL, keytab, NULL, &tkt))) {
+               DEBUG(3,("krb5_rd_req with auth failed (%s)\n", 
+                        error_message(ret)));
+               return NT_STATUS_LOGON_FAILURE;
+       }
+
+       if (tkt->enc_part2) {
+               *auth_data = data_blob(tkt->enc_part2->authorization_data[0]->contents,
+                                      tkt->enc_part2->authorization_data[0]->length);
+       }
+
+#if 0
+       if (tkt->enc_part2) {
+               file_save("/tmp/authdata.dat", 
+                         tkt->enc_part2->authorization_data[0]->contents,
+                         tkt->enc_part2->authorization_data[0]->length);
+       }
+#endif
+
+       if ((ret = krb5_unparse_name(context, tkt->enc_part2->client, principal))) {
+               DEBUG(3,("krb5_unparse_name failed (%s)\n", 
+                        error_message(ret)));
+               return NT_STATUS_LOGON_FAILURE;
+       }
+
+       return NT_STATUS_OK;
+}
+
+#endif
diff --git a/source3/libsmb/cli_spoolss_notify.c b/source3/libsmb/cli_spoolss_notify.c
new file mode 100644 (file)
index 0000000..922b0fb
--- /dev/null
@@ -0,0 +1,223 @@
+/* 
+   Unix SMB/CIFS implementation.
+   RPC pipe client
+
+   Copyright (C) Gerald Carter                2001-2002,
+   Copyright (C) Tim Potter                   2000-2002,
+   Copyright (C) Andrew Tridgell              1994-2000,
+   Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
+   Copyright (C) Jean-Francois Micouleau      1999-2000.
+
+   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"
+
+/*
+ * SPOOLSS Client RPC's used by servers as the notification
+ * back channel.
+ */
+
+/* Send a ReplyOpenPrinter request.  This rpc is made by the printer
+   server to the printer client in response to a rffpcnex request.
+   The rrfpcnex request names a printer and a handle (the printerlocal
+   value) and this rpc establishes a back-channel over which printer
+   notifications are performed. */
+
+WERROR cli_spoolss_reply_open_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+                                     char *printer, uint32 printerlocal, uint32 type, 
+                                     POLICY_HND *handle)
+{
+       prs_struct qbuf, rbuf;
+       SPOOL_Q_REPLYOPENPRINTER q;
+       SPOOL_R_REPLYOPENPRINTER r;
+       WERROR result = W_ERROR(ERRgeneral);
+       
+       /* Initialise input parameters */
+
+       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+       make_spoolss_q_replyopenprinter(&q, printer, printerlocal, type);
+
+       /* Marshall data and send request */
+
+       if (!spoolss_io_q_replyopenprinter("", &q, &qbuf, 0) ||
+           !rpc_api_pipe_req (cli, SPOOLSS_REPLYOPENPRINTER, &qbuf, &rbuf)) 
+               goto done;
+       
+       /* Unmarshall response */
+       
+       if (!spoolss_io_r_replyopenprinter("", &r, &rbuf, 0))
+               goto done;
+               
+       /* Return result */
+
+       memcpy(handle, &r.handle, sizeof(r.handle));
+       result = r.status;
+
+done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+
+       return result;
+}
+
+/* Close a back-channel notification connection */
+
+WERROR cli_spoolss_reply_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+                                      POLICY_HND *handle)
+{
+       prs_struct qbuf, rbuf;
+       SPOOL_Q_REPLYCLOSEPRINTER q;
+       SPOOL_R_REPLYCLOSEPRINTER r;
+       WERROR result = W_ERROR(ERRgeneral);
+
+       /* Initialise input parameters */
+
+       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+       make_spoolss_q_reply_closeprinter(&q, handle);
+
+       /* Marshall data and send request */
+
+       if (!spoolss_io_q_replycloseprinter("", &q, &qbuf, 0) ||
+           !rpc_api_pipe_req (cli, SPOOLSS_REPLYCLOSEPRINTER, &qbuf, &rbuf)) 
+               goto done;
+       
+       /* Unmarshall response */
+       
+       if (!spoolss_io_r_replycloseprinter("", &r, &rbuf, 0))
+               goto done;
+               
+       /* Return result */
+
+       result = r.status;
+       
+done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+
+       return result;
+}
+
+/*********************************************************************
+ This SPOOLSS_ROUTERREPLYPRINTER function is used to send a change 
+ notification event when the registration **did not** use 
+ SPOOL_NOTIFY_OPTION_TYPE structure to specify the events to monitor.
+ Also see cli_spolss_reply_rrpcn()
+ *********************************************************************/
+WERROR cli_spoolss_routerreplyprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                                     POLICY_HND *pol, uint32 condition, uint32 change_id)
+{
+       prs_struct qbuf, rbuf;
+       SPOOL_Q_ROUTERREPLYPRINTER q;
+        SPOOL_R_ROUTERREPLYPRINTER r;
+       WERROR result = W_ERROR(ERRgeneral);
+
+       /* Initialise input parameters */
+
+       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+       make_spoolss_q_routerreplyprinter(&q, pol, condition, change_id);
+
+       /* Marshall data and send request */
+
+       if (!spoolss_io_q_routerreplyprinter("", &q, &qbuf, 0) ||
+           !rpc_api_pipe_req (cli, SPOOLSS_ROUTERREPLYPRINTER, &qbuf, &rbuf)) 
+               goto done;
+       
+       /* Unmarshall response */
+       
+       if (!spoolss_io_r_routerreplyprinter("", &r, &rbuf, 0))
+               goto done;
+
+       /* Return output parameters */
+
+       result = r.status;
+
+done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+
+       return result;  
+}
+
+/*********************************************************************
+ This SPOOLSS_REPLY_RRPCN function is used to send a change 
+ notification event when the registration **did** use 
+ SPOOL_NOTIFY_OPTION_TYPE structure to specify the events to monitor
+ Also see cli_spoolss_routereplyprinter()
+ *********************************************************************/
+
+WERROR cli_spoolss_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+                        POLICY_HND *pol, uint32 notify_data_len,
+                        SPOOL_NOTIFY_INFO_DATA *notify_data,
+                        uint32 change_low, uint32 change_high)
+{
+       prs_struct qbuf, rbuf;
+       SPOOL_Q_REPLY_RRPCN q;
+       SPOOL_R_REPLY_RRPCN r;
+       WERROR result = W_ERROR(ERRgeneral);
+       SPOOL_NOTIFY_INFO       notify_info;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Initialise parse structures */
+
+       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+       ZERO_STRUCT(notify_info);
+
+       /* Initialise input parameters */
+
+       notify_info.version = 0x2;
+       notify_info.flags   = 0x00020000;       /* ?? */
+       notify_info.count   = notify_data_len;
+       notify_info.data    = notify_data;
+
+       /* create and send a MSRPC command with api  */
+       /* store the parameters */
+
+       make_spoolss_q_reply_rrpcn(&q, pol, change_low, change_high, 
+                                  &notify_info);
+
+       /* Marshall data and send request */
+
+       if(!spoolss_io_q_reply_rrpcn("", &q,  &qbuf, 0) ||
+          !rpc_api_pipe_req(cli, SPOOLSS_RRPCN, &qbuf, &rbuf)) 
+               goto done;
+
+       /* Unmarshall response */
+       
+       if(!spoolss_io_r_reply_rrpcn("", &r, &rbuf, 0))
+               goto done;
+
+       if (r.unknown0 == 0x00080000)
+               DEBUG(8,("cli_spoolss_reply_rrpcn: I think the spooler resonded that the notification was ignored.\n"));
+       
+       result = r.status;
+
+done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+
+       return result;
+}
diff --git a/source3/libsmb/libsmb_cache.c b/source3/libsmb/libsmb_cache.c
new file mode 100644 (file)
index 0000000..34b818e
--- /dev/null
@@ -0,0 +1,191 @@
+/* 
+   Unix SMB/CIFS implementation.
+   SMB client library implementation (server cache)
+   Copyright (C) Andrew Tridgell 1998
+   Copyright (C) Richard Sharpe 2000
+   Copyright (C) John Terpstra 2000
+   Copyright (C) Tom Jansen (Ninja ISD) 2002 
+   
+   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"
+
+/*
+ * Define this to get the real SMBCFILE and SMBCSRV structures 
+ */
+#define _SMBC_INTERNAL
+#include "libsmbclient.h"
+
+/*
+ * Structure we use if internal caching mechanism is used 
+ * nothing fancy here.
+ */
+struct smbc_server_cache {
+       char *server_name;
+       char *share_name;
+       char *workgroup;
+       char *username;
+       SMBCSRV *server;
+       
+       struct smbc_server_cache *next, *prev;
+};
+       
+
+
+/*
+ * Add a new connection to the server cache.
+ * This function is only used if the external cache is not enabled 
+ */
+static int smbc_add_cached_server(SMBCCTX * context, SMBCSRV * new,
+                                 char * server, char * share, 
+                                 char * workgroup, char * username)
+{
+       struct smbc_server_cache * srvcache = NULL;
+
+       if (!(srvcache = malloc(sizeof(*srvcache)))) {
+               errno = ENOMEM;
+               DEBUG(3, ("Not enough space for server cache allocation\n"));
+               return 1;
+       }
+       
+       ZERO_STRUCTP(srvcache);
+
+       srvcache->server = new;
+
+       srvcache->server_name = strdup(server);
+       if (!srvcache->server_name) {
+               errno = ENOMEM;
+               goto failed;
+       }
+
+       srvcache->share_name = strdup(share);
+       if (!srvcache->share_name) {
+               errno = ENOMEM;
+               goto failed;
+       }
+
+       srvcache->workgroup = strdup(workgroup);
+       if (!srvcache->workgroup) {
+               errno = ENOMEM;
+               goto failed;
+       }
+
+       srvcache->username = strdup(username);
+       if (!srvcache->username) {
+               errno = ENOMEM;
+               goto failed;
+       }
+
+       DLIST_ADD(((struct smbc_server_cache *)context->server_cache), srvcache);
+       return 0;
+
+ failed:
+       SAFE_FREE(srvcache->server_name);
+       SAFE_FREE(srvcache->share_name);
+       SAFE_FREE(srvcache->workgroup);
+       SAFE_FREE(srvcache->username);
+       
+       return 1;
+}
+
+
+
+/*
+ * Search the server cache for a server 
+ * returns server_fd on success, -1 on error (not found)
+ * This function is only used if the external cache is not enabled 
+ */
+static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, char * server, 
+                                 char * share, char * workgroup, char * user)
+{
+       struct smbc_server_cache * srv = NULL;
+       
+       /* Search the cache lines */
+       for (srv=((struct smbc_server_cache *)context->server_cache);srv;srv=srv->next) {
+               if (strcmp(server,srv->server_name)  == 0 &&
+                   strcmp(share,srv->share_name)    == 0 &&
+                   strcmp(workgroup,srv->workgroup) == 0 &&
+                   strcmp(user, srv->username)  == 0) 
+                       return srv->server;
+       }
+
+       return NULL;
+}
+
+
+/* 
+ * Search the server cache for a server and remove it
+ * returns 0 on success
+ * This function is only used if the external cache is not enabled 
+ */
+static int smbc_remove_cached_server(SMBCCTX * context, SMBCSRV * server)
+{
+       struct smbc_server_cache * srv = NULL;
+       
+       for (srv=((struct smbc_server_cache *)context->server_cache);srv;srv=srv->next) {
+               if (server == srv->server) { 
+
+                       /* remove this sucker */
+                       DLIST_REMOVE(((struct smbc_server_cache *)context->server_cache), srv);
+                       SAFE_FREE(srv->server_name);
+                       SAFE_FREE(srv->share_name);
+                       SAFE_FREE(srv->workgroup);
+                       SAFE_FREE(srv->username);
+                       SAFE_FREE(srv);
+                       return 0;
+               }
+       }
+       /* server not found */
+       return 1;
+}
+
+
+/*
+ * Try to remove all the servers in cache
+ * returns 1 on failure and 0 if all servers could be removed.
+ */
+static int smbc_purge_cached(SMBCCTX * context)
+{
+       struct smbc_server_cache * srv = NULL;
+       int could_not_purge_all = 0;
+
+       for (srv=((struct smbc_server_cache *) context->server_cache);srv;srv=srv->next) {
+               if (smbc_remove_unused_server(context, srv->server)) {
+                       /* could not be removed */
+                       could_not_purge_all = 1;
+               }
+       }
+       return could_not_purge_all;
+}
+
+
+
+/*
+ * This functions initializes all server-cache related functions 
+ * to the default (internal) system.
+ *
+ * We use this to make the rest of the cache system static.
+ */
+
+int smbc_default_cache_functions(SMBCCTX * context)
+{
+       context->callbacks.add_cached_srv_fn    = smbc_add_cached_server;
+       context->callbacks.get_cached_srv_fn    = smbc_get_cached_server;
+       context->callbacks.remove_cached_srv_fn = smbc_remove_cached_server;
+       context->callbacks.purge_cached_fn      = smbc_purge_cached;
+
+       return 0;
+}
diff --git a/source3/libsmb/libsmb_compat.c b/source3/libsmb/libsmb_compat.c
new file mode 100644 (file)
index 0000000..dbfd860
--- /dev/null
@@ -0,0 +1,285 @@
+/* 
+   Unix SMB/CIFS implementation.
+   SMB client library implementation (Old interface compatibility)
+   Copyright (C) Andrew Tridgell 1998
+   Copyright (C) Richard Sharpe 2000
+   Copyright (C) John Terpstra 2000
+   Copyright (C) Tom Jansen (Ninja ISD) 2002 
+   
+   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"
+
+/*
+ * Define this to get the real SMBCFILE and SMBCSRV structures 
+ */
+#define _SMBC_INTERNAL
+#include "libsmbclient.h"
+
+struct smbc_compat_fdlist {
+       SMBCFILE * file;
+       int fd;
+       struct smbc_compat_fdlist *next, *prev;
+};
+
+static SMBCCTX * statcont = NULL;
+static int smbc_compat_initialized = 0;
+static int smbc_currentfd = 10000;
+static struct smbc_compat_fdlist * smbc_compat_fdlist = NULL;
+
+
+/* Find an fd and return the SMBCFILE * or NULL on failure */
+static SMBCFILE * find_fd(int fd)
+{
+       struct smbc_compat_fdlist * f = smbc_compat_fdlist;
+       while (f) {
+               if (f->fd == fd) 
+                       return f->file;
+               f = f->next;
+       }
+       return NULL;
+}
+
+/* Add an fd, returns 0 on success, -1 on error with errno set */
+static int add_fd(SMBCFILE * file)
+{
+       struct smbc_compat_fdlist * f = malloc(sizeof(struct smbc_compat_fdlist));
+       if (!f) {
+               errno = ENOMEM;
+               return -1;
+       }
+       
+       f->fd = smbc_currentfd++;
+       f->file = file;
+       
+       DLIST_ADD(smbc_compat_fdlist, f);
+
+       return f->fd;
+}
+
+
+
+/* Delete an fd, returns 0 on success */
+static int del_fd(int fd)
+{
+       struct smbc_compat_fdlist * f = smbc_compat_fdlist;
+       while (f) {
+               if (f->fd == fd) 
+                       break;
+               f = f->next;
+       }
+       if (f) {
+               /* found */
+               DLIST_REMOVE(smbc_compat_fdlist, f);
+               SAFE_FREE(f);
+               return 0;
+       }
+       return 1;
+}
+
+
+int smbc_init(smbc_get_auth_data_fn fn, int debug)
+{
+       if (!smbc_compat_initialized) {
+               statcont = smbc_new_context();
+               if (!statcont) 
+                       return -1;
+
+               statcont->debug = debug;
+               statcont->callbacks.auth_fn = fn;
+               
+               if (!smbc_init_context(statcont)) {
+                       smbc_free_context(statcont, False);
+                       return -1;
+               }
+
+               smbc_compat_initialized = 1;
+
+               return 0;
+       }
+       return 0;
+}
+
+
+int smbc_open(const char *furl, int flags, mode_t mode)
+{
+       SMBCFILE * file;
+       int fd;
+
+       file = statcont->open(statcont, furl, flags, mode);
+       if (!file)
+               return -1;
+
+       fd = add_fd(file);
+       if (fd == -1) 
+               statcont->close(statcont, file);
+       return fd;
+}
+
+
+int smbc_creat(const char *furl, mode_t mode)
+{
+       SMBCFILE * file;
+       int fd;
+
+       file = statcont->creat(statcont, furl, mode);
+       if (!file)
+               return -1;
+
+       fd = add_fd(file);
+       if (fd == -1) {
+               /* Hmm... should we delete the file too ? I guess we could try */
+               statcont->close(statcont, file);
+               statcont->unlink(statcont, furl);
+       }
+       return fd;
+}
+
+
+ssize_t smbc_read(int fd, void *buf, size_t bufsize)
+{
+       SMBCFILE * file = find_fd(fd);
+       return statcont->read(statcont, file, buf, bufsize);
+}
+
+ssize_t smbc_write(int fd, void *buf, size_t bufsize)
+{
+       SMBCFILE * file = find_fd(fd);
+       return statcont->write(statcont, file, buf, bufsize);
+}
+
+off_t smbc_lseek(int fd, off_t offset, int whence)
+{
+       SMBCFILE * file = find_fd(fd);
+       return statcont->lseek(statcont, file, offset, whence);
+}
+
+int smbc_close(int fd)
+{
+       SMBCFILE * file = find_fd(fd);
+       del_fd(fd);
+       return statcont->close(statcont, file);
+}
+
+int smbc_unlink(const char *fname)
+{
+        return statcont->unlink(statcont, fname);
+}
+
+int smbc_rename(const char *ourl, const char *nurl)
+{
+       return statcont->rename(statcont, ourl, statcont, nurl);
+}
+
+int smbc_opendir(const char *durl)
+{
+       SMBCFILE * file;
+       int fd;
+
+       file = statcont->opendir(statcont, durl);
+       if (!file)
+               return -1;
+
+       fd = add_fd(file);
+       if (fd == -1) 
+               statcont->closedir(statcont, file);
+
+       return fd;
+}
+
+int smbc_closedir(int dh) 
+{
+       SMBCFILE * file = find_fd(dh);
+       del_fd(dh);
+       return statcont->closedir(statcont, file);
+}
+
+int smbc_getdents(unsigned int dh, struct smbc_dirent *dirp, int count)
+{
+       SMBCFILE * file = find_fd(dh);
+       return statcont->getdents(statcont, file,dirp, count);
+}
+
+struct smbc_dirent* smbc_readdir(unsigned int dh)
+{
+       SMBCFILE * file = find_fd(dh);
+       return statcont->readdir(statcont, file);
+}
+
+off_t smbc_telldir(int dh)
+{
+       SMBCFILE * file = find_fd(dh);
+       return statcont->telldir(statcont, file);
+}
+
+int smbc_lseekdir(int fd, off_t offset)
+{
+       SMBCFILE * file = find_fd(fd);
+       return statcont->lseekdir(statcont, file, offset);
+}
+
+int smbc_mkdir(const char *durl, mode_t mode)
+{
+       return statcont->mkdir(statcont, durl, mode);
+}
+
+int smbc_rmdir(const char *durl)
+{
+       return statcont->rmdir(statcont, durl);
+}
+
+int smbc_stat(const char *url, struct stat *st)
+{
+       return statcont->stat(statcont, url, st);
+}
+
+int smbc_fstat(int fd, struct stat *st)
+{
+       SMBCFILE * file = find_fd(fd);
+       return statcont->fstat(statcont, file, st);
+}
+
+int smbc_chmod(const char *url, mode_t mode)
+{
+       /* NOT IMPLEMENTED IN LIBSMBCLIENT YET */
+       return -1;
+}
+
+int smbc_print_file(const char *fname, const char *printq)
+{
+       return statcont->print_file(statcont, fname, statcont, printq);
+}
+
+int smbc_open_print_job(const char *fname)
+{
+       SMBCFILE * file = statcont->open_print_job(statcont, fname);
+       if (!file) return -1;
+       return (int) file;
+}
+
+int smbc_list_print_jobs(const char *purl, smbc_get_print_job_info fn)
+{
+       return statcont->list_print_jobs(statcont, purl, fn);
+}
+
+int smbc_unlink_print_job(const char *purl, int id)
+{
+       return statcont->unlink_print_job(statcont, purl, id);
+}
+
+
diff --git a/source3/nsswitch/winbindd_dual.c b/source3/nsswitch/winbindd_dual.c
new file mode 100644 (file)
index 0000000..d32d62e
--- /dev/null
@@ -0,0 +1,209 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   Winbind background daemon
+
+   Copyright (C) Andrew Tridgell 2002
+   
+   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.
+*/
+
+/*
+  the idea of the optional dual daemon mode is ot prevent slow domain
+  responses from clagging up the rest of the system. When in dual
+  daemon mode winbindd always responds to requests from cache if the
+  request is in cache, and if the cached answer is stale then it asks
+  the "dual daemon" to update the cache for that request
+
+ */
+
+#include "winbindd.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
+extern BOOL opt_dual_daemon;
+BOOL backgroud_process = False;
+int dual_daemon_pipe = -1;
+
+
+/* a list of requests ready to be sent to the dual daemon */
+struct dual_list {
+       struct dual_list *next;
+       char *data;
+       int length;
+       int offset;
+};
+
+static struct dual_list *dual_list;
+static struct dual_list *dual_list_end;
+
+/*
+  setup a select() including the dual daemon pipe
+ */
+int dual_select_setup(fd_set *fds, int maxfd)
+{
+       if (dual_daemon_pipe == -1 ||
+           !dual_list) {
+               return maxfd;
+       }
+
+       FD_SET(dual_daemon_pipe, fds);
+       if (dual_daemon_pipe > maxfd) {
+               maxfd = dual_daemon_pipe;
+       }
+       return maxfd;
+}
+
+
+/*
+  a hook called from the main winbindd select() loop to handle writes
+  to the dual daemon pipe 
+*/
+void dual_select(fd_set *fds)
+{
+       int n;
+
+       if (dual_daemon_pipe == -1 ||
+           !dual_list ||
+           !FD_ISSET(dual_daemon_pipe, fds)) {
+               return;
+       }
+
+       n = write(dual_daemon_pipe, 
+                 &dual_list->data[dual_list->offset],
+                 dual_list->length - dual_list->offset);
+
+       if (n <= 0) {
+               /* the pipe is dead! fall back to normal operation */
+               dual_daemon_pipe = -1;
+               return;
+       }
+
+       dual_list->offset += n;
+
+       if (dual_list->offset == dual_list->length) {
+               struct dual_list *next;
+               next = dual_list->next;
+               free(dual_list->data);
+               free(dual_list);
+               dual_list = next;
+               if (!dual_list) {
+                       dual_list_end = NULL;
+               }
+       }
+}
+
+/* 
+   send a request to the background daemon 
+   this is called for stale cached entries
+*/
+void dual_send_request(struct winbindd_cli_state *state)
+{
+       struct dual_list *list;
+
+       if (!backgroud_process) return;
+
+       list = malloc(sizeof(*list));
+       if (!list) return;
+
+       list->next = NULL;
+       list->data = memdup(&state->request, sizeof(state->request));
+       list->length = sizeof(state->request);
+       list->offset = 0;
+       
+       if (!dual_list_end) {
+               dual_list = list;
+               dual_list_end = list;
+       } else {
+               dual_list_end->next = list;
+               dual_list_end = list;
+       }
+
+       backgroud_process = False;
+}
+
+
+/* 
+the main dual daemon 
+*/
+void do_dual_daemon(void)
+{
+       int fdpair[2];
+       struct winbindd_cli_state state;
+
+       if (pipe(fdpair) != 0) {
+               return;
+       }
+
+       ZERO_STRUCT(state);
+       state.pid = getpid();
+
+       dual_daemon_pipe = fdpair[1];
+       state.sock = fdpair[0];
+
+       if (fork() != 0) {
+               close(fdpair[0]);
+               return;
+       }
+       close(fdpair[1]);
+
+       if (winbind_setup_common() != 0) _exit(0);
+
+       dual_daemon_pipe = -1;
+       opt_dual_daemon = False;
+
+       while (1) {
+               /* free up any talloc memory */
+               lp_talloc_free();
+               main_loop_talloc_free();
+
+               /* fetch a request from the main daemon */
+               winbind_client_read(&state);
+
+               if (state.finished) {
+                       /* we lost contact with our parent */
+                       exit(0);
+               }
+
+               /* process full rquests */
+               if (state.read_buf_len == sizeof(state.request)) {
+                       DEBUG(4,("dual daemon request %d\n", (int)state.request.cmd));
+
+                       /* special handling for the stateful requests */
+                       switch (state.request.cmd) {
+                       case WINBINDD_GETPWENT:
+                               winbindd_setpwent(&state);
+                               break;
+                               
+                       case WINBINDD_GETGRENT:
+                       case WINBINDD_GETGRLST:
+                               winbindd_setgrent(&state);
+                               break;
+                       default:
+                               break;
+                       }
+
+                       winbind_process_packet(&state);
+                       SAFE_FREE(state.response.extra_data);
+
+                       free_getent_state(state.getpwent_state);
+                       free_getent_state(state.getgrent_state);
+                       state.getpwent_state = NULL;
+                       state.getgrent_state = NULL;
+               }
+       }
+}
+
diff --git a/source3/pam_smbpass/INSTALL b/source3/pam_smbpass/INSTALL
new file mode 100644 (file)
index 0000000..ae2ba02
--- /dev/null
@@ -0,0 +1,64 @@
+
+Because pam_smbpass is derived from the Samba smbpasswd utility, recent
+versions of pam_smbpass require a copy of the Samba source code to be
+available on the build system.  Version 0.7.5 has been tested against
+Samba 2.2.0-alpha3, and this is the recommended version of Samba to use
+for building pam_smbpass.  This only affects /building/ pam_smbpass; you
+can still run any version of the Samba server that you want, although
+clearly it saves some disk space to have only one copy of the source
+code on your system (Samba 2.2.0-alpha3 takes roughly 32MB of disk space
+to build pam_smbpass).
+
+Version 0.7.5 features a new build system to make it easier to build
+pam_smbpass.
+
+
+Using the new build system
+==========================
+
+If you don't have a copy of the Samba source code on your machine, and you
+don't have a preferred Samba version (or mirror site), you can build
+pam_smbpass by just typing 'make'.
+
+If you want to use a version other than 2.2.0-alpha3, or you want to
+download the source code from a faster Samba mirror (see
+<http://us1.samba.org/samba/> for a list of mirror sites), please download
+the source code and unpack it before running make.  The build scripts will
+attempt to autodetect your Samba source directory, and if it can't be
+found automatically, you will be given the opportunity to specify an
+alternate directory for the Samba sources.
+
+Feedback is welcome if you try (or succeed!) to build pam_smbpass with
+other versions of Samba.
+
+
+Options to 'make'
+=================
+
+By default, pam_smbpass will configure the Samba build tree with the
+options
+
+    --with-fhs --with-privatedir=/etc --with-configdir=/etc
+
+This will configure pam_smbpass to look for the smbpasswd file as
+/etc/smbpasswd (or /etc/smbpasswd.tdb), and the smb.conf file as
+/etc/smb.conf.  You can override these options by setting CONFIGOPTS when
+calling make.  E.g., if you have your smb.conf file in /usr/etc and your
+smbpasswd file in /usr/etc/private, you might run
+
+    make CONFIGOPTS="--with-privatedir=/usr/etc/private --with-configdir=/usr/etc"
+
+For a complete list of available configuration options, see
+'./samba/configure --help'
+
+
+Installing the module
+=====================
+
+If all goes well in the build process, the file pam_smbpass.so will be
+created in the current directory.  Simply install the module into your
+system's PAM module directory:
+
+       install -m 755 -s bin/pam_smbpass.so /lib/security
+
+and you're all set.
diff --git a/source3/passdb/pdb_compat.c b/source3/passdb/pdb_compat.c
new file mode 100644 (file)
index 0000000..713c92e
--- /dev/null
@@ -0,0 +1,104 @@
+/* 
+   Unix SMB/CIFS implementation.
+   SAM_ACCOUNT access routines
+   Copyright (C) Jeremy Allison                1996-2001
+   Copyright (C) Luke Kenneth Casson Leighton  1996-1998
+   Copyright (C) Gerald (Jerry) Carter         2000-2001
+   Copyright (C) Andrew Bartlett               2001-2002
+   Copyright (C) Stefan (metze) Metzmacher     2002
+      
+   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"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_PASSDB
+
+uint32 pdb_get_user_rid (const SAM_ACCOUNT *sampass)
+{
+       uint32 u_rid;
+
+       if (sampass)
+               if (sid_peek_check_rid(get_global_sam_sid(), pdb_get_user_sid(sampass),&u_rid))
+                       return u_rid;
+       
+       return (0);
+}
+
+uint32 pdb_get_group_rid (const SAM_ACCOUNT *sampass)
+{
+       uint32 g_rid;
+
+       if (sampass)
+               if (sid_peek_check_rid(get_global_sam_sid(), pdb_get_group_sid(sampass),&g_rid))
+                       return g_rid;
+       return (0);
+}
+
+BOOL pdb_set_user_sid_from_rid (SAM_ACCOUNT *sampass, uint32 rid)
+{
+       DOM_SID u_sid;
+       const DOM_SID *global_sam_sid;
+       
+       if (!sampass)
+               return False;
+
+       if (!(global_sam_sid = get_global_sam_sid())) {
+               DEBUG(1, ("pdb_set_user_sid_from_rid: Could not read global sam sid!\n"));
+               return False;
+       }
+
+       sid_copy(&u_sid, global_sam_sid);
+
+       if (!sid_append_rid(&u_sid, rid))
+               return False;
+
+       if (!pdb_set_user_sid(sampass, &u_sid))
+               return False;
+
+       DEBUG(10, ("pdb_set_user_sid_from_rid:\n\tsetting user sid %s from rid %d\n", 
+                   sid_string_static(&u_sid),rid));
+
+       return True;
+}
+
+BOOL pdb_set_group_sid_from_rid (SAM_ACCOUNT *sampass, uint32 grid)
+{
+       DOM_SID g_sid;
+       const DOM_SID *global_sam_sid;
+
+       if (!sampass)
+               return False;
+       
+       if (!(global_sam_sid = get_global_sam_sid())) {
+               DEBUG(1, ("pdb_set_user_sid_from_rid: Could not read global sam sid!\n"));
+               return False;
+       }
+
+       sid_copy(&g_sid, global_sam_sid);
+       
+       if (!sid_append_rid(&g_sid, grid))
+               return False;
+
+       if (!pdb_set_group_sid(sampass, &g_sid))
+               return False;
+
+       DEBUG(10, ("pdb_set_group_sid_from_rid:\n\tsetting group sid %s from rid %d\n", 
+                   sid_string_static(&g_sid), grid));
+
+       return True;
+}
+
diff --git a/source3/passdb/pdb_unix.c b/source3/passdb/pdb_unix.c
new file mode 100644 (file)
index 0000000..b4092b8
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Unix password backend for samba
+ * Copyright (C) Jelmer Vernooij 2002
+ * 
+ * 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"
+
+/******************************************************************
+  Lookup a name in the SAM database
+ ******************************************************************/
+
+static BOOL unixsam_getsampwnam (struct pdb_methods *methods, SAM_ACCOUNT *user, const char *sname)
+{
+       struct passwd *pass;
+       if (!methods) {
+               DEBUG(0,("invalid methods\n"));
+               return False;
+       }
+       if (!sname) {
+               DEBUG(0,("invalid name specified"));
+               return False;
+       }
+       pass = Get_Pwnam(sname);
+
+       return NT_STATUS_IS_OK(pdb_fill_sam_pw(user, pass));
+}
+
+
+/***************************************************************************
+  Search by rid
+ **************************************************************************/
+
+static BOOL unixsam_getsampwrid (struct pdb_methods *methods, 
+                                SAM_ACCOUNT *user, uint32 rid)
+{
+       struct passwd *pass;
+       BOOL ret = False;
+       if (!methods) {
+               DEBUG(0,("invalid methods\n"));
+               return False;
+       }
+
+       if (pdb_rid_is_user(rid)) {
+               pass = getpwuid_alloc(fallback_pdb_user_rid_to_uid (rid));
+               
+               if (pass) {
+                       ret = NT_STATUS_IS_OK(pdb_fill_sam_pw(user, pass));
+                       passwd_free(&pass);
+               }
+       }
+       return ret;
+}
+
+static BOOL unixsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, DOM_SID *sid)
+{
+       uint32 rid;
+       if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
+               return False;
+       return unixsam_getsampwrid(my_methods, user, rid);
+}
+
+/***************************************************************************
+  Adds an existing SAM_ACCOUNT
+ ****************************************************************************/
+
+static BOOL unixsam_add_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd)
+{
+       DEBUG(0,("pdb_unix should not be listed as the first passdb backend! You can't add users to it.\n"));
+       return False;
+}
+
+/***************************************************************************
+  Updates a SAM_ACCOUNT
+
+  This isn't a particulary practical option for pdb_unix.  We certainly don't
+  want to twidde the filesystem, so what should we do?
+
+  Current plan is to transparently add the account.  It should appear
+  as if the pdb_unix version was modified, but its actually stored somehwere.
+ ****************************************************************************/
+
+static BOOL unixsam_update_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd)
+{
+       return methods->parent->pdb_add_sam_account(methods->parent, newpwd);
+}
+
+NTSTATUS pdb_init_unixsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+{
+       NTSTATUS nt_status;
+       
+       if (!pdb_context) {
+               DEBUG(0, ("invalid pdb_context specified\n"));
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
+               return nt_status;
+       }
+       
+       (*pdb_method)->name = "unixsam";
+       
+       (*pdb_method)->setsampwent = NULL;
+       (*pdb_method)->endsampwent = NULL;
+       (*pdb_method)->getsampwent = NULL;
+       (*pdb_method)->getsampwnam = unixsam_getsampwnam;
+       (*pdb_method)->getsampwsid = unixsam_getsampwsid;
+       (*pdb_method)->add_sam_account = unixsam_add_sam_account;
+       (*pdb_method)->update_sam_account = unixsam_update_sam_account;
+       (*pdb_method)->delete_sam_account = NULL;
+       
+       /* There's not very much to initialise here */
+       return NT_STATUS_OK;
+}
diff --git a/source3/passdb/util_sam_sid.c b/source3/passdb/util_sam_sid.c
new file mode 100644 (file)
index 0000000..2c574f4
--- /dev/null
@@ -0,0 +1,275 @@
+/* 
+   Unix SMB/CIFS implementation.
+   Samba utility functions
+   Copyright (C) Andrew Tridgell 1992-1998
+   Copyright (C) Luke Kenneth Caseson Leighton 1998-1999
+   Copyright (C) Jeremy Allison  1999
+   
+   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"
+
+extern pstring global_myname;
+extern fstring global_myworkgroup;
+
+#define MAX_SID_NAMES  7
+
+typedef struct _known_sid_users {
+       uint32 rid;
+       enum SID_NAME_USE sid_name_use;
+       char *known_user_name;
+} known_sid_users;
+
+static struct sid_name_map_info
+{
+       DOM_SID *sid;
+       char *name;
+       known_sid_users *known_users;
+} sid_name_map[MAX_SID_NAMES];
+
+extern DOM_SID global_sid_Builtin;                             /* Local well-known domain */
+extern DOM_SID global_sid_World_Domain;                /* Everyone domain */
+extern DOM_SID global_sid_Creator_Owner_Domain;    /* Creator Owner domain */
+extern DOM_SID global_sid_NT_Authority;                /* NT Authority */
+
+
+static BOOL sid_name_map_initialized = False;
+/* static known_sid_users no_users[] = {{0, 0, NULL}}; */
+
+static known_sid_users everyone_users[] = {
+       { 0, SID_NAME_WKN_GRP, "Everyone" },
+       {0, (enum SID_NAME_USE)0, NULL}};
+
+static known_sid_users creator_owner_users[] = {
+       { 0, SID_NAME_ALIAS, "Creator Owner" },
+       {0, (enum SID_NAME_USE)0, NULL}};
+
+static known_sid_users nt_authority_users[] = {
+       {  1, SID_NAME_ALIAS, "Dialup" },
+       {  2, SID_NAME_ALIAS, "Network"},
+       {  3, SID_NAME_ALIAS, "Batch"},
+       {  4, SID_NAME_ALIAS, "Interactive"},
+       {  6, SID_NAME_ALIAS, "Service"},
+       {  7, SID_NAME_ALIAS, "AnonymousLogon"},
+       {  8, SID_NAME_ALIAS, "Proxy"},
+       {  9, SID_NAME_ALIAS, "ServerLogon"},
+       { 11, SID_NAME_ALIAS, "Authenticated Users"},
+       { 18, SID_NAME_ALIAS, "SYSTEM"},
+       {  0, (enum SID_NAME_USE)0, NULL}};
+
+static known_sid_users builtin_groups[] = {
+       { BUILTIN_ALIAS_RID_ADMINS, SID_NAME_ALIAS, "Administrators" },
+       { BUILTIN_ALIAS_RID_USERS, SID_NAME_ALIAS, "Users" },
+       { BUILTIN_ALIAS_RID_GUESTS, SID_NAME_ALIAS, "Guests" },
+       { BUILTIN_ALIAS_RID_ACCOUNT_OPS, SID_NAME_ALIAS, "Account Operators" },
+       { BUILTIN_ALIAS_RID_SYSTEM_OPS, SID_NAME_ALIAS, "Server Operators" },
+       { BUILTIN_ALIAS_RID_PRINT_OPS, SID_NAME_ALIAS, "Print Operators" },
+       { BUILTIN_ALIAS_RID_BACKUP_OPS, SID_NAME_ALIAS, "Backup Operators" },
+       {  0, (enum SID_NAME_USE)0, NULL}};
+
+
+
+/**************************************************************************
+ quick init function
+ *************************************************************************/
+static void init_sid_name_map (void)
+{
+       int i = 0;
+       
+       if (sid_name_map_initialized) return;
+
+       generate_wellknown_sids();
+
+       if ((lp_security() == SEC_USER) && lp_domain_logons()) {
+               sid_name_map[i].sid = get_global_sam_sid();
+               sid_name_map[i].name = global_myworkgroup;
+               sid_name_map[i].known_users = NULL;
+               i++;
+               sid_name_map[i].sid = get_global_sam_sid();
+               sid_name_map[i].name = global_myname;
+               sid_name_map[i].known_users = NULL;
+               i++;
+       }
+       else {
+               sid_name_map[i].sid = get_global_sam_sid();
+               sid_name_map[i].name = global_myname;
+               sid_name_map[i].known_users = NULL;
+               i++;
+       }
+
+       sid_name_map[i].sid = &global_sid_Builtin;
+       sid_name_map[i].name = "BUILTIN";
+       sid_name_map[i].known_users = &builtin_groups[0];
+       i++;
+       
+       sid_name_map[i].sid = &global_sid_World_Domain;
+       sid_name_map[i].name = "";
+       sid_name_map[i].known_users = &everyone_users[0];
+       i++;
+
+       sid_name_map[i].sid = &global_sid_Creator_Owner_Domain;
+       sid_name_map[i].name = "";
+       sid_name_map[i].known_users = &creator_owner_users[0];
+       i++;
+               
+       sid_name_map[i].sid = &global_sid_NT_Authority;
+       sid_name_map[i].name = "NT Authority";
+       sid_name_map[i].known_users = &nt_authority_users[0];
+       i++;
+               
+
+       /* end of array */
+       sid_name_map[i].sid = NULL;
+       sid_name_map[i].name = NULL;
+       sid_name_map[i].known_users = NULL;
+       
+       sid_name_map_initialized = True;
+               
+       return;
+
+}
+
+/**************************************************************************
+ Turns a domain SID into a name, returned in the nt_domain argument.
+***************************************************************************/
+
+BOOL map_domain_sid_to_name(DOM_SID *sid, fstring nt_domain)
+{
+       fstring sid_str;
+       int i = 0;
+       
+       sid_to_string(sid_str, sid);
+
+       if (!sid_name_map_initialized) 
+               init_sid_name_map();
+
+       DEBUG(5,("map_domain_sid_to_name: %s\n", sid_str));
+
+       if (nt_domain == NULL)
+               return False;
+
+       while (sid_name_map[i].sid != NULL) {
+               sid_to_string(sid_str, sid_name_map[i].sid);
+               DEBUG(5,("map_domain_sid_to_name: compare: %s\n", sid_str));
+               if (sid_equal(sid_name_map[i].sid, sid)) {              
+                       fstrcpy(nt_domain, sid_name_map[i].name);
+                       DEBUG(5,("map_domain_sid_to_name: found '%s'\n", nt_domain));
+                       return True;
+               }
+               i++;
+       }
+
+       DEBUG(5,("map_domain_sid_to_name: mapping for %s not found\n", sid_str));
+
+    return False;
+}
+
+/**************************************************************************
+ Looks up a known username from one of the known domains.
+***************************************************************************/
+
+BOOL lookup_known_rid(DOM_SID *sid, uint32 rid, char *name, enum SID_NAME_USE *psid_name_use)
+{
+       int i = 0;
+       struct sid_name_map_info *psnm;
+
+       if (!sid_name_map_initialized) 
+               init_sid_name_map();
+
+       for(i = 0; sid_name_map[i].sid != NULL; i++) {
+               psnm = &sid_name_map[i];
+               if(sid_equal(psnm->sid, sid)) {
+                       int j;
+                       for(j = 0; psnm->known_users && psnm->known_users[j].known_user_name != NULL; j++) {
+                               if(rid == psnm->known_users[j].rid) {
+                                       DEBUG(5,("lookup_builtin_rid: rid = %u, domain = '%s', user = '%s'\n",
+                                               (unsigned int)rid, psnm->name, psnm->known_users[j].known_user_name ));
+                                       fstrcpy( name, psnm->known_users[j].known_user_name);
+                                       *psid_name_use = psnm->known_users[j].sid_name_use;
+                                       return True;
+                               }
+                       }
+               }
+       }
+
+       return False;
+}
+
+/**************************************************************************
+ Turns a domain name into a SID.
+ *** side-effect: if the domain name is NULL, it is set to our domain ***
+***************************************************************************/
+
+BOOL map_domain_name_to_sid(DOM_SID *sid, char *nt_domain)
+{
+       int i = 0;
+
+       if (nt_domain == NULL) {
+               DEBUG(5,("map_domain_name_to_sid: mapping NULL domain to our SID.\n"));
+               sid_copy(sid, get_global_sam_sid());
+               return True;
+       }
+
+       if (nt_domain[0] == 0) {
+               fstrcpy(nt_domain, global_myname);
+               DEBUG(5,("map_domain_name_to_sid: overriding blank name to %s\n", nt_domain));
+               sid_copy(sid, get_global_sam_sid());
+               return True;
+       }
+
+       DEBUG(5,("map_domain_name_to_sid: %s\n", nt_domain));
+
+       if (!sid_name_map_initialized) 
+               init_sid_name_map();
+
+       while (sid_name_map[i].name != NULL) {
+               DEBUG(5,("map_domain_name_to_sid: compare: %s\n", sid_name_map[i].name));
+               if (strequal(sid_name_map[i].name, nt_domain)) {
+                       fstring sid_str;
+                       sid_copy(sid, sid_name_map[i].sid);
+                       sid_to_string(sid_str, sid_name_map[i].sid);
+                       DEBUG(5,("map_domain_name_to_sid: found %s\n", sid_str));
+                       return True;
+               }
+               i++;
+       }
+
+       DEBUG(0,("map_domain_name_to_sid: mapping to %s not found.\n", nt_domain));
+       return False;
+}
+
+/*****************************************************************
+ Check if the SID is our domain SID (S-1-5-21-x-y-z).
+*****************************************************************/  
+BOOL sid_check_is_domain(const DOM_SID *sid)
+{
+       return sid_equal(sid, get_global_sam_sid());
+}
+
+/*****************************************************************
+ Check if the SID is our domain SID (S-1-5-21-x-y-z).
+*****************************************************************/  
+BOOL sid_check_is_in_our_domain(const DOM_SID *sid)
+{
+       DOM_SID dom_sid;
+       uint32 rid;
+
+       sid_copy(&dom_sid, sid);
+       sid_split_rid(&dom_sid, &rid);
+       
+       return sid_equal(&dom_sid, get_global_sam_sid());
+}
+
diff --git a/source3/printing/notify.c b/source3/printing/notify.c
new file mode 100644 (file)
index 0000000..21e28d0
--- /dev/null
@@ -0,0 +1,230 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 2.2
+   printing backend routines
+   Copyright (C) Tim Potter, 2002
+   
+   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 "printing.h"
+
+/*
+ * Print notification routines
+ */
+
+static void send_spoolss_notify2_msg(struct spoolss_notify_msg *msg)
+{
+       char *buf = NULL;
+       int buflen = 0, len;
+       TDB_CONTEXT *tdb;
+
+       /* Let's not waste any time with this */
+
+       if (lp_disable_spoolss())
+               return;
+
+       /* Flatten data into a message */
+
+again:
+       len = 0;
+
+       /* Pack header */
+
+       len += tdb_pack(buf + len, buflen - len, "f", msg->printer);
+
+       len += tdb_pack(buf + len, buflen - len, "ddddd",
+                       msg->type, msg->field, msg->id, msg->len, msg->flags);
+
+       /* Pack data */
+
+       if (msg->len == 0)
+               len += tdb_pack(buf + len, buflen - len, "dd",
+                               msg->notify.value[0], msg->notify.value[1]);
+       else
+               len += tdb_pack(buf + len, buflen - len, "B",
+                               msg->len, msg->notify.data);
+
+       if (buflen != len) {
+               buf = Realloc(buf, len);
+               buflen = len;
+               goto again;
+       }
+
+       /* Send message */
+
+       tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0);
+
+       if (!tdb) {
+               DEBUG(3, ("Failed to open connections database in send_spoolss_notify2_msg\n"));
+               return;
+       }
+
+       message_send_all(tdb, MSG_PRINTER_NOTIFY2, buf,
+                        buflen, False, NULL);
+
+       SAFE_FREE(buf);
+       tdb_close(tdb);
+}
+
+static void send_notify_field_values(const char *printer_name, uint32 type,
+                                    uint32 field, uint32 id, uint32 value1, 
+                                    uint32 value2, uint32 flags)
+{
+       struct spoolss_notify_msg msg;
+
+       ZERO_STRUCT(msg);
+
+       fstrcpy(msg.printer, printer_name);
+       msg.type = type;
+       msg.field = field;
+       msg.id = id;
+       msg.notify.value[0] = value1;
+       msg.notify.value[1] = value2;
+       msg.flags = flags;
+
+       send_spoolss_notify2_msg(&msg);
+}
+
+static void send_notify_field_buffer(const char *printer_name, uint32 type,
+                                    uint32 field, uint32 id, uint32 len,
+                                    char *buffer)
+{
+       struct spoolss_notify_msg msg;
+
+       ZERO_STRUCT(msg);
+
+       fstrcpy(msg.printer, printer_name);
+       msg.type = type;
+       msg.field = field;
+       msg.id = id;
+       msg.len = len;
+       msg.notify.data = buffer;
+
+       send_spoolss_notify2_msg(&msg);
+}
+
+/* Send a message that the printer status has changed */
+
+void notify_printer_status_byname(const char *printer_name, uint32 status)
+{
+       /* Printer status stored in value1 */
+
+       send_notify_field_values(printer_name, PRINTER_NOTIFY_TYPE, 
+                                PRINTER_NOTIFY_STATUS, 0, 
+                                status, 0, 0);
+}
+
+void notify_printer_status(int snum, uint32 status)
+{
+       const char *printer_name = PRINTERNAME(snum);
+
+       if (printer_name)
+               notify_printer_status_byname(printer_name, status);
+}
+
+void notify_job_status_byname(const char *printer_name, uint32 jobid, uint32 status,
+                             uint32 flags)
+{
+       /* Job id stored in id field, status in value1 */
+
+       send_notify_field_values(printer_name, JOB_NOTIFY_TYPE,
+                                JOB_NOTIFY_STATUS, jobid,
+                                status, 0, flags);
+}
+
+void notify_job_status(int snum, uint32 jobid, uint32 status)
+{
+       const char *printer_name = PRINTERNAME(snum);
+
+       notify_job_status_byname(printer_name, jobid, status, 0);
+}
+
+void notify_job_total_bytes(int snum, uint32 jobid, uint32 size)
+{
+       const char *printer_name = PRINTERNAME(snum);
+
+       /* Job id stored in id field, status in value1 */
+
+       send_notify_field_values(printer_name, JOB_NOTIFY_TYPE,
+                                JOB_NOTIFY_TOTAL_BYTES, jobid,
+                                size, 0, 0);
+}
+
+void notify_job_total_pages(int snum, uint32 jobid, uint32 pages)
+{
+       const char *printer_name = PRINTERNAME(snum);
+
+       /* Job id stored in id field, status in value1 */
+
+       send_notify_field_values(printer_name, JOB_NOTIFY_TYPE,
+                                JOB_NOTIFY_TOTAL_PAGES, jobid,
+                                pages, 0, 0);
+}
+
+void notify_job_username(int snum, uint32 jobid, char *name)
+{
+       const char *printer_name = PRINTERNAME(snum);
+
+       send_notify_field_buffer(
+               printer_name, JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME,
+               jobid, strlen(name) + 1, name);
+}
+
+void notify_job_name(int snum, uint32 jobid, char *name)
+{
+       const char *printer_name = PRINTERNAME(snum);
+
+       send_notify_field_buffer(
+               printer_name, JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT,
+               jobid, strlen(name) + 1, name);
+}
+
+void notify_job_submitted(int snum, uint32 jobid, time_t submitted)
+{
+       const char *printer_name = PRINTERNAME(snum);
+
+       send_notify_field_buffer(
+               printer_name, JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED,
+               jobid, sizeof(submitted), (char *)&submitted);
+}
+
+void notify_printer_delete(char *printer_name)
+{
+}
+
+void notify_printer_add(char *printer_name)
+{
+}
+
+void notify_printer_driver(int num, char *driver_name)
+{
+}
+
+void notify_printer_comment(int num, char *comment)
+{
+}
+
+void notify_printer_sharename(int num, char *share_name)
+{
+}
+
+void notify_printer_port(int num, char *port_name)
+{
+}
+
+void notify_printer_location(int num, char *location)
+{
+}
diff --git a/source3/python/py_common.h b/source3/python/py_common.h
new file mode 100644 (file)
index 0000000..1f51889
--- /dev/null
@@ -0,0 +1,35 @@
+/* 
+   Python wrappers for DCERPC/SMB client routines.
+
+   Copyright (C) Tim Potter, 2002
+   
+   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.
+*/
+
+#ifndef _PY_COMMON_H
+#define _PY_COMMON_H
+
+#include "includes.h"
+
+/* Return a cli_state struct opened on the specified pipe.  If credentials
+   are passed use them. */
+
+typedef struct cli_state *(cli_pipe_fn)(
+       struct cli_state *cli, char *system_name,
+       struct ntuser_creds *creds);
+
+#include "python/py_common_proto.h"
+
+#endif /* _PY_COMMON_H */
diff --git a/source3/python/py_lsa.h b/source3/python/py_lsa.h
new file mode 100644 (file)
index 0000000..f9a30d2
--- /dev/null
@@ -0,0 +1,46 @@
+/* 
+   Python wrappers for DCERPC/SMB client routines.
+
+   Copyright (C) Tim Potter, 2002
+   
+   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.
+*/
+
+#ifndef _PY_LSA_H
+#define _PY_LSA_H
+
+#include "includes.h"
+#include "Python.h"
+
+#include "python/py_common_proto.h"
+
+/* LSA policy handle object */
+
+typedef struct {
+       PyObject_HEAD
+       struct cli_state *cli;
+       TALLOC_CTX *mem_ctx;
+       POLICY_HND pol;
+} lsa_policy_hnd_object;
+     
+/* Exceptions raised by this module */
+
+extern PyTypeObject lsa_policy_hnd_type;
+
+extern PyObject *lsa_error;
+
+#include "python/py_lsa_proto.h"
+
+#endif /* _PY_LSA_H */
diff --git a/source3/python/py_lsa_proto.h b/source3/python/py_lsa_proto.h
new file mode 100644 (file)
index 0000000..1c6f6ab
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _PY_LSA_PROTO_H
+#define _PY_LSA_PROTO_H
+
+/* This file is automatically generated with "make proto". DO NOT EDIT */
+
+
+/* The following definitions come from python/py_lsa.c  */
+
+PyObject *new_lsa_policy_hnd_object(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                                   POLICY_HND *pol);
+void initlsa(void);
+
+#endif /*  _PY_LSA_PROTO_H  */
diff --git a/source3/python/py_ntsec.c b/source3/python/py_ntsec.c
new file mode 100644 (file)
index 0000000..f216d96
--- /dev/null
@@ -0,0 +1,284 @@
+/* 
+   Python wrappers for DCERPC/SMB client routines.
+
+   Copyright (C) Tim Potter, 2002
+   
+   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 "Python.h"
+
+#include "python/py_common_proto.h"
+
+/* Convert a SID to a Python dict */
+
+BOOL py_from_SID(PyObject **obj, DOM_SID *sid)
+{
+       fstring sidstr;
+
+       if (!sid) {
+               Py_INCREF(Py_None);
+               *obj = Py_None;
+               return True;
+       }
+
+       if (!sid_to_string(sidstr, sid))
+               return False;
+
+       *obj = PyString_FromString(sidstr);
+
+       return True;
+}
+
+BOOL py_to_SID(DOM_SID *sid, PyObject *obj)
+{
+       if (!PyString_Check(obj))
+               return False;
+
+       return string_to_sid(sid, PyString_AsString(obj));
+}
+
+BOOL py_from_ACE(PyObject **dict, SEC_ACE *ace)
+{
+       PyObject *obj;
+
+       if (!ace) {
+               Py_INCREF(Py_None);
+               *dict = Py_None;
+               return True;
+       }
+
+       *dict = PyDict_New();
+
+       PyDict_SetItemString(*dict, "type", PyInt_FromLong(ace->type));
+       PyDict_SetItemString(*dict, "flags", PyInt_FromLong(ace->flags));
+       PyDict_SetItemString(*dict, "mask", PyInt_FromLong(ace->info.mask));
+
+       if (py_from_SID(&obj, &ace->trustee))
+               PyDict_SetItemString(*dict, "trustee", obj);
+
+       return True;
+}
+
+BOOL py_to_ACE(SEC_ACE *ace, PyObject *dict)
+{
+       PyObject *obj;
+       uint8 ace_type, ace_flags;
+       DOM_SID trustee;
+       SEC_ACCESS sec_access;
+
+       if (!PyDict_Check(dict))
+               return False;
+
+       if (!(obj = PyDict_GetItemString(dict, "type")) ||
+           !PyInt_Check(obj))
+               return False;
+
+       ace_type = PyInt_AsLong(obj);
+
+       if (!(obj = PyDict_GetItemString(dict, "flags")) ||
+           !PyInt_Check(obj))
+               return False;
+
+       ace_flags = PyInt_AsLong(obj);
+
+       if (!(obj = PyDict_GetItemString(dict, "trustee")) ||
+           !PyString_Check(obj))
+               return False;
+
+       if (!py_to_SID(&trustee, obj))
+               return False;
+
+       if (!(obj = PyDict_GetItemString(dict, "mask")) ||
+           !PyInt_Check(obj))
+               return False;
+
+       sec_access.mask = PyInt_AsLong(obj);
+
+       init_sec_ace(ace, &trustee, ace_type, sec_access, ace_flags);
+
+       /* Fill in size field */
+
+       ace->size = SEC_ACE_HEADER_SIZE + sid_size(&trustee);
+
+       return True;
+}
+
+BOOL py_from_ACL(PyObject **dict, SEC_ACL *acl)
+{
+       PyObject *ace_list;
+       int i;
+
+       if (!acl) {
+               Py_INCREF(Py_None);
+               *dict = Py_None;
+               return True;
+       }
+
+       *dict = PyDict_New();
+
+       PyDict_SetItemString(*dict, "revision", PyInt_FromLong(acl->revision));
+
+       ace_list = PyList_New(acl->num_aces);
+
+       for (i = 0; i < acl->num_aces; i++) {
+               PyObject *obj;
+
+               if (py_from_ACE(&obj, &acl->ace[i]))
+                       PyList_SetItem(ace_list, i, obj);
+       }
+
+       PyDict_SetItemString(*dict, "ace_list", ace_list);
+
+       return True;
+}
+
+BOOL py_to_ACL(SEC_ACL *acl, PyObject *dict, TALLOC_CTX *mem_ctx)
+{
+       PyObject *obj;
+       uint32 i;
+
+       if (!(obj = PyDict_GetItemString(dict, "revision")) ||
+           !PyInt_Check(obj))
+               return False;
+
+       acl->revision = PyInt_AsLong(obj);
+
+       if (!(obj = PyDict_GetItemString(dict, "ace_list")) ||
+           !PyList_Check(obj)) 
+               return False;
+       
+       acl->num_aces = PyList_Size(obj);
+
+       acl->ace = talloc(mem_ctx, acl->num_aces * sizeof(SEC_ACE));
+       acl->size = SEC_ACL_HEADER_SIZE;
+
+       for (i = 0; i < acl->num_aces; i++) {
+               PyObject *py_ace = PyList_GetItem(obj, i);
+
+               if (!py_to_ACE(&acl->ace[i], py_ace))
+                       return False;
+
+               acl->size += acl->ace[i].size;
+       }
+
+       return True;
+}
+
+BOOL py_from_SECDESC(PyObject **dict, SEC_DESC *sd)
+{
+       PyObject *obj;
+
+       *dict = PyDict_New();
+
+       PyDict_SetItemString(*dict, "revision", PyInt_FromLong(sd->revision));
+
+       if (py_from_SID(&obj, sd->owner_sid))
+               PyDict_SetItemString(*dict, "owner_sid", obj);
+
+       if (py_from_SID(&obj, sd->grp_sid))
+               PyDict_SetItemString(*dict, "group_sid", obj);
+
+       if (py_from_ACL(&obj, sd->dacl))
+               PyDict_SetItemString(*dict, "dacl", obj);
+
+       if (py_from_ACL(&obj, sd->sacl))
+               PyDict_SetItemString(*dict, "sacl", obj);
+
+       return True;
+}
+
+BOOL py_to_SECDESC(SEC_DESC **sd, PyObject *dict, TALLOC_CTX *mem_ctx)
+{
+       PyObject *obj;
+       uint16 revision;
+       DOM_SID owner_sid, group_sid;
+       SEC_ACL sacl, dacl;
+       BOOL got_dacl = False, got_sacl = False;
+       BOOL got_owner_sid = False, got_group_sid = False;
+
+       ZERO_STRUCT(dacl); ZERO_STRUCT(sacl);
+       ZERO_STRUCT(owner_sid); ZERO_STRUCT(group_sid);
+
+       if (!(obj = PyDict_GetItemString(dict, "revision")))
+               return False;
+
+       revision = PyInt_AsLong(obj);
+
+       if ((obj = PyDict_GetItemString(dict, "owner_sid"))) {
+
+               if (obj != Py_None) {
+
+                       if (!py_to_SID(&owner_sid, obj))
+                               return False;
+
+                       got_owner_sid = True;
+               }
+       }
+
+       if ((obj = PyDict_GetItemString(dict, "group_sid"))) {
+
+               if (obj != Py_None) {
+
+                       if (!py_to_SID(&group_sid, obj))
+                               return False;
+                       
+                       got_group_sid = True;
+               }
+       }
+
+       if ((obj = PyDict_GetItemString(dict, "dacl"))) {
+
+               if (obj != Py_None) {
+
+                       if (!py_to_ACL(&dacl, obj, mem_ctx))
+                               return False;
+                       
+                       got_dacl = True;
+               }
+       }
+
+       if ((obj = PyDict_GetItemString(dict, "sacl"))) {
+
+               if (obj != Py_None) {
+
+                       if (!py_to_ACL(&sacl, obj, mem_ctx))
+                               return False;
+
+                       got_sacl = True;
+               }
+       }
+
+#if 0                          /* For new secdesc code */
+       *sd = make_sec_desc(mem_ctx, revision, 
+                           got_owner_sid ? &owner_sid : NULL, 
+                           got_group_sid ? &group_sid : NULL,
+                           got_sacl ? &sacl : NULL, 
+                           got_dacl ? &dacl : NULL);
+#else
+       {
+               size_t sd_size;
+
+               *sd = make_sec_desc(mem_ctx, revision,
+                           got_owner_sid ? &owner_sid : NULL, 
+                           got_group_sid ? &group_sid : NULL,
+                           got_sacl ? &sacl : NULL, 
+                           got_dacl ? &dacl : NULL, &sd_size);
+       }
+#endif
+
+       return True;
+}
diff --git a/source3/python/py_samr.h b/source3/python/py_samr.h
new file mode 100644 (file)
index 0000000..22c3660
--- /dev/null
@@ -0,0 +1,83 @@
+/* 
+   Python wrappers for DCERPC/SMB client routines.
+
+   Copyright (C) Tim Potter, 2002
+   
+   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.
+*/
+
+#ifndef _PY_SAMR_H
+#define _PY_SAMR_H
+
+#include "includes.h"
+#include "Python.h"
+
+#include "python/py_common_proto.h"
+
+/* SAMR connect policy handle object */
+
+typedef struct {
+       PyObject_HEAD
+       struct cli_state *cli;
+       TALLOC_CTX *mem_ctx;
+       POLICY_HND connect_pol;
+} samr_connect_hnd_object;
+     
+/* SAMR domain policy handle object */
+
+typedef struct {
+       PyObject_HEAD
+       struct cli_state *cli;
+       TALLOC_CTX *mem_ctx;
+       POLICY_HND domain_pol;
+} samr_domain_hnd_object;
+
+/* SAMR user policy handle object */
+
+typedef struct {
+       PyObject_HEAD
+       struct cli_state *cli;
+       TALLOC_CTX *mem_ctx;
+       POLICY_HND user_pol;
+} samr_user_hnd_object;
+
+/* SAMR group policy handle object */
+
+typedef struct {
+       PyObject_HEAD
+       struct cli_state *cli;
+       TALLOC_CTX *mem_ctx;
+       POLICY_HND group_pol;
+} samr_group_hnd_object;
+     
+/* SAMR alias policy handle object */
+
+typedef struct {
+       PyObject_HEAD
+       struct cli_state *cli;
+       TALLOC_CTX *mem_ctx;
+       POLICY_HND alias_pol;
+} samr_alias_hnd_object;
+     
+extern PyTypeObject samr_connect_hnd_type, samr_domain_hnd_type,
+       samr_user_hnd_type, samr_group_hnd_type, samr_alias_hnd_type; 
+
+/* Exceptions raised by this module */
+
+extern PyObject *samr_error;
+
+/* #include "python/py_samr_proto.h" */
+
+#endif /* _PY_SAMR_H */
diff --git a/source3/python/py_spoolss.h b/source3/python/py_spoolss.h
new file mode 100644 (file)
index 0000000..40a6ae9
--- /dev/null
@@ -0,0 +1,46 @@
+/* 
+   Python wrappers for DCERPC/SMB client routines.
+
+   Copyright (C) Tim Potter, 2002
+   
+   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.
+*/
+
+#ifndef _PY_SPOOLSS_H
+#define _PY_SPOOLSS_H
+
+#include "includes.h"
+#include "Python.h"
+
+#include "python/py_common_proto.h"
+
+/* Spoolss policy handle object */
+
+typedef struct {
+       PyObject_HEAD
+       struct cli_state *cli;
+       TALLOC_CTX *mem_ctx;
+       POLICY_HND pol;
+} spoolss_policy_hnd_object;
+     
+/* Exceptions raised by this module */
+
+extern PyTypeObject spoolss_policy_hnd_type;
+
+extern PyObject *spoolss_error, *spoolss_werror;
+
+#include "python/py_spoolss_proto.h"
+
+#endif /* _PY_SPOOLSS_H */
diff --git a/source3/python/py_spoolss_forms_conv.c b/source3/python/py_spoolss_forms_conv.c
new file mode 100644 (file)
index 0000000..6ef953c
--- /dev/null
@@ -0,0 +1,79 @@
+/* 
+   Python wrappers for DCERPC/SMB client routines.
+
+   Copyright (C) Tim Potter, 2002
+   
+   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 "python/py_spoolss.h"
+#include "python/py_conv.h"
+
+struct pyconv py_FORM[] = {
+       { "flags", PY_UINT32, offsetof(FORM, flags) },
+       { "width", PY_UINT32, offsetof(FORM, size_x) },
+       { "length", PY_UINT32, offsetof(FORM, size_y) },
+       { "top", PY_UINT32, offsetof(FORM, top) },
+       { "left", PY_UINT32, offsetof(FORM, left) },
+       { "right", PY_UINT32, offsetof(FORM, right) },
+       { "bottom", PY_UINT32, offsetof(FORM, bottom) },
+       { NULL }
+};
+
+struct pyconv py_FORM_1[] = {
+       { "flags", PY_UINT32, offsetof(FORM_1, flag) },
+       { "width", PY_UINT32, offsetof(FORM_1, width) },
+       { "length", PY_UINT32, offsetof(FORM_1, length) },
+       { "top", PY_UINT32, offsetof(FORM_1, top) },
+       { "left", PY_UINT32, offsetof(FORM_1, left) },
+       { "right", PY_UINT32, offsetof(FORM_1, right) },
+       { "bottom", PY_UINT32, offsetof(FORM_1, bottom) },
+       { "name", PY_UNISTR, offsetof(FORM_1, name) },
+       { NULL }
+};
+
+BOOL py_from_FORM_1(PyObject **dict, FORM_1 *form)
+{
+       *dict = from_struct(form, py_FORM_1);
+
+       PyDict_SetItemString(*dict, "level", PyInt_FromLong(1));
+
+       return True;
+}
+
+BOOL py_to_FORM(FORM *form, PyObject *dict)
+{
+       PyObject *obj, *dict_copy = PyDict_Copy(dict);
+       char *name;
+
+       obj = PyDict_GetItemString(dict, "name");
+
+       if (!obj || !PyString_Check(obj))
+               return False;
+
+       PyDict_DelItemString(dict_copy, "level");
+       PyDict_DelItemString(dict_copy, "name");
+
+       if (!to_struct(form, dict_copy, py_FORM)) {
+               Py_DECREF(dict_copy);
+               return False;
+       }
+
+       name = PyString_AsString(obj);
+
+       init_unistr2(&form->name, name, strlen(name) + 1);
+       
+       return True;
+}
diff --git a/source3/python/py_spoolss_jobs_conv.c b/source3/python/py_spoolss_jobs_conv.c
new file mode 100644 (file)
index 0000000..cb04ec6
--- /dev/null
@@ -0,0 +1,102 @@
+/* 
+   Python wrappers for DCERPC/SMB client routines.
+
+   Copyright (C) Tim Potter, 2002
+   
+   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 "python/py_spoolss.h"
+#include "python/py_conv.h"
+
+struct pyconv py_JOB_INFO_1[] = {
+       { "jobid", PY_UINT32, offsetof(JOB_INFO_1, jobid) },
+       { "printer_name", PY_UNISTR, offsetof(JOB_INFO_1, printername) },
+       { "server_name", PY_UNISTR, offsetof(JOB_INFO_1, machinename) },
+       { "user_name", PY_UNISTR, offsetof(JOB_INFO_1, username) },
+       { "document_name", PY_UNISTR, offsetof(JOB_INFO_1, document) },
+       { "data_type", PY_UNISTR, offsetof(JOB_INFO_1, datatype) },
+       { "text_status", PY_UNISTR, offsetof(JOB_INFO_1, text_status) },
+       { "status", PY_UINT32, offsetof(JOB_INFO_1, status) },
+       { "priority", PY_UINT32, offsetof(JOB_INFO_1, priority) },
+       { "position", PY_UINT32, offsetof(JOB_INFO_1, position) },
+       { "total_pages", PY_UINT32, offsetof(JOB_INFO_1, totalpages) },
+       { "pages_printed", PY_UINT32, offsetof(JOB_INFO_1, pagesprinted) },
+       { NULL }
+};
+
+struct pyconv py_JOB_INFO_2[] = {
+       { "jobid", PY_UINT32, offsetof(JOB_INFO_2, jobid) },
+       { "printer_name", PY_UNISTR, offsetof(JOB_INFO_2, printername) },
+       { "server_name", PY_UNISTR, offsetof(JOB_INFO_2, machinename) },
+       { "user_name", PY_UNISTR, offsetof(JOB_INFO_2, username) },
+       { "document_name", PY_UNISTR, offsetof(JOB_INFO_2, document) },
+       { "notify_name", PY_UNISTR, offsetof(JOB_INFO_2, notifyname) },
+       { "data_type", PY_UNISTR, offsetof(JOB_INFO_2, datatype) },
+       { "print_processor", PY_UNISTR, offsetof(JOB_INFO_2, printprocessor) },
+       { "parameters", PY_UNISTR, offsetof(JOB_INFO_2, parameters) },
+       { "driver_name", PY_UNISTR, offsetof(JOB_INFO_2, drivername) },
+       { "text_status", PY_UNISTR, offsetof(JOB_INFO_2, text_status) },
+       { "status", PY_UINT32, offsetof(JOB_INFO_2, status) },
+       { "priority", PY_UINT32, offsetof(JOB_INFO_2, priority) },
+       { "position", PY_UINT32, offsetof(JOB_INFO_2, position) },
+       { "start_time", PY_UINT32, offsetof(JOB_INFO_2, starttime) },
+       { "until_time", PY_UINT32, offsetof(JOB_INFO_2, untiltime) },
+       { "total_pages", PY_UINT32, offsetof(JOB_INFO_2, totalpages) },
+       { "size", PY_UINT32, offsetof(JOB_INFO_2, size) },
+       { "time_elapsed", PY_UINT32, offsetof(JOB_INFO_2, timeelapsed) },
+       { "pages_printed", PY_UINT32, offsetof(JOB_INFO_2, pagesprinted) },
+       { NULL }
+};
+
+struct pyconv py_DOC_INFO_1[] = {
+       { "document_name", PY_UNISTR, offsetof(DOC_INFO_1, docname) },
+       { "output_file", PY_UNISTR, offsetof(DOC_INFO_1, outputfile) },
+       { "data_type", PY_UNISTR, offsetof(DOC_INFO_1, datatype) },
+       { NULL }
+};
+
+BOOL py_from_JOB_INFO_1(PyObject **dict, JOB_INFO_1 *info)
+{
+       *dict = from_struct(info, py_JOB_INFO_1);
+       return True;
+}
+
+BOOL py_to_JOB_INFO_1(JOB_INFO_1 *info, PyObject *dict)
+{
+       return False;
+}
+
+BOOL py_from_JOB_INFO_2(PyObject **dict, JOB_INFO_2 *info)
+{
+       *dict = from_struct(info, py_JOB_INFO_2);
+       return True;
+}
+
+BOOL py_to_JOB_INFO_2(JOB_INFO_2 *info, PyObject *dict)
+{
+       return False;
+}
+
+BOOL py_from_DOC_INFO_1(PyObject **dict, DOC_INFO_1 *info)
+{
+       *dict = from_struct(info, py_DOC_INFO_1);
+       return True;
+}
+
+BOOL py_to_DOC_INFO_1(DOC_INFO_1 *info, PyObject *dict)
+{
+       return to_struct(info, dict, py_DOC_INFO_1);
+}
diff --git a/source3/python/py_spoolss_ports.c b/source3/python/py_spoolss_ports.c
new file mode 100644 (file)
index 0000000..b5f2102
--- /dev/null
@@ -0,0 +1,137 @@
+/* 
+   Python wrappers for DCERPC/SMB client routines.
+
+   Copyright (C) Tim Potter, 2002
+   
+   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 "python/py_spoolss.h"
+
+/* Enumerate ports */
+
+PyObject *spoolss_enumports(PyObject *self, PyObject *args, PyObject *kw)
+{
+       WERROR werror;
+       PyObject *result = NULL, *creds = NULL;
+       int level = 1;
+       uint32 i, needed, num_ports;
+       static char *kwlist[] = {"server", "level", "creds", NULL};
+       TALLOC_CTX *mem_ctx = NULL;
+       struct cli_state *cli = NULL;
+       char *server, *errstr;
+       PORT_INFO_CTR ctr;
+
+       /* Parse parameters */
+
+       if (!PyArg_ParseTupleAndKeywords(
+                   args, kw, "s|iO", kwlist, &server, &level, &creds))
+               return NULL;
+       
+       if (server[0] != '\\' || server[1] != '\\') {
+               PyErr_SetString(PyExc_ValueError, "UNC name required");
+               return NULL;
+       }
+
+       server += 2;
+
+       if (creds && creds != Py_None && !PyDict_Check(creds)) {
+               PyErr_SetString(PyExc_TypeError, 
+                               "credentials must be dictionary or None");
+               return NULL;
+       }
+
+       if (!(cli = open_pipe_creds(server, creds, PIPE_SPOOLSS, &errstr))) {
+               PyErr_SetString(spoolss_error, errstr);
+               free(errstr);
+               goto done;
+       }
+
+       if (!(mem_ctx = talloc_init())) {
+               PyErr_SetString(
+                       spoolss_error, "unable to init talloc context\n");
+               goto done;
+       }
+
+       /* Call rpc function */
+       
+       werror = cli_spoolss_enum_ports(
+               cli, mem_ctx, 0, &needed, level, &num_ports, &ctr);
+
+       if (W_ERROR_V(werror) == ERRinsufficientbuffer)
+               werror = cli_spoolss_enum_ports(
+                       cli, mem_ctx, needed, NULL, level,
+                       &num_ports, &ctr);
+
+       if (!W_ERROR_IS_OK(werror)) {
+               PyErr_SetObject(spoolss_werror, py_werror_tuple(werror));
+               goto done;
+       }
+
+       /* Return value */
+       
+       switch (level) {
+       case 1: 
+               result = PyDict_New();
+
+               for (i = 0; i < num_ports; i++) {
+                       PyObject *value;
+                       fstring name;
+
+                       rpcstr_pull(name, ctr.port.info_1[i].port_name.buffer,
+                                   sizeof(fstring), -1, STR_TERMINATE);
+
+                       py_from_PORT_INFO_1(&value, &ctr.port.info_1[i]);
+
+                       PyDict_SetItemString(
+                               value, "level", PyInt_FromLong(1));
+
+                       PyDict_SetItemString(result, name, value);
+               }
+
+               break;
+       case 2:
+               result = PyDict_New();
+
+               for(i = 0; i < num_ports; i++) {
+                       PyObject *value;
+                       fstring name;
+
+                       rpcstr_pull(name, ctr.port.info_2[i].port_name.buffer,
+                                   sizeof(fstring), -1, STR_TERMINATE);
+
+                       py_from_PORT_INFO_2(&value, &ctr.port.info_2[i]);
+
+                       PyDict_SetItemString(
+                               value, "level", PyInt_FromLong(2));
+
+                       PyDict_SetItemString(result, name, value);
+               }
+               
+               break;
+       default:
+               PyErr_SetString(spoolss_error, "unknown info level");
+               goto done;
+       }
+
+ done:
+       if (cli)
+               cli_shutdown(cli);
+       
+       if (mem_ctx)
+               talloc_destroy(mem_ctx);
+
+       return result;
+}
diff --git a/source3/python/py_tdb.c b/source3/python/py_tdb.c
new file mode 100644 (file)
index 0000000..4969c10
--- /dev/null
@@ -0,0 +1,614 @@
+/* 
+   Python wrappers for TDB module
+
+   Copyright (C) Tim Potter, 2002
+   
+   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.
+*/
+
+/* 
+   NOTE: Since tdb is licenced under the GPL any program that uses these bindings
+   must be distributed under the GPL license terms since this is what
+   the GPL requires.
+
+   http://www.gnu.org/licenses/gpl-faq.html#IfInterpreterIsGPL 
+*/
+
+#include "includes.h"
+#include "Python.h"
+
+/* Tdb exception */
+
+PyObject *py_tdb_error;
+
+/* tdb handle object */
+
+typedef struct {
+       PyObject_HEAD
+       TDB_CONTEXT *tdb;
+} tdb_hnd_object;
+
+PyTypeObject tdb_hnd_type;
+     
+PyObject *new_tdb_hnd_object(TDB_CONTEXT *tdb)
+{
+       tdb_hnd_object *obj;
+
+       obj = PyObject_New(tdb_hnd_object, &tdb_hnd_type);
+       obj->tdb = tdb;
+
+       return (PyObject *)obj;
+}
+
+PyObject *py_tdb_close(PyObject *self, PyObject *args)
+{
+       tdb_hnd_object *obj;
+
+       if (!PyArg_ParseTuple(args, "O!", &tdb_hnd_type, &obj))
+               return NULL;
+
+       if (tdb_close(obj->tdb) == -1) {
+               obj->tdb = NULL;
+               PyErr_SetString(py_tdb_error, strerror(errno));
+               return NULL;
+       }
+
+       obj->tdb = NULL;
+
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
+PyObject *py_tdb_open(PyObject *self, PyObject *args, PyObject *kw)
+{
+       static char *kwlist[] = { "name", "hash_size", "tdb_flags",
+                                 "open_flags", "mode", NULL };
+       char *name;
+       int hash_size = 0, flags = TDB_DEFAULT, open_flags = -1, open_mode = 0600;      
+       TDB_CONTEXT *tdb;
+
+       if (!PyArg_ParseTupleAndKeywords(
+                   args, kw, "s|iiii", kwlist, &name, &hash_size, &flags,
+                   &open_flags, &open_mode))
+               return NULL;
+
+       /* Default open_flags to read/write */
+
+       if (open_flags == -1) {
+               if (access(name, W_OK) == -1)
+                       open_flags = O_RDONLY;
+               else
+                       open_flags = O_RDWR;
+       }
+
+       if (!(tdb = tdb_open(name, hash_size, flags, open_flags, open_mode))) {
+               PyErr_SetString(py_tdb_error, strerror(errno));
+               return NULL;
+       }
+
+       return new_tdb_hnd_object(tdb);
+}
+
+/*
+ * Allow a tdb to act as a python mapping (dictionary)
+ */
+
+static int tdb_traverse_count(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
+                             void *state)
+{
+       /* Do nothing - tdb_traverse will return the number of records
+           traversed. */
+
+       return 0;
+}
+
+static int tdb_hnd_length(tdb_hnd_object *obj)
+{
+       int result;
+
+       result = tdb_traverse(obj->tdb, tdb_traverse_count, NULL);
+
+       return result;
+}
+
+static PyObject *tdb_hnd_subscript(tdb_hnd_object *obj, PyObject *key)
+{
+       TDB_DATA drec, krec;
+       PyObject *result;
+
+       if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize))
+               return NULL;
+
+       drec = tdb_fetch(obj->tdb, krec);
+
+       if (!drec.dptr) {
+               PyErr_SetString(PyExc_KeyError,
+                               PyString_AsString(key));
+               return NULL;
+       }
+
+       result = PyString_FromStringAndSize(drec.dptr, drec.dsize);
+       free(drec.dptr);
+
+       return result;
+}
+       
+static int tdb_ass_subscript(tdb_hnd_object *obj, PyObject *key, PyObject *value)
+{
+       TDB_DATA krec, drec;
+
+        if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize)) {
+               PyErr_SetString(PyExc_TypeError,
+                               "tdb mappings have string indices only");
+               return -1;
+       }
+
+        if (!obj->tdb) {
+               PyErr_SetString(
+                       py_tdb_error, "tdb object has been closed"); 
+               return -1; 
+        }
+
+       if (!value) {
+
+               /* Delete value */
+
+               if (tdb_delete(obj->tdb, krec) == -1) {
+                       PyErr_SetString(PyExc_KeyError,
+                                       PyString_AsString(value));
+                       return -1;
+               }
+
+       } else {
+
+               /* Set value */
+
+               if (!PyArg_Parse(value, "s#", &drec.dptr, &drec.dsize)) {
+                       PyErr_SetString(PyExc_TypeError,
+                                   "tdb mappings have string elements only");
+                       return -1;
+               }
+
+               errno = 0;
+
+               if (tdb_store(obj->tdb, krec, drec, 0) < 0 ) {
+                       if (errno != 0)
+                               PyErr_SetFromErrno(py_tdb_error);
+                       else
+                               PyErr_SetString(
+                                       py_tdb_error, 
+                                       (char *)tdb_errorstr(obj->tdb));
+
+                       return -1;
+               }
+       }
+
+       return 0;
+} 
+
+static PyMappingMethods tdb_mapping = {
+       (inquiry) tdb_hnd_length,
+       (binaryfunc) tdb_hnd_subscript,
+       (objobjargproc) tdb_ass_subscript
+};
+
+/*
+ * Utility methods
+ */
+
+/* Return non-zero if a given key exists in the tdb */
+
+PyObject *py_tdb_hnd_has_key(PyObject *self, PyObject *args)
+{
+       tdb_hnd_object *obj = (tdb_hnd_object *)self;
+       TDB_DATA key;
+
+       if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
+               return NULL;
+
+        if (!obj->tdb) {
+               PyErr_SetString(
+                       py_tdb_error, "tdb object has been closed"); 
+               return NULL;
+        }      
+
+       return PyInt_FromLong(tdb_exists(obj->tdb, key));
+}
+
+/* Return a list of keys in the tdb */
+
+static int tdb_traverse_keys(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
+                            void *state)
+{
+       PyObject *key_list = (PyObject *)state;
+
+       PyList_Append(key_list, 
+                     PyString_FromStringAndSize(key.dptr, key.dsize));
+
+       return 0;
+}
+
+PyObject *py_tdb_hnd_keys(PyObject *self, PyObject *args)
+{
+       tdb_hnd_object *obj = (tdb_hnd_object *)self;
+       PyObject *key_list = PyList_New(0);
+
+        if (!obj->tdb) {
+               PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
+               return NULL;
+        }      
+
+       if (tdb_traverse(obj->tdb, tdb_traverse_keys, key_list) == -1) {
+               PyErr_SetString(py_tdb_error, "error traversing tdb");
+               Py_DECREF(key_list);
+               return NULL;
+       }
+
+       return key_list;        
+}
+
+PyObject *py_tdb_hnd_first_key(PyObject *self, PyObject *args)
+{
+       tdb_hnd_object *obj = (tdb_hnd_object *)self;
+       TDB_DATA key;
+
+        if (!obj->tdb) {
+               PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
+               return NULL;
+        }      
+
+       key = tdb_firstkey(obj->tdb);
+
+       return Py_BuildValue("s#", key.dptr, key.dsize);
+}
+
+PyObject *py_tdb_hnd_next_key(PyObject *self, PyObject *py_oldkey)
+{
+       tdb_hnd_object *obj = (tdb_hnd_object *)self;
+       TDB_DATA key, oldkey;
+
+        if (!obj->tdb) {
+               PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
+               return NULL;
+        }      
+
+       if (!PyArg_Parse(py_oldkey, "s#", &oldkey.dptr, &oldkey.dsize))
+               return NULL;
+
+       key = tdb_nextkey(obj->tdb, oldkey);
+
+       return Py_BuildValue("s#", key.dptr, key.dsize);
+}
+
+/*
+ * Locking routines
+ */
+
+PyObject *py_tdb_hnd_lock_all(PyObject *self, PyObject *args)
+{
+       tdb_hnd_object *obj = (tdb_hnd_object *)self;
+       int result;
+
+        if (!obj->tdb) {
+               PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
+               return NULL;
+        }      
+
+       result = tdb_lockall(obj->tdb);
+
+       return PyInt_FromLong(result != -1);
+}
+
+PyObject *py_tdb_hnd_unlock_all(PyObject *self, PyObject *args)
+{
+       tdb_hnd_object *obj = (tdb_hnd_object *)self;
+
+        if (!obj->tdb) {
+               PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
+               return NULL;
+        }      
+
+       tdb_unlockall(obj->tdb);
+
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
+/* Return an array of keys from a python object which must be a string or a
+   list of strings. */
+
+static BOOL make_lock_list(PyObject *py_keys, TDB_DATA **keys, int *num_keys)
+{
+       /* Are we a list or a string? */
+
+       if (!PyList_Check(py_keys) && !PyString_Check(py_keys)) {
+               PyErr_SetString(PyExc_TypeError, "arg must be list of string");
+               return False;
+       }
+
+       if (PyList_Check(py_keys)) {
+               int i;
+
+               /* Turn python list into array of keys */
+               
+               *num_keys = PyList_Size(py_keys);
+               *keys = (TDB_DATA *)malloc(sizeof(TDB_DATA) * (*num_keys));
+               
+               for (i = 0; i < *num_keys; i++) {
+                       PyObject *key = PyList_GetItem(py_keys, i);
+                       
+                       if (!PyString_Check(key)) {
+                               PyErr_SetString(
+                                       PyExc_TypeError,
+                                       "list elements must be strings");
+                               return False;
+                       }
+
+                       PyArg_Parse(key, "s#", &(*keys)[i].dptr, 
+                                   &(*keys)[i].dsize);
+               }
+
+       } else {
+
+               /* Turn python string into a single key */
+
+               *keys = (TDB_DATA *)malloc(sizeof(TDB_DATA));
+               *num_keys = 1;
+               PyArg_Parse(py_keys, "s#", &(*keys)->dptr, &(*keys)->dsize);
+       }
+
+       return True;
+}
+
+PyObject *py_tdb_hnd_lock(PyObject *self, PyObject *args)
+{
+       tdb_hnd_object *obj = (tdb_hnd_object *)self;
+       PyObject *py_keys;
+       TDB_DATA *keys;
+       int num_keys, result;
+
+        if (!obj->tdb) {
+               PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
+               return NULL;
+        }      
+
+       if (!PyArg_ParseTuple(args, "O", &py_keys))
+               return NULL;
+
+       if (!make_lock_list(py_keys, &keys, &num_keys))
+               return NULL;
+
+       result = tdb_lockkeys(obj->tdb, num_keys, keys);
+
+       free(keys);
+
+       return PyInt_FromLong(result != -1);
+}
+
+PyObject *py_tdb_hnd_unlock(PyObject *self, PyObject *args)
+{
+       tdb_hnd_object *obj = (tdb_hnd_object *)self;
+       
+        if (!obj->tdb) {
+               PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
+               return NULL;
+        }      
+       
+       if (!PyArg_ParseTuple(args, ""))
+               return NULL;
+       
+       tdb_unlockkeys(obj->tdb);
+
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
+/*
+ * tdb traversal
+ */
+
+struct traverse_info {
+       PyObject *callback;
+       PyObject *state;
+};
+
+static int tdb_traverse_traverse(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
+                                void *state)
+{
+       struct traverse_info *info = state;
+       PyObject *arglist, *py_result;
+       int result;
+
+       arglist = Py_BuildValue("(s#s#O)", key.dptr, key.dsize, value.dptr,
+                               value.dsize, info->state);
+
+       py_result = PyEval_CallObject(info->callback, arglist);
+
+       Py_DECREF(arglist);
+       
+       if (!PyInt_Check(py_result)) {
+               result = 1;     /* Hmm - non-integer object returned by callback */
+               goto done;
+       }
+
+       result = PyInt_AsLong(py_result);
+
+done:
+       Py_DECREF(py_result);
+       return result;
+}
+
+PyObject *py_tdb_hnd_traverse(PyObject *self, PyObject *args, PyObject *kw)
+{
+       tdb_hnd_object *obj = (tdb_hnd_object *)self;
+       static char *kwlist[] = { "traverse_fn", "state", NULL };
+       PyObject *state = Py_None, *callback;
+       struct traverse_info info;
+       int result;
+
+       if (!PyArg_ParseTupleAndKeywords(
+                   args, kw, "O|O", kwlist, &callback, &state))
+               return NULL;
+
+       if (!PyCallable_Check(callback)) {
+               PyErr_SetString(PyExc_TypeError, "parameter must be callable");
+               return NULL;
+        }
+
+       Py_INCREF(callback);
+       Py_INCREF(state);
+
+       info.callback = callback;
+       info.state = state;
+
+       result = tdb_traverse(obj->tdb, tdb_traverse_traverse, &info);
+
+       Py_DECREF(callback);
+       Py_DECREF(state);
+
+       return PyInt_FromLong(result);
+}
+
+/* 
+ * Method dispatch table for this module
+ */
+
+static PyMethodDef tdb_methods[] = {
+       { "open", (PyCFunction)py_tdb_open, METH_VARARGS | METH_KEYWORDS },
+       { "close", (PyCFunction)py_tdb_close, METH_VARARGS },
+       { NULL }
+};
+
+/* 
+ * Methods on a tdb object
+ */
+
+static PyMethodDef tdb_hnd_methods[] = {
+       { "keys", (PyCFunction)py_tdb_hnd_keys, METH_VARARGS },
+       { "has_key", (PyCFunction)py_tdb_hnd_has_key, METH_VARARGS },
+       { "first_key", (PyCFunction)py_tdb_hnd_first_key, METH_VARARGS },
+       { "next_key", (PyCFunction)py_tdb_hnd_next_key, METH_VARARGS },
+       { "lock_all", (PyCFunction)py_tdb_hnd_lock_all, METH_VARARGS },
+       { "unlock_all", (PyCFunction)py_tdb_hnd_unlock_all, METH_VARARGS },
+       { "lock", (PyCFunction)py_tdb_hnd_lock, METH_VARARGS },
+       { "unlock", (PyCFunction)py_tdb_hnd_unlock, METH_VARARGS },
+       { "traverse", (PyCFunction)py_tdb_hnd_traverse, METH_VARARGS | METH_KEYWORDS },
+       { NULL }
+};
+
+/* Deallocate a tdb handle object */
+
+static void tdb_hnd_dealloc(PyObject* self)
+{
+        tdb_hnd_object *hnd = (tdb_hnd_object *)self;
+
+       if (hnd->tdb) {
+               tdb_close(hnd->tdb);
+               hnd->tdb = NULL;
+       }
+}
+
+/* Return tdb handle attributes */
+
+static PyObject *tdb_hnd_getattr(PyObject *self, char *attrname)
+{
+       return Py_FindMethod(tdb_hnd_methods, self, attrname);
+}
+
+static char tdb_hnd_type_doc[] = 
+"Python wrapper for tdb.";
+
+PyTypeObject tdb_hnd_type = {
+       PyObject_HEAD_INIT(NULL)
+       0,
+       "tdb",
+       sizeof(tdb_hnd_object),
+       0,
+       tdb_hnd_dealloc,        /* tp_dealloc*/
+       0,                      /* tp_print*/
+       tdb_hnd_getattr,        /* tp_getattr*/
+       0,                      /* tp_setattr*/
+       0,                      /* tp_compare*/
+       0,                      /* tp_repr*/
+       0,                      /* tp_as_number*/
+       0,                      /* tp_as_sequence*/
+       &tdb_mapping,           /* tp_as_mapping*/
+       0,                      /* tp_hash */
+       0,                      /* tp_call */
+       0,                      /* tp_str */
+       0,                      /* tp_getattro */
+       0,                      /* tp_setattro */
+       0,                      /* tp_as_buffer*/
+       Py_TPFLAGS_DEFAULT,     /* tp_flags */
+       tdb_hnd_type_doc,       /* tp_doc */
+};
+
+/* Constants */
+
+static struct const_vals {
+       char *name;
+       uint32 value;
+} module_const_vals[] = {
+
+        /* Flags for tdb_open() */
+
+       { "TDB_DEFAULT", TDB_DEFAULT },
+       { "TDB_CLEAR_IF_FIRST", TDB_CLEAR_IF_FIRST },
+       { "TDB_INTERNAL", TDB_INTERNAL },
+       { "TDB_NOLOCK", TDB_NOLOCK },
+       { "TDB_NOMMAP", TDB_NOMMAP },
+       { "TDB_CONVERT", TDB_CONVERT },
+       { "TDB_BIGENDIAN", TDB_BIGENDIAN },
+       
+       { NULL },
+};
+
+static void const_init(PyObject *dict)
+{
+       struct const_vals *tmp;
+       PyObject *obj;
+
+       for (tmp = module_const_vals; tmp->name; tmp++) {
+               obj = PyInt_FromLong(tmp->value);
+               PyDict_SetItemString(dict, tmp->name, obj);
+               Py_DECREF(obj);
+       }
+}
+
+/* Module initialisation */
+
+void inittdb(void)
+{
+       PyObject *module, *dict;
+
+       /* Initialise module */
+
+       module = Py_InitModule("tdb", tdb_methods);
+       dict = PyModule_GetDict(module);
+
+       py_tdb_error = PyErr_NewException("tdb.error", NULL, NULL);
+       PyDict_SetItemString(dict, "error", py_tdb_error);
+
+       /* Initialise policy handle object */
+
+       tdb_hnd_type.ob_type = &PyType_Type;
+
+       PyDict_SetItemString(dict, "tdb.hnd", 
+                            (PyObject *)&tdb_hnd_type);
+
+       /* Initialise constants */
+
+       const_init(dict);
+}
diff --git a/source3/python/py_tdb.h b/source3/python/py_tdb.h
new file mode 100644 (file)
index 0000000..794a20c
--- /dev/null
@@ -0,0 +1,29 @@
+/* 
+   Python wrappers for DCERPC/SMB client routines.
+
+   Copyright (C) Tim Potter, 2002
+   
+   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.
+*/
+
+#ifndef _PY_TDB_H
+#define _PY_TDB_H
+
+#include "includes.h"
+#include "Python.h"
+
+#include "python/py_common_proto.h"
+
+#endif /* _PY_TDB_H */
diff --git a/source3/python/py_winreg.c b/source3/python/py_winreg.c
new file mode 100644 (file)
index 0000000..ce27f5c
--- /dev/null
@@ -0,0 +1,82 @@
+/* 
+   Python wrappers for DCERPC/SMB client routines.
+
+   Copyright (C) Tim Potter, 2002
+   
+   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 "python/py_winreg.h"
+
+static struct const_vals {
+       char *name;
+       uint32 value;
+} module_const_vals[] = {
+       
+       /* Registry value types */
+
+       { "REG_NONE", REG_NONE },
+       { "REG_SZ", REG_SZ },
+       { "REG_EXPAND_SZ", REG_EXPAND_SZ },
+       { "REG_BINARY", REG_BINARY },
+       { "REG_DWORD", REG_DWORD },
+       { "REG_DWORD_LE", REG_DWORD_LE },
+       { "REG_DWORD_BE", REG_DWORD_BE },
+       { "REG_LINK", REG_LINK },
+       { "REG_MULTI_SZ", REG_MULTI_SZ },
+       { "REG_RESOURCE_LIST", REG_RESOURCE_LIST },
+       { "REG_FULL_RESOURCE_DESCRIPTOR", REG_FULL_RESOURCE_DESCRIPTOR },
+       { "REG_RESOURCE_REQUIREMENTS_LIST", REG_RESOURCE_REQUIREMENTS_LIST },
+
+       { NULL },
+};
+
+static void const_init(PyObject *dict)
+{
+       struct const_vals *tmp;
+       PyObject *obj;
+
+       for (tmp = module_const_vals; tmp->name; tmp++) {
+               obj = PyInt_FromLong(tmp->value);
+               PyDict_SetItemString(dict, tmp->name, obj);
+               Py_DECREF(obj);
+       }
+}
+
+/*
+ * Module initialisation 
+ */
+
+static PyMethodDef winreg_methods[] = {
+       { NULL }
+};
+
+void initwinreg(void)
+{
+       PyObject *module, *dict;
+
+       /* Initialise module */
+
+       module = Py_InitModule("winreg", winreg_methods);
+       dict = PyModule_GetDict(module);
+
+       /* Initialise constants */
+
+       const_init(dict);
+
+       /* Do samba initialisation */
+
+       py_samba_init();
+}
diff --git a/source3/python/py_winreg.h b/source3/python/py_winreg.h
new file mode 100644 (file)
index 0000000..088be72
--- /dev/null
@@ -0,0 +1,29 @@
+/* 
+   Python wrappers for DCERPC/SMB client routines.
+
+   Copyright (C) Tim Potter, 2002
+   
+   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.
+*/
+
+#ifndef _PY_WINREG_H
+#define _PY_WINREG_H
+
+#include "includes.h"
+#include "Python.h"
+
+#include "python/py_common_proto.h"
+
+#endif /* _PY_WINREG_H */
diff --git a/source3/rpc_server/srv_samr_util.c b/source3/rpc_server/srv_samr_util.c
new file mode 100644 (file)
index 0000000..7a5b1e5
--- /dev/null
@@ -0,0 +1,143 @@
+/* 
+   Unix SMB/CIFS implementation.
+   SAMR Pipe utility functions.
+   Copyright (C) Jeremy Allison                1996-2001
+   Copyright (C) Luke Kenneth Casson Leighton  1996-1998
+   Copyright (C) Gerald (Jerry) Carter         2000-2001
+   Copyright (C) Andrew Bartlett               2001-2002
+      
+   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"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+/*************************************************************
+ Copies a SAM_USER_INFO_23 to a SAM_ACCOUNT
+ **************************************************************/
+
+void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from)
+{
+
+       if (from == NULL || to == NULL) 
+               return;
+
+       pdb_set_logon_time(to,nt_time_to_unix(&from->logon_time), True);
+       pdb_set_logoff_time(to,nt_time_to_unix(&from->logoff_time), True);
+       pdb_set_kickoff_time(to, nt_time_to_unix(&from->kickoff_time), True);
+       pdb_set_pass_can_change_time(to, nt_time_to_unix(&from->pass_can_change_time), True);
+       pdb_set_pass_must_change_time(to, nt_time_to_unix(&from->pass_must_change_time), True);
+
+       pdb_set_pass_last_set_time(to, nt_time_to_unix(&from->pass_last_set_time));
+
+       if (from->uni_user_name.buffer)
+               pdb_set_username(to      , pdb_unistr2_convert(&from->uni_user_name   ));
+       if (from->uni_full_name.buffer)
+               pdb_set_fullname(to      , pdb_unistr2_convert(&from->uni_full_name   ));
+       if (from->uni_home_dir.buffer)
+               pdb_set_homedir(to       , pdb_unistr2_convert(&from->uni_home_dir    ), True);
+       if (from->uni_dir_drive.buffer)
+               pdb_set_dir_drive(to     , pdb_unistr2_convert(&from->uni_dir_drive   ), True);
+       if (from->uni_logon_script.buffer)
+               pdb_set_logon_script(to  , pdb_unistr2_convert(&from->uni_logon_script), True);
+       if (from->uni_profile_path.buffer)
+               pdb_set_profile_path(to  , pdb_unistr2_convert(&from->uni_profile_path), True);
+       if (from->uni_acct_desc.buffer)
+               pdb_set_acct_desc(to     , pdb_unistr2_convert(&from->uni_acct_desc   ));
+       if (from->uni_workstations.buffer)
+               pdb_set_workstations(to  , pdb_unistr2_convert(&from->uni_workstations));
+       if (from->uni_unknown_str.buffer)
+               pdb_set_unknown_str(to   , pdb_unistr2_convert(&from->uni_unknown_str ));
+       if (from->uni_munged_dial.buffer)
+               pdb_set_munged_dial(to   , pdb_unistr2_convert(&from->uni_munged_dial ));
+
+       if (from->user_rid)
+               pdb_set_user_sid_from_rid(to, from->user_rid);
+       if (from->group_rid)
+               pdb_set_group_sid_from_rid(to, from->group_rid);
+
+       pdb_set_acct_ctrl(to, from->acb_info);
+       pdb_set_unknown_3(to, from->unknown_3);
+
+       pdb_set_logon_divs(to, from->logon_divs);
+       pdb_set_hours_len(to, from->logon_hrs.len);
+       pdb_set_hours(to, from->logon_hrs.hours);
+
+       pdb_set_unknown_5(to, from->unknown_5);
+       pdb_set_unknown_6(to, from->unknown_6);
+}
+
+
+/*************************************************************
+ Copies a sam passwd.
+ **************************************************************/
+
+void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from)
+{
+       if (from == NULL || to == NULL) 
+               return;
+
+       pdb_set_logon_time(to,nt_time_to_unix(&from->logon_time), True);
+       pdb_set_logoff_time(to,nt_time_to_unix(&from->logoff_time), True);
+       pdb_set_kickoff_time(to, nt_time_to_unix(&from->kickoff_time), True);
+       pdb_set_pass_can_change_time(to, nt_time_to_unix(&from->pass_can_change_time), True);
+       pdb_set_pass_must_change_time(to, nt_time_to_unix(&from->pass_must_change_time), True);
+
+       pdb_set_pass_last_set_time(to, nt_time_to_unix(&from->pass_last_set_time));
+
+       if (from->uni_user_name.buffer)
+               pdb_set_username(to      , pdb_unistr2_convert(&from->uni_user_name   ));
+       if (from->uni_full_name.buffer)
+               pdb_set_fullname(to      , pdb_unistr2_convert(&from->uni_full_name   ));
+       if (from->uni_home_dir.buffer)
+               pdb_set_homedir(to       , pdb_unistr2_convert(&from->uni_home_dir    ), True);
+       if (from->uni_dir_drive.buffer)
+               pdb_set_dir_drive(to     , pdb_unistr2_convert(&from->uni_dir_drive   ), True);
+       if (from->uni_logon_script.buffer)
+               pdb_set_logon_script(to  , pdb_unistr2_convert(&from->uni_logon_script), True);
+       if (from->uni_profile_path.buffer)
+               pdb_set_profile_path(to  , pdb_unistr2_convert(&from->uni_profile_path), True);
+       if (from->uni_acct_desc.buffer)
+               pdb_set_acct_desc(to     , pdb_unistr2_convert(&from->uni_acct_desc   ));
+       if (from->uni_workstations.buffer)
+               pdb_set_workstations(to  , pdb_unistr2_convert(&from->uni_workstations));
+       if (from->uni_unknown_str.buffer)
+               pdb_set_unknown_str(to   , pdb_unistr2_convert(&from->uni_unknown_str ));
+       if (from->uni_munged_dial.buffer)
+               pdb_set_munged_dial(to   , pdb_unistr2_convert(&from->uni_munged_dial ));
+
+       if (from->user_rid)
+               pdb_set_user_sid_from_rid(to, from->user_rid);
+       if (from->group_rid)
+               pdb_set_group_sid_from_rid(to, from->group_rid);
+
+       /* FIXME!!  Do we need to copy the passwords here as well?
+          I don't know.  Need to figure this out   --jerry */
+
+       /* Passwords dealt with in caller --abartlet */
+
+       pdb_set_acct_ctrl(to, from->acb_info);
+       pdb_set_unknown_3(to, from->unknown_3);
+
+       pdb_set_logon_divs(to, from->logon_divs);
+       pdb_set_hours_len(to, from->logon_hrs.len);
+       pdb_set_hours(to, from->logon_hrs.hours);
+
+       pdb_set_unknown_5(to, from->unknown_5);
+       pdb_set_unknown_6(to, from->unknown_6);
+}
+
diff --git a/source3/script/findsmb.in b/source3/script/findsmb.in
new file mode 100755 (executable)
index 0000000..d2aa945
--- /dev/null
@@ -0,0 +1,145 @@
+#!/usr/bin/perl
+#
+# Prints info on all smb responding machines on a subnet.
+# This script needs to be run on a machine without nmbd running and be
+# run as root to get correct info from WIN95 clients.
+#
+# syntax:
+#    findsmb [subnet broadcast address]
+#
+# with no agrument it will list machines on the current subnet
+#
+# There will be a "+" in front of the workgroup name for machines that are
+# local master browsers for that workgroup. There will be an "*" in front
+# of the workgroup name for machines that are the domain master browser for
+# that workgroup.
+#
+
+$SAMBABIN = "@prefix@/bin";
+
+for ($i = 0; $i < 2; $i++) {   # test for -d option and broadcast address
+  $_ = shift;
+  if (m/-d|-D/) {
+    $DEBUG = 1;
+  } else  {
+    if ($_) {
+      $BCAST = "-B $_";
+    }
+  }
+}
+
+sub ipsort                     # do numeric sort on last field of IP address
+{
+  @t1 = split(/\./,$a);
+  @t2 = split(/\./,$b);
+  @t1[3] <=> @t2[3];
+}
+
+# look for all machines that respond to a name lookup
+
+open(NMBLOOKUP,"$SAMBABIN/nmblookup $BCAST '*'|") || 
+  die("Can't run nmblookup '*'.\n");
+
+# get rid of all lines that are not a response IP address,
+# strip everything but IP address and sort by last field in address
+
+@ipaddrs = sort ipsort grep(s/ \*<00>.*$//,<NMBLOOKUP>);
+
+# print header info
+
+print "\nIP ADDR         NETBIOS NAME   WORKGROUP/OS/VERSION $BCAST\n";
+print "---------------------------------------------------------------------\n";
+
+foreach $ip (@ipaddrs)         # loop through each IP address found
+{
+  $ip =~ s/\n//;               # strip newline from IP address
+
+# find the netbios names registered by each machine
+
+  open(NMBLOOKUP,"$SAMBABIN/nmblookup -r -A $ip|") || 
+       die("Can't get nmb name list.\n");
+  @nmblookup = <NMBLOOKUP>;
+  close NMBLOOKUP;
+
+# get the first <00> name
+
+  @name = grep(/<00>/,@nmblookup);
+  $_ = @name[0];
+  if ($_) {                     # we have a netbios name
+    if (/GROUP/) {             # is it a group name
+       ($name, $aliases, $type, $length, @addresses) = 
+       gethostbyaddr(pack('C4',split('\.',$ip)),2);
+       if (! $name) {                  # could not get name
+           $name = "unknown nis name";
+       }
+    } else {
+# The Netbios name can contain lot of characters also '<' '>'
+# and spaces. The follwing cure inside name space but not
+# names starting or ending with spaces
+       /(.{1,15})\s+<00>\s+/;
+       $name = $1;
+    }
+
+# do an smbclient command on the netbios name.
+
+    open(SMB,"$SAMBABIN/smbclient -N -L $name -I $ip -U% |") ||
+       die("Can't do smbclient command.\n");
+    @smb = <SMB>;
+    close SMB;
+
+    if ($DEBUG) {              # if -d flag print results of nmblookup and smbclient
+      print "===============================================================\n";
+      print @nmblookup;
+      print @smb;
+    }
+
+# look for the OS= string
+
+    @info = grep(/OS=/,@smb);
+    $_ = @info[0];
+    if ($_) {                          # we found response
+      s/Domain=|OS=|Server=|\n//g;     # strip out descriptions to make line shorter
+
+    } else {                           # no OS= string in response (WIN95 client)
+
+# for WIN95 clients get workgroup name from nmblookup response
+      @name = grep(/<00> - <GROUP>/,@nmblookup);
+      $_ = @name[0];
+      if ($_) {
+# Same as before for space and characters
+        /(.{1,15})\s+<00>\s+/;
+        $_ = "[$1]";
+      } else {
+       $_ = "Unknown Workgroup";
+      }
+    }
+
+# see if machine registered a local master browser name
+    if (grep(/<1d>/,@nmblookup)) {
+      $master = '+';                   # indicate local master browser
+      if (grep(/<1b>/,@nmblookup)) {   # how about domain master browser?
+        $master = '*';                 # indicate domain master browser
+      }
+    } else {
+      $master = ' ';                   # not a browse master
+    }
+
+# line up info in 3 columns
+
+    print "$ip".' 'x(16-length($ip))."$name".' 'x(14-length($name))."$master"."$_\n";
+
+  } else {                             # no netbios name found
+# try getting the host name
+    ($name, $aliases, $type, $length, @addresses) = 
+      gethostbyaddr(pack('C4',split('\.',$ip)),2);
+    if (! $name) {                     # could not get name
+      $name = "unknown nis name";
+    }
+    if ($DEBUG) {                      # if -d flag print results of nmblookup
+      print "===============================================================\n";
+      print @nmblookup;
+    }
+    print "$ip".' 'x(16-length($ip))."$name\n";
+  }
+} 
+
diff --git a/source3/script/findstatic.pl b/source3/script/findstatic.pl
new file mode 100755 (executable)
index 0000000..43a4916
--- /dev/null
@@ -0,0 +1,70 @@
+#!/usr/bin/perl -w
+# find a list of fns and variables in the code that could be static
+# usually called with something like this:
+#    findstatic.pl `find . -name "*.o"`
+# Andrew Tridgell <tridge@samba.org>
+
+use strict;
+
+# use nm to find the symbols
+my($saved_delim) = $/;
+undef $/;
+my($syms) = `nm -o @ARGV`;
+$/ = $saved_delim;
+
+my(@lines) = split(/\n/s, $syms);
+
+my(%def);
+my(%undef);
+my(%stype);
+
+my(%typemap) = (
+              "T" => "function",
+              "C" => "uninitialised variable",
+              "D" => "initialised variable"
+               );
+
+
+# parse the symbols into defined and undefined 
+for (my($i)=0; $i <= $#{@lines}; $i++) {
+       my($line) = $lines[$i];
+       if ($line =~ /(.*):[a-f0-9]* ([TCD]) (.*)/) {
+               my($fname) = $1;
+               my($symbol) = $3;
+               push(@{$def{$fname}}, $symbol);
+               $stype{$symbol} = $2;
+       }
+       if ($line =~ /(.*):\s* U (.*)/) {
+               my($fname) = $1;
+               my($symbol) = $2;
+               push(@{$undef{$fname}}, $symbol);
+       }
+}
+
+# look for defined symbols that are never referenced outside the place they 
+# are defined
+foreach my $f (keys %def) {
+       print "Checking $f\n";
+       my($found_one) = 0;
+       foreach my $s (@{$def{$f}}) {
+               my($found) = 0;
+               foreach my $f2 (keys %undef) {
+                       if ($f2 ne $f) {
+                               foreach my $s2 (@{$undef{$f2}}) {
+                                       if ($s2 eq $s) {
+                                               $found = 1;
+                                               $found_one = 1;
+                                       }
+                               }
+                       }
+               }
+               if ($found == 0) {
+                       my($t) = $typemap{$stype{$s}};
+                       print "  '$s' is unique to $f  ($t)\n";
+               }
+       }
+       if ($found_one == 0) {
+               print "  all symbols in '$f' are unused (main program?)\n";
+       }
+}
+
diff --git a/source3/tdb/tdbutil.h b/source3/tdb/tdbutil.h
new file mode 100644 (file)
index 0000000..0147344
--- /dev/null
@@ -0,0 +1,37 @@
+/* 
+   Unix SMB/CIFS implementation.
+   tdb utility functions
+   Copyright (C) Andrew Tridgell 1999
+   
+   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.
+*/
+
+#ifndef __TDBUTIL_H__
+#define __TDBUTIL_H__
+
+
+/* single node of a list returned by tdb_search_keys */
+typedef struct keys_node 
+{
+       struct keys_node *prev, *next;
+       TDB_DATA node_key;
+} TDB_LIST_NODE;
+
+
+TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT*, const char*);
+void tdb_search_list_free(TDB_LIST_NODE*);
+
+
+#endif /* __TDBUTIL_H__ */
diff --git a/source3/utils/.cvsignore b/source3/utils/.cvsignore
new file mode 100644 (file)
index 0000000..6b8749f
--- /dev/null
@@ -0,0 +1 @@
+net_proto.h
\ No newline at end of file