r1383: sync from 3.0 tree
authorGerald Carter <jerry@samba.org>
Wed, 7 Jul 2004 19:18:31 +0000 (19:18 +0000)
committerGerald Carter <jerry@samba.org>
Wed, 7 Jul 2004 19:18:31 +0000 (19:18 +0000)
117 files changed:
examples/smb.conf.default
packaging/RedHat/samba.spec.tmpl
source/Makefile.in
source/VERSION
source/auth/auth_util.c
source/client/client.c
source/client/clitar.c
source/client/smbspool.c
source/configure.in
source/include/client.h
source/include/debug.h
source/include/includes.h
source/include/local.h
source/include/rpc_dce.h
source/include/rpc_netlogon.h
source/include/rpc_samr.h
source/include/safe_string.h
source/include/smb.h
source/include/smbldap.h
source/lib/afs_settoken.c
source/lib/charcnv.c
source/lib/iconv.c
source/lib/interface.c
source/lib/smbldap.c
source/lib/snprintf.c
source/lib/time.c
source/lib/username.c
source/lib/util.c
source/lib/util_sock.c
source/lib/util_str.c
source/libads/kerberos.c
source/libads/kerberos_keytab.c [new file with mode: 0644]
source/libads/kerberos_verify.c
source/libads/krb5_setpw.c
source/libads/ldap.c
source/libads/sasl.c
source/libsmb/asn1.c
source/libsmb/clientgen.c
source/libsmb/clikrb5.c
source/libsmb/clispnego.c
source/libsmb/conncache.c
source/libsmb/namequery.c
source/libsmb/ntlmssp.c
source/libsmb/smb_signing.c
source/locking/brlock.c
source/locking/locking.c
source/nmbd/nmbd_browsesync.c
source/nmbd/nmbd_winsserver.c
source/nsswitch/winbindd.c
source/nsswitch/winbindd_cache.c
source/nsswitch/winbindd_cm.c
source/nsswitch/winbindd_group.c
source/nsswitch/winbindd_passdb.c
source/nsswitch/winbindd_rpc.c
source/nsswitch/winbindd_util.c
source/param/loadparm.c
source/passdb/login_cache.c
source/passdb/lookup_sid.c
source/passdb/passdb.c
source/passdb/pdb_ldap.c
source/printing/notify.c
source/printing/nt_printing.c
source/printing/print_cups.c
source/printing/printing.c
source/printing/printing_db.c
source/rpc_client/cli_netlogon.c
source/rpc_client/cli_pipe.c
source/rpc_parse/parse_net.c
source/rpc_parse/parse_prs.c
source/rpc_parse/parse_samr.c
source/rpc_server/srv_lsa_nt.c
source/rpc_server/srv_netlog.c
source/rpc_server/srv_netlog_nt.c
source/rpc_server/srv_pipe.c
source/rpc_server/srv_pipe_hnd.c
source/rpc_server/srv_samr_util.c
source/rpc_server/srv_spoolss_nt.c
source/rpc_server/srv_srvsvc_nt.c
source/rpcclient/cmd_spoolss.c
source/sam/idmap.c
source/sam/idmap_ldap.c
source/script/mkproto.awk
source/smbd/blocking.c
source/smbd/close.c
source/smbd/conn.c
source/smbd/connection.c
source/smbd/dir.c
source/smbd/dosmode.c
source/smbd/error.c
source/smbd/filename.c
source/smbd/lanman.c
source/smbd/mangle_hash.c
source/smbd/msdfs.c
source/smbd/negprot.c
source/smbd/notify_hash.c
source/smbd/nttrans.c
source/smbd/open.c
source/smbd/oplock.c
source/smbd/posix_acls.c
source/smbd/process.c
source/smbd/quotas.c
source/smbd/reply.c
source/smbd/server.c
source/smbd/service.c
source/smbd/session.c
source/smbd/sesssetup.c
source/smbd/trans2.c
source/smbd/uid.c
source/smbd/utmp.c
source/smbd/vfs.c
source/tdb/Makefile
source/torture/torture.c
source/torture/vfstest.c
source/utils/net_ads.c
source/utils/net_rpc.c
source/utils/ntlm_auth.c
source/utils/smbcacls.c

index 839fede123357ef2202df733b413ea40692916c5..58d38aa9f7dd965bcde231a280a111d957c5b538 100644 (file)
@@ -4,7 +4,12 @@
 # many!) most of which are not shown in this example
 #
 # For a step to step guide on installing, configuring and using samba, 
-# read the Samba HOWTO Collection.
+# read the Samba-HOWTO-Collection. This may be obtained from:
+#  http://www.samba.org/samba/docs/Samba-HOWTO-Collection.pdf
+#
+# Many working examples of smb.conf files can be found in the 
+# Samba-Guide which is generated daily and can be downloaded from: 
+#  http://www.samba.org/samba/docs/Samba-Guide.pdf
 #
 # Any line which starts with a ; (semi-colon) or a # (hash) 
 # is a comment and is ignored. In this example we will use a #
@@ -17,7 +22,7 @@
 #======================= Global Settings =====================================
 [global]
 
-# workgroup = NT-Domain-Name or Workgroup-Name, eg: REDHAT4
+# workgroup = NT-Domain-Name or Workgroup-Name, eg: MIDEARTH
    workgroup = MYGROUP
 
 # server string is the equivalent of the NT Description field
@@ -25,7 +30,7 @@
 
 # Security mode. Defines in which mode Samba will operate. Possible 
 # values are share, user, server, domain and ads. Most people will want 
-# user level security. See the HOWTO Collection for details.
+# user level security. See the Samba-HOWTO-Collection for details.
    security = user
 
 # This option is important for security. It allows you to restrict
index 06237af7260b9cf3109d3c0622e3e08ee743f030..aafb9bd21885a5b2626f189cb62ac5e22fbb82ee 100644 (file)
@@ -16,7 +16,8 @@ Source998: filter-requires-samba_rh8.sh
 Source999: filter-requires-samba_rh9.sh
 
 Packager: Gerald Carter [Samba-Team] <jerry@samba.org>
-Requires: pam pam-devel kernel glibc
+Requires: pam openldap krb5-libs 
+BuildRequires: openldap-devel krb5-devel pam-devel
 Prereq: chkconfig fileutils /sbin/ldconfig
 Provides: samba = %{version}
 Obsoletes: samba-common, samba-client, samba-swat
index c8d2b959a4db08f5f238293358da27b21bbee1de..398ad4e0e3f9a41cff36df7579d33e2e71c37bb2 100644 (file)
@@ -228,7 +228,7 @@ KRBCLIENT_OBJ = libads/kerberos.o libads/ads_status.o
 
 LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o libads/sasl.o \
             libads/krb5_setpw.o libads/ldap_user.o \
-            libads/ads_struct.o \
+            libads/ads_struct.o libads/kerberos_keytab.o \
              libads/disp_sec.o libads/ads_utils.o libads/ldap_utils.o \
             libads/ads_ldap.o libads/authdata.o
 
@@ -1315,9 +1315,9 @@ installswat: installdirs installmsg
        @$(SHELL) $(srcdir)/script/installswat.sh $(DESTDIR)$(SWATDIR) $(srcdir)
 
 installclientlib: installdirs libsmbclient
-       @$(SHELL) $(srcdir)/script/installdirs.sh $(DESTDIR)${prefix}/lib
-       -$(INSTALLCLIENTCMD_SH) bin/libsmbclient.@SHLIBEXT@ $(DESTDIR)${prefix}/lib
-       -$(INSTALLCLIENTCMD_A) bin/libsmbclient.a $(DESTDIR)${prefix}/lib
+       @$(SHELL) $(srcdir)/script/installdirs.sh $(DESTDIR)$(LIBDIR)
+       -$(INSTALLCLIENTCMD_SH) bin/libsmbclient.@SHLIBEXT@ $(DESTDIR)$(LIBDIR)
+       -$(INSTALLCLIENTCMD_A) bin/libsmbclient.a $(DESTDIR)$(LIBDIR)
        @$(SHELL) $(srcdir)/script/installdirs.sh $(DESTDIR)${prefix}/include
        -$(INSTALLCMD) $(srcdir)/include/libsmbclient.h $(DESTDIR)${prefix}/include
 
index e493805fdb4c7b7896cadce1d7c2954df4e05504..5a7d9836c85e6b5327777267aea1a0263859fade 100644 (file)
@@ -29,7 +29,7 @@ SAMBA_VERSION_RELEASE=5
 # e.g. SAMBA_VERSION_PRE_RELEASE=1                     #
 #  ->  "2.2.9pre1"                                     #
 ########################################################
-SAMBA_VERSION_PRE_RELEASE=1
+SAMBA_VERSION_PRE_RELEASE=2
 
 ########################################################
 # For 'rc' releases the version will be                #
@@ -51,7 +51,7 @@ SAMBA_VERSION_RC_RELEASE=
 # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes               #
 #  ->  "3.0.0-SVN-build-199"                           #
 ########################################################
-SAMBA_VERSION_IS_SVN_SNAPSHOT=
+SAMBA_VERSION_IS_SVN_SNAPSHOT=yes
 
 ########################################################
 # This can be set by vendors if they want...           #
index 9a03e7fe13cf1e8f02a09a4a24b6c6474201c1e5..5e8f18881fb26b3f6563ca97bb6f2329f735e5c9 100644 (file)
@@ -972,25 +972,25 @@ struct passwd *smb_getpwnam( char *domuser, fstring save_username, BOOL create )
 {
        struct passwd *pw = NULL;
        char *p;
-       fstring mapped_username;
-       fstring strip_username;
+       fstring username;
        
        /* we only save a copy of the username it has been mangled 
           by winbindd use default domain */
           
        save_username[0] = '\0';
-       
-       /* save a local copy of the username and run it through the 
-          username map */
           
-       fstrcpy( mapped_username, domuser );
-       map_username( mapped_username );        
+       /* don't call map_username() here since it has to be done higher 
+          up the stack so we don't call it mutliple times */
+
+       fstrcpy( username, domuser );
        
-       p = strchr_m( mapped_username, *lp_winbind_separator() );
+       p = strchr_m( username, *lp_winbind_separator() );
        
        /* code for a DOMAIN\user string */
        
        if ( p ) {
+               fstring strip_username;
+
                pw = Get_Pwnam( domuser );
                if ( pw ) {     
                        /* make sure we get the case of the username correct */
@@ -999,8 +999,10 @@ struct passwd *smb_getpwnam( char *domuser, fstring save_username, BOOL create )
                        if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
                                char *domain;
                                
-                               domain = mapped_username;
+                               /* split the domain and username into 2 strings */
                                *p = '\0';
+                               domain = username;
+
                                fstr_sprintf(save_username, "%s%c%s", domain, *lp_winbind_separator(), pw->pw_name);
                        }
                        else
@@ -1011,26 +1013,26 @@ struct passwd *smb_getpwnam( char *domuser, fstring save_username, BOOL create )
                }
 
                /* setup for lookup of just the username */
-               /* remember that p and mapped_username are overlapping memory */
+               /* remember that p and username are overlapping memory */
 
                p++;
                fstrcpy( strip_username, p );
-               fstrcpy( mapped_username, strip_username );
+               fstrcpy( username, strip_username );
        }
        
        /* just lookup a plain username */
        
-       pw = Get_Pwnam(mapped_username);
+       pw = Get_Pwnam(username);
                
        /* Create local user if requested. */
        
        if ( !pw && create ) {
                /* Don't add a machine account. */
-               if (mapped_username[strlen(mapped_username)-1] == '$')
+               if (username[strlen(username)-1] == '$')
                        return NULL;
 
-               auth_add_user_script(NULL, mapped_username);
-               pw = Get_Pwnam(mapped_username);
+               auth_add_user_script(NULL, username);
+               pw = Get_Pwnam(username);
        }
        
        /* one last check for a valid passwd struct */
@@ -1207,7 +1209,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
        
        /* Create a 'combined' list of all SIDs we might want in the SD */
        
-       all_group_SIDs = malloc(sizeof(DOM_SID) * (info3->num_groups2 +info3->num_other_sids));
+       all_group_SIDs = malloc(sizeof(DOM_SID) * (info3->num_groups2 + info3->num_other_sids + n_lgroupSIDs));
        
        if (!all_group_SIDs) {
                DEBUG(0, ("malloc() failed for DOM_SID list!\n"));
@@ -1216,12 +1218,6 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
                return NT_STATUS_NO_MEMORY;
        }
 
-#if 0  /* JERRY -- no such thing as local groups in current code */
-       /* Copy the 'local' sids */
-       memcpy(all_group_SIDs, lgroupSIDs, sizeof(DOM_SID) * n_lgroupSIDs);
-       SAFE_FREE(lgroupSIDs);
-#endif
-
        /* and create (by appending rids) the 'domain' sids */
        
        for (i = 0; i < info3->num_groups2; i++) {
@@ -1254,13 +1250,22 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
                sid_copy(&all_group_SIDs[info3->num_groups2 + i],
                         &info3->other_sids[i].sid);
        }
+
+
+       /* add local alias sids */ 
+
+       for (i = 0; i < n_lgroupSIDs; i++) {
+               sid_copy(&all_group_SIDs[info3->num_groups2 +
+                                        info3->num_other_sids + i],
+                        &lgroupSIDs[i]);
+       }
        
        /* Where are the 'global' sids... */
 
        /* can the user be guest? if yes, where is it stored? */
        
        nt_status = create_nt_user_token(&user_sid, &group_sid,
-               info3->num_groups2 + info3->num_other_sids,
+               info3->num_groups2 + info3->num_other_sids + n_lgroupSIDs,
                all_group_SIDs, False, &token);
                
        if ( !NT_STATUS_IS_OK(nt_status) ) {
@@ -1425,8 +1430,10 @@ BOOL is_trusted_domain(const char* dom_name)
 
        /* if we are a DC, then check for a direct trust relationships */
 
-       if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) {
+       if ( IS_DC ) {
                become_root();
+               DEBUG (5,("is_trusted_domain: Checking for domain trust with [%s]\n",
+                       dom_name ));
                ret = secrets_fetch_trusted_domain_password(dom_name, &pass, &trustdom_sid, &lct);
                unbecome_root();
                SAFE_FREE(pass);
index a0470315f82baf664a857ffec7dd6239eeb5b783..1fccfaa581ca0d33ee97a839bc41b9b9811af225 100644 (file)
@@ -1571,7 +1571,7 @@ static int cmd_open(void)
        }
        pstrcat(mask,buf);
 
-       cli_open(cli, mask, O_RDWR, DENY_ALL);
+       cli_nt_create(cli, mask, FILE_READ_DATA);
 
        return 0;
 }
@@ -1868,6 +1868,21 @@ static int cmd_lowercase(void)
        return 0;
 }
 
+/****************************************************************************
+ Toggle the case sensitive flag.
+****************************************************************************/
+
+static int cmd_setcase(void)
+{
+       BOOL orig_case_sensitive = cli_set_case_sensitive(cli, False);
+
+       cli_set_case_sensitive(cli, !orig_case_sensitive);
+       DEBUG(2,("filename case sensitivity is now %s\n",!orig_case_sensitive ?
+               "on":"off"));
+
+       return 0;
+}
+
 /****************************************************************************
  Toggle the recurse flag.
 ****************************************************************************/
@@ -2179,6 +2194,7 @@ static struct
   {"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit",{COMPL_NONE,COMPL_NONE}},
   {"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
   {"cancel",cmd_cancel,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}},
+  {"case_sensitive",cmd_setcase,"toggle the case sensitive flag to server",{COMPL_NONE,COMPL_NONE}},
   {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
   {"chmod",cmd_chmod,"<src> <mode> chmod a file using UNIX permission",{COMPL_REMOTE,COMPL_REMOTE}},
   {"chown",cmd_chown,"<src> <uid> <gid> chown a file using UNIX uids and gids",{COMPL_REMOTE,COMPL_REMOTE}},
@@ -2563,9 +2579,10 @@ static void readline_callback(void)
  Process commands on stdin.
 ****************************************************************************/
 
-static void process_stdin(void)
+static int process_stdin(void)
 {
        const char *ptr;
+       int rc = 0;
 
        while (1) {
                pstring tok;
@@ -2593,13 +2610,14 @@ static void process_stdin(void)
                if (!next_token_nr(&ptr,tok,NULL,sizeof(tok))) continue;
 
                if ((i = process_tok(tok)) >= 0) {
-                       commands[i].fn();
+                       rc = commands[i].fn();
                } else if (i == -2) {
                        d_printf("%s: command abbreviation ambiguous\n",tok);
                } else {
                        d_printf("%s: command not found\n",tok);
                }
        }
+       return rc;
 }
 
 /***************************************************** 
index e43b3e4cc50bee204166c43d70e5d2e6b014f265..64c194b54dae7d91997e3fcd7b985083c2bcdbee 100644 (file)
@@ -1357,9 +1357,8 @@ int cmd_tar(void)
        if (!tar_parseargs(argcl, argl, buf, 0))
                return 1;
 
-       process_tar();
        SAFE_FREE(argl);
-       return 0;
+       return process_tar();
 }
 
 /****************************************************************************
@@ -1368,6 +1367,7 @@ Command line (option) version
 
 int process_tar(void)
 {
+       int rc = 0;
        initarbuf();
        switch(tar_type) {
                case 'x':
@@ -1445,7 +1445,7 @@ int process_tar(void)
                clipn = 0;
                must_free_cliplist = False;
        }
-       return(0);
+       return rc;
 }
 
 /****************************************************************************
index 5daefec5a550f2dd0a8f610b1705f2e437dedfda..a67ccadb90b45e460eddebecbd6854964da29460 100644 (file)
@@ -36,7 +36,7 @@ extern BOOL           in_client;      /* Boolean for client library */
  */
 
 static void            list_devices(void);
-static struct cli_state        *smb_connect(const char *, const char *, const char *, const char *, const char *);
+static struct cli_state        *smb_connect(const char *, const char *, int, const char *, const char *, const char *);
 static int             smb_print(struct cli_state *, char *, FILE *);
 
 
@@ -50,6 +50,7 @@ static int            smb_print(struct cli_state *, char *, FILE *);
 {
   int          i;              /* Looping var */
   int          copies;         /* Number of copies */
+  int          port;           /* Port number */
   char         uri[1024],      /* URI */
                *sep,           /* Pointer to separator */
                *password;      /* Password */
@@ -87,7 +88,7 @@ static int            smb_print(struct cli_state *, char *, FILE *);
     fputs("       The DEVICE_URI environment variable can also contain the\n", stderr);
     fputs("       destination printer:\n", stderr);
     fputs("\n", stderr);
-    fputs("           smb://[username:password@][workgroup/]server/printer\n", stderr);
+    fputs("           smb://[username:password@][workgroup/]server[:port]/printer\n", stderr);
     return (1);
   }
 
@@ -179,7 +180,17 @@ static int         smb_print(struct cli_state *, char *, FILE *);
   }
   else
     workgroup = NULL;
+  
+  if ((sep = strrchr_m(server, ':')) != NULL)
+  {
+    *sep++ = '\0';
 
+    port=atoi(sep);
+  }
+  else
+       port=0;
+       
  /*
   * Setup the SAMBA server state...
   */
@@ -201,7 +212,7 @@ static int          smb_print(struct cli_state *, char *, FILE *);
 
   do
   {
-    if ((cli = smb_connect(workgroup, server, printer, username, password)) == NULL)
+    if ((cli = smb_connect(workgroup, server, port, printer, username, password)) == NULL)
     {
       if (getenv("CLASS") == NULL)
       {
@@ -267,6 +278,7 @@ list_devices(void)
 static struct cli_state *              /* O - SMB connection */
 smb_connect(const char *workgroup,             /* I - Workgroup */
             const char *server,                /* I - Server */
+            const int port,            /* I - Port */
             const char *share,         /* I - Printer */
             const char *username,              /* I - Username */
             const char *password)              /* I - Password */
@@ -281,7 +293,7 @@ smb_connect(const char *workgroup,          /* I - Workgroup */
 
   get_myname(myname);  
        
-  nt_status = cli_full_connection(&c, myname, server, NULL, 0, share, "?????", 
+  nt_status = cli_full_connection(&c, myname, server, NULL, port, share, "?????", 
                                  username, workgroup, password, 0, Undefined, NULL);
   
   if (!NT_STATUS_IS_OK(nt_status)) {
index e1fc69b4b7943dc6e46823f999d36154a6dbcaa1..e57076a346aca945b11954f104adbf16da0eddd4 100644 (file)
@@ -11,6 +11,11 @@ AC_ENABLE_SHARED
 SMB_VERSION_STRING=`cat include/version.h | grep 'SAMBA_VERSION_OFFICIAL_STRING' | cut -d '"' -f2`
 echo "SAMBA VERSION: ${SMB_VERSION_STRING}"
 
+SAMBA_VERSION_SVN_REVISION=`cat include/version.h | grep 'SAMBA_VERSION_SVN_REVISION' | cut -d ' ' -f3-`
+if test -n "${SAMBA_VERSION_SVN_REVISION}";then
+       echo "BUILD REVISION: ${SAMBA_VERSION_SVN_REVISION}"
+fi
+
 #################################################
 # Directory handling stuff to support both the
 # legacy SAMBA directories and FHS compliant
@@ -707,10 +712,12 @@ if test x$enable_cups != xno; then
        AC_PATH_PROG(CUPS_CONFIG, cups-config)
 
         if test "x$CUPS_CONFIG" != x; then
-                        AC_DEFINE(HAVE_CUPS,1,[Whether we have CUPS])
+                AC_DEFINE(HAVE_CUPS,1,[Whether we have CUPS])
                CFLAGS="$CFLAGS `$CUPS_CONFIG --cflags`"
                LDFLAGS="$LDFLAGS `$CUPS_CONFIG --ldflags`"
                PRINT_LIBS="$PRINT_LIBS `$CUPS_CONFIG --libs`"
+       elif test x$enable_cups == xyes; then
+               AC_MSG_ERROR(Cups support required but cups-config not located.  Make sure cups-devel related files are installed.)
         fi
 fi
 
@@ -2708,6 +2715,7 @@ if test x"$with_ads_support" != x"no"; then
   # now see if we can find the krb5 libs in standard paths
   # or as specified above
   AC_CHECK_LIB_EXT(krb5, KRB5_LIBS, krb5_mk_req_extended)
+  AC_CHECK_LIB_EXT(krb5, KRB5_LIBS, krb5_kt_compare)
 
   ########################################################
   # now see if we can find the gssapi libs in standard paths
@@ -2730,6 +2738,9 @@ if test x"$with_ads_support" != x"no"; then
   AC_CHECK_FUNC_EXT(krb5_free_ktypes, $KRB5_LIBS)
   AC_CHECK_FUNC_EXT(krb5_free_data_contents, $KRB5_LIBS)
   AC_CHECK_FUNC_EXT(krb5_principal_get_comp_string, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_free_unparsed_name, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_free_keytab_entry_contents, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_kt_free_entry, $KRB5_LIBS)
 
   LIBS="$LIBS $KRB5_LIBS"
   
@@ -2812,6 +2823,18 @@ if test x"$with_ads_support" != x"no"; then
               [Whether the AP_OPTS_USE_SUBKEY ap option is available])
   fi
 
+  AC_CACHE_CHECK([for KV5M_KEYTAB],
+                 samba_cv_HAVE_KV5M_KEYTAB,[
+    AC_TRY_COMPILE([#include <krb5.h>],
+      [krb5_keytab_entry entry; entry.magic = KV5M_KEYTAB;],
+      samba_cv_HAVE_KV5M_KEYTAB=yes,
+      samba_cv_HAVE_KV5M_KEYTAB=no)])
+
+  if test x"$samba_cv_HAVE_KV5M_KEYTAB" = x"yes"; then
+      AC_DEFINE(HAVE_KV5M_KEYTAB,1,
+             [Whether the KV5M_KEYTAB option is available])
+  fi
+
   AC_CACHE_CHECK([for the krb5_princ_component macro],
                 samba_cv_HAVE_KRB5_PRINC_COMPONENT,[
     AC_TRY_LINK([#include <krb5.h>],
@@ -2862,7 +2885,45 @@ if test x"$with_ads_support" != x"no"; then
     KRB5_LIBS=""
     with_ads_support=no 
   fi
-  LIBS="$ac_save_LIBS"
+
+  AC_CACHE_CHECK([for WRFILE: keytab support],
+                samba_cv_HAVE_WRFILE_KEYTAB,[
+    AC_TRY_RUN([
+#include<krb5.h>
+  main()
+  {
+    krb5_context context;
+    krb5_keytab keytab;
+
+    krb5_init_context(&context);
+    if (krb5_kt_resolve(context, "WRFILE:api", &keytab))
+      exit(0);
+    exit(1);
+  }],
+  samba_cv_HAVE_WRFILE_KEYTAB=no,
+  samba_cv_HAVE_WRFILE_KEYTAB=yes)])
+
+  if test x"$samba_cv_HAVE_WRFILE_KEYTAB" = x"yes"; then
+      AC_DEFINE(HAVE_WRFILE_KEYTAB,1,
+               [Whether the WRFILE:-keytab is supported])
+  fi
+
+  AC_CACHE_CHECK([for krb5_princ_realm returns krb5_realm or krb5_data],
+               samba_cv_KRB5_PRINC_REALM_RETURNS_REALM,[
+    AC_TRY_COMPILE([#include <krb5.h>],
+    [
+    krb5_context context;
+    krb5_principal principal;
+    krb5_realm realm; realm = *krb5_princ_realm(context, principal);],
+    samba_cv_KRB5_PRINC_REALM_RETURNS_REALM=yes,
+    samba_cv_KRB5_PRINC_REALM_RETURNS_REALM=no)])
+
+  if test x"$samba_cv_KRB5_PRINC_REALM_RETURNS_REALM" = x"yes"; then
+    AC_DEFINE(KRB5_PRINC_REALM_RETURNS_REALM,1,
+              [Whether krb5_princ_realm returns krb5_realm or krb5_data])
+  fi
+
+LIBS="$ac_save_LIBS"
 fi
 
 ########################################################
@@ -2950,6 +3011,7 @@ AC_ARG_WITH(smbmount,
 )
 
 
+
 #################################################
 # check for a PAM clear-text auth, accounts, password and session support
 with_pam_for_crypt=no
index 968b73f0b41cdaadd6eee576b5f880e9795d1b3c..52a6c76299d606b2af80c55c8b9d2ba387859647 100644 (file)
@@ -153,6 +153,7 @@ struct cli_state {
        BOOL (*oplock_handler)(struct cli_state *cli, int fnum, unsigned char level);
 
        BOOL force_dos_errors;
+       BOOL case_sensitive; /* False by default. */
 
        /* was this structure allocated by cli_initialise? If so, then
            free in cli_shutdown() */
index 52e06b9360bfa51512d532a0ef956eda9dc0b5f4..05a9a3f0c523426deb900b243f83514045dd5621 100644 (file)
@@ -33,7 +33,7 @@
  * diffferent prototype declarations), so we must do these by hand.
  */
 /* I know the __attribute__ stuff is ugly, but it does ensure we get the 
-   arguemnts to DEBUG() right. We have got them wrong too often in the 
+   arguments to DEBUG() right. We have got them wrong too often in the 
    past.
    The PRINTFLIKE comment does the equivalent for SGI MIPSPro.
  */
index ea8eb1a3043b835e16fa285765d6ebbe8ada8198..7657984bfb195fd04f1911d31b429b5ff2effe14 100644 (file)
@@ -1239,6 +1239,7 @@ int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3);
 
 #if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
 #define snprintf smb_snprintf
+#define vsnprintf smb_vsnprintf
 #endif
 
 void sys_adminlog(int priority, const char *format_str, ...) PRINTF_ATTRIBUTE(2,3);
@@ -1293,6 +1294,10 @@ krb5_error_code krb5_set_default_tgs_ktypes(krb5_context ctx, const krb5_enctype
 krb5_error_code krb5_auth_con_setuseruserkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock *keyblock);
 #endif
 
+#ifndef HAVE_KRB5_FREE_UNPARSED_NAME
+void krb5_free_unparsed_name(krb5_context ctx, char *val);
+#endif
+
 /* Samba wrapper function for krb5 functionality. */
 void setup_kaddr( krb5_address *pkaddr, struct sockaddr *paddr);
 int create_kerberos_key_from_string(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, krb5_enctype enctype);
index 540365047a2b281a724cbd2e8a64b315f29ec5d7..7ac2e256120ac1892c37c5b86ec514c7d8e485d6 100644 (file)
 /* size of listen() backlog in smbd */
 #define SMBD_LISTEN_BACKLOG 50
 
+/* Number of microseconds to wait before a sharing violation. */
+#define SHARING_VIOLATION_USEC_WAIT 950000
+
+#define MAX_LDAP_REPLICATION_SLEEP_TIME 5000 /* In milliseconds. */
+
 #endif
index 0df903109db27b54fd5b42bc6193251c259eae80..57b1184bd96a537ea0049e702960bcefbe3b22e4 100644 (file)
@@ -71,7 +71,8 @@ enum RPC_PKT_TYPE
    to NT4.  Actually, anything other than 1ff would seem to do... */
 #define NETLOGON_NEG_AUTH2_FLAGS 0x000701ff
  
-#define NETLOGON_NEG_SCHANNEL    0x40000000
+#define NETLOGON_NEG_SCHANNEL                  0x40000000
+#define NETLOGON_NEG_DOMAIN_TRUST_ACCOUNT      0x2010b000
 
 enum netsec_direction
 {
index a5b93b0238a3479428907ba562f1538f7361bd6e..44beb2b8c82e81bec2c0584811fbd816f37987ba 100644 (file)
 #define SAM_DATABASE_BUILTIN   0x01 /* BUILTIN users and groups */
 #define SAM_DATABASE_PRIVS     0x02 /* Privileges */
 
+#define NETLOGON_CONTROL_REDISCOVER            0x5
+#define NETLOGON_CONTROL_TC_QUERY              0x6
+#define NETLOGON_CONTROL_TRANSPORT_NOTIFY      0x7
+#define NETLOGON_CONTROL_SET_DBFLAG            0xfffe
+
 #if 0
 /* I think this is correct - it's what gets parsed on the wire. JRA. */
 /* NET_USER_INFO_2 */
@@ -204,7 +209,7 @@ typedef struct netlogon_2_info
        uint32  flags;            /* 0x0 - undocumented */
        uint32  pdc_status;       /* 0x0 - undocumented */
        uint32  ptr_trusted_dc_name; /* pointer to trusted domain controller name */
-       uint32  tc_status;           /* 0x051f - ERROR_NO_LOGON_SERVERS */
+       uint32  tc_status;           
        UNISTR2 uni_trusted_dc_name; /* unicode string - trusted dc name */
 
 } NETLOGON_INFO_2;
@@ -255,6 +260,26 @@ typedef struct net_r_logon_ctrl_info
        NTSTATUS status;
 } NET_R_LOGON_CTRL;
 
+
+typedef struct ctrl_data_info_5
+{
+       uint32          function_code;
+       
+       uint32          ptr_domain;
+       UNISTR2         domain;
+       
+} CTRL_DATA_INFO_5;
+
+typedef struct ctrl_data_info_6
+{
+       uint32          function_code;
+       
+       uint32          ptr_domain;
+       UNISTR2         domain;
+       
+} CTRL_DATA_INFO_6;
+
+
 /********************************************************
  Logon Control2 Query
 
@@ -266,13 +291,16 @@ typedef struct net_r_logon_ctrl_info
 /* NET_Q_LOGON_CTRL2 - LSA Netr Logon Control 2 */
 typedef struct net_q_logon_ctrl2_info
 {
-       uint32       ptr;             /* undocumented buffer pointer */
-       UNISTR2      uni_server_name; /* server name, starting with two '\'s */
+       uint32          ptr;             /* undocumented buffer pointer */
+       UNISTR2         uni_server_name; /* server name, starting with two '\'s */
+       
+       uint32          function_code; 
+       uint32          query_level;   
+       union {
+               CTRL_DATA_INFO_5 info5;
+               CTRL_DATA_INFO_6 info6;
+       } info;
        
-       uint32       function_code; /* 0x1 */
-       uint32       query_level;   /* 0x1, 0x3 */
-       uint32       switch_value;  /* 0x1 */
-
 } NET_Q_LOGON_CTRL2;
 
 /*******************************************************
index 089941de3aadfd6b9f66ac2d27e59aa51febf69c..ae603c9cd93cea8db44aae4d31e669916b2a6343 100644 (file)
@@ -1068,6 +1068,14 @@ typedef struct samr_group_info1
 
 } GROUP_INFO1;
 
+typedef struct samr_group_info2
+{
+       uint16 level;
+       UNIHDR hdr_acct_name;
+       UNISTR2 uni_acct_name;
+
+} GROUP_INFO2;
+
 typedef struct samr_group_info3
 {
        uint32 unknown_1; /* 0x0000 0003 - number of group members? */
@@ -1090,6 +1098,7 @@ typedef struct group_info_ctr
        union
        {
                GROUP_INFO1 info1;
+               GROUP_INFO2 info2;
                GROUP_INFO3 info3;
                GROUP_INFO4 info4;
 
@@ -1734,11 +1743,7 @@ typedef struct q_samr_get_dom_pwinfo
 typedef struct r_samr_get_dom_pwinfo
 {
        /*
-        * Previously this was 3 uint16's.  However, after some tests
-        * it appears that the data len for the signing needs to be 16.
-        * Not sure how 3 unit16's ever worked since the length always
-        * turned out to 12.  3 uint32's + NT_STATUS == 16 bytes.  Tested
-        * using NT and 2k.  --jerry
+        * See Samba4 IDL
         */
        uint16 unk_0;
        uint32 unk_1;
index b22c5efcc99aa62984dab533b4a0ced8486a3470..d278e29aca59cbc6ff3d4939b70b188f5c417509 100644 (file)
@@ -59,7 +59,7 @@
 #ifdef strncasecmp
 #undef strncasecmp
 #endif
-#define strncasecmp __ERROR__XX__NEVER_USE_STRCASECMP__;
+#define strncasecmp __ERROR__XX__NEVER_USE_STRNCASECMP__;
 
 #endif /* !_SPLINT_ */
 
index 54a69d1433aa3dc5dfe93dc46007abfead97d11f..a802e9622662c431614eb9becbc7b8a66dc3b00d 100644 (file)
@@ -584,6 +584,24 @@ struct interface
        struct in_addr nmask;
 };
 
+/* struct used by share mode violation error processing */
+typedef struct {
+       pid_t pid;
+       uint16 mid;
+       struct timeval time;
+       SMB_DEV_T dev;
+       SMB_INO_T inode;
+       uint16 port;
+} deferred_open_entry;
+
+/* Internal message queue for deferred opens. */
+struct pending_message_list {
+       struct pending_message_list *next, *prev;
+       struct timeval msg_time; /* The timeout time */
+       DATA_BLOB buf;
+       DATA_BLOB private_data;
+};
+
 /* struct returned by get_share_modes */
 typedef struct {
        pid_t pid;
@@ -663,28 +681,14 @@ struct locking_key {
        SMB_INO_T inode;
 };
 
-struct locking_data {
-       union {
-               int num_share_mode_entries;
-               share_mode_entry dummy; /* Needed for alignment. */
-       } u;
-       /* the following two entries are implicit 
-          share_mode_entry modes[num_share_mode_entries];
-           char file_name[];
-       */
-};
-
-
 /* the following are used by loadparm for option lists */
-typedef enum
-{
-  P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,P_LIST,
-  P_STRING,P_USTRING,P_GSTRING,P_UGSTRING,P_ENUM,P_SEP
+typedef enum {
+       P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,P_LIST,
+       P_STRING,P_USTRING,P_GSTRING,P_UGSTRING,P_ENUM,P_SEP
 } parm_type;
 
-typedef enum
-{
-  P_LOCAL,P_GLOBAL,P_SEPARATOR,P_NONE
+typedef enum {
+       P_LOCAL,P_GLOBAL,P_SEPARATOR,P_NONE
 } parm_class;
 
 /* passed to br lock code */
@@ -1345,7 +1349,8 @@ enum ldap_ssl_types {LDAP_SSL_ON, LDAP_SSL_OFF, LDAP_SSL_START_TLS};
 enum ldap_passwd_sync_types {LDAP_PASSWD_SYNC_ON, LDAP_PASSWD_SYNC_OFF, LDAP_PASSWD_SYNC_ONLY};
 
 /* Remote architectures we know about. */
-enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT, RA_WIN2K, RA_WINXP, RA_WIN2K3, RA_SAMBA};
+enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT,
+                       RA_WIN2K, RA_WINXP, RA_WIN2K3, RA_SAMBA, RA_CIFSFS};
 
 /* case handling */
 enum case_handling {CASE_LOWER,CASE_UPPER};
@@ -1410,6 +1415,7 @@ extern int chain_size;
 #define EXCLUSIVE_OPLOCK 1
 #define BATCH_OPLOCK 2
 #define LEVEL_II_OPLOCK 4
+#define INTERNAL_OPEN_ONLY 8
 
 #define EXCLUSIVE_OPLOCK_TYPE(lck) ((lck) & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
 #define BATCH_OPLOCK_TYPE(lck) ((lck) & BATCH_OPLOCK)
@@ -1461,6 +1467,25 @@ extern int chain_size;
 #define LEVEL_II_OPLOCK_BREAK_CMD 0x3
 #define ASYNC_LEVEL_II_OPLOCK_BREAK_CMD 0x4
 
+/* Add the "deferred open" message. */
+#define RETRY_DEFERRED_OPEN_CMD 0x5
+
+/*
+ * And the message format for it. Keep the same message length.
+ *
+ *  0     2       2+pid   2+pid+dev 2+pid+dev+ino
+ *  +----+--------+-------+--------+---------+
+ *  | cmd| pid    | dev   |  inode | mid     |
+ *  +----+--------+-------+--------+---------+
+ */
+
+#define DEFERRED_OPEN_CMD_OFFSET 0
+#define DEFERRED_OPEN_PID_OFFSET 2 /* pid we're *sending* from. */
+#define DEFERRED_OPEN_DEV_OFFSET (DEFERRED_OPEN_PID_OFFSET + sizeof(pid_t))
+#define DEFERRED_OPEN_INODE_OFFSET (DEFERRED_OPEN_DEV_OFFSET + sizeof(SMB_DEV_T))
+#define DEFERRED_OPEN_MID_OFFSET (DEFERRED_OPEN_INODE_OFFSET + sizeof(SMB_INO_T))
+#define DEFERRED_OPEN_MSG_LEN OPLOCK_BREAK_MSG_LEN
+
 /*
  * Capabilities abstracted for different systems.
  */
index 61b8df0f0efb5f9e6c6ea95dd03db0d99fa75638..c7de7d84b375226b5243d7d9ece202246e4496e8 100644 (file)
@@ -153,5 +153,6 @@ struct smbldap_state {
 
 struct smbldap_state;
 
-#endif /* _SMBLDAP_H */
+#define LDAP_CONNECT_DEFAULT_TIMEOUT   5
 
+#endif /* _SMBLDAP_H */
index eb10c4c66d45416f592a8a1fb5cb4791538d7162..5c646c72e48028cc59a022d8658d4049b95b1ac6 100644 (file)
 #include <afs/venus.h>
 #include <asm/unistd.h>
 #include <openssl/des.h>
+#include <sys/syscall.h>
 
-_syscall5(int, afs_syscall, int, subcall,
-         char *, path,
-         int, cmd,
-         char *, cmarg,
-         int, follow);
+int afs_syscall( int subcall,
+         char * path,
+         int cmd,
+         char * cmarg,
+         int follow)
+{
+       return( syscall( SYS_afs_syscall, subcall, path, cmd, cmarg, follow));
+}
 
 struct ClearToken {
        uint32 AuthHandle;
index b9791931a35d45b28cb508848f663248ec4d25eb..3d7678c34cb168decf8ef42e9adbd72513fcc76e 100644 (file)
@@ -932,7 +932,7 @@ size_t pull_ascii_fstring(char *dest, const void *src)
 
 size_t pull_ascii_nstring(char *dest, size_t dest_len, const void *src)
 {
-       return pull_ascii(dest, src, dest_len, sizeof(nstring), STR_TERMINATE);
+       return pull_ascii(dest, src, dest_len, sizeof(nstring)-1, STR_TERMINATE);
 }
 
 /**
index 7df73192f24a6df5b25626dc041c60e5761efce3..4c9ecf992e6790190e0ee1e4e0598de9ff237863 100644 (file)
@@ -129,7 +129,11 @@ static size_t sys_iconv(void *cd,
        size_t ret = iconv((iconv_t)cd, 
                           inbuf, inbytesleft, 
                           outbuf, outbytesleft);
-       if (ret == (size_t)-1) iconv(cd, NULL, NULL, NULL, NULL);
+       if (ret == (size_t)-1) {
+               int saved_errno = errno;
+               iconv(cd, NULL, NULL, NULL, NULL);
+               errno = saved_errno;
+       }
        return ret;
 #else
        errno = EINVAL;
index 4d8010e31bc4e61e4019a624ddb129ea6e86f962..adf9ca34381e45d723450fe6cbf2b816e13d73db 100644 (file)
@@ -94,7 +94,7 @@ This handles the following different forms:
 4) ip/mask
 5) bcast/mask
 ****************************************************************************/
-static void interpret_interface(const char *token)
+static void interpret_interface(char *token)
 {
        struct in_addr ip, nmask;
        char *p;
@@ -130,9 +130,9 @@ static void interpret_interface(const char *token)
        }
 
        /* parse it into an IP address/netmasklength pair */
-       *p++ = 0;
-
+       *p = 0;
        ip = *interpret_addr2(token);
+       *p++ = '/';
 
        if (strlen(p) > 2) {
                nmask = *interpret_addr2(p);
@@ -207,7 +207,11 @@ void load_interfaces(void)
 
        if (ptr) {
                while (*ptr) {
-                       interpret_interface(*ptr);
+                       char *ptr_cpy = strdup(*ptr);
+                       if (ptr_cpy) {
+                               interpret_interface(ptr_cpy);
+                               free(ptr_cpy);
+                       }
                        ptr++;
                }
        }
index 21e2a7c1018ec84a180226a5b4f9e4d545ac35d8..d058613f004e8a9c5a1f7989d721f27ed5a99dab 100644 (file)
@@ -676,7 +676,7 @@ static int rebindproc_with_state  (LDAP * ld, char **whop, char **credp,
                *methodp = LDAP_AUTH_SIMPLE;
        }
 
-       gettimeofday(&(ldap_state->last_rebind),NULL);
+       GetTimeOfDay(&ldap_state->last_rebind);
                
        return 0;
 }
@@ -704,7 +704,7 @@ static int rebindproc_connect_with_state (LDAP *ldap_struct,
 
        rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
        
-       gettimeofday(&(ldap_state->last_rebind),NULL);
+       GetTimeOfDay(&ldap_state->last_rebind);
 
        return rc;
 }
@@ -755,8 +755,7 @@ static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_
        char *ldap_secret;
 
        /* get the password */
-       if (!fetch_ldap_pw(&ldap_dn, &ldap_secret))
-       {
+       if (!fetch_ldap_pw(&ldap_dn, &ldap_secret)) {
                DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
                return LDAP_INVALID_CREDENTIALS;
        }
@@ -808,7 +807,7 @@ static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_
 }
 
 /**********************************************************************
-Connect to LDAP server (called before every ldap operation)
+ Connect to LDAP server (called before every ldap operation)
 *********************************************************************/
 static int smbldap_open(struct smbldap_state *ldap_state)
 {
@@ -854,7 +853,7 @@ static int smbldap_open(struct smbldap_state *ldap_state)
 
 
        ldap_state->last_ping = time(NULL);
-       DEBUG(4,("The LDAP server is succesful connected\n"));
+       DEBUG(4,("The LDAP server is succesfully connected\n"));
 
        return LDAP_SUCCESS;
 }
@@ -933,25 +932,25 @@ int smbldap_search(struct smbldap_state *ldap_state,
 
        if (ldap_state->last_rebind.tv_sec > 0) {
                struct timeval  tval;
-               int             tdiff = 0;
+               SMB_BIG_INT     tdiff = 0;
                int             sleep_time = 0;
 
                ZERO_STRUCT(tval);
+               GetTimeOfDay(&tval);
 
-               gettimeofday(&tval,NULL);
-
-               tdiff = 1000000 *(tval.tv_sec - ldap_state->last_rebind.tv_sec) + 
-                       (tval.tv_usec - ldap_state->last_rebind.tv_usec);
+               tdiff = usec_time_diff(&tval, &ldap_state->last_rebind.tv_sec);
+               tdiff /= 1000; /* Convert to milliseconds. */
 
-               sleep_time = ((1000*lp_ldap_replication_sleep())-tdiff)/1000;
+               sleep_time = lp_ldap_replication_sleep()-(int)tdiff;
+               sleep_time = MIN(sleep_time, MAX_LDAP_REPLICATION_SLEEP_TIME);
 
                if (sleep_time > 0) {
                        /* we wait for the LDAP replication */
                        DEBUG(5,("smbldap_search: waiting %d milliseconds for LDAP replication.\n",sleep_time));
                        smb_msleep(sleep_time);
                        DEBUG(5,("smbldap_search: go on!\n"));
-                       ZERO_STRUCT(ldap_state->last_rebind);
                }
+               ZERO_STRUCT(ldap_state->last_rebind);
        }
 
        if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) {
index 5b0cfa1ab337774fcc4c48bc0936a817dd574536..79de3c0ca5d86072a7fef2e96c0d54bd64336e3f 100644 (file)
@@ -817,7 +817,7 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
        (*currlen)++;
 }
 
- int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
+ int smb_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
 {
        return dopr(str, count, fmt, args);
 }
index faca2cba879b78f62782bfd2fae3d2413350dc8e..e63e0b29659c2ff425e377382c97fd8556e22d04 100644 (file)
@@ -754,3 +754,9 @@ BOOL nt_time_is_zero(NTTIME *nt)
                return True;
        return False;
 }
+
+SMB_BIG_INT usec_time_diff(struct timeval *larget, struct timeval *smallt)
+{
+       SMB_BIG_INT sec_diff = larget->tv_sec - smallt->tv_sec;
+       return (sec_diff * 1000000) + (SMB_BIG_INT)(larget->tv_usec - smallt->tv_usec);
+}
index ac5530b5c71dd7b2c04cc93be56f377cd5a05e71..317935d396ffade1d1b2ac349b1c70408b20a3ff 100644 (file)
@@ -306,7 +306,7 @@ static BOOL user_in_netgroup_list(const char *user, const char *ngname)
 {
 #ifdef HAVE_NETGROUP
        static char *mydomain = NULL;
-       fstring lowercase_user, lowercase_ngname;
+       fstring lowercase_user;
 
        if (mydomain == NULL)
                yp_get_default_domain(&mydomain);
@@ -318,25 +318,28 @@ static BOOL user_in_netgroup_list(const char *user, const char *ngname)
 
        DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
                user, mydomain, ngname));
-       DEBUG(5,("innetgr is %s\n", innetgr(ngname, NULL, user, mydomain)
-               ? "TRUE" : "FALSE"));
 
-       if (innetgr(ngname, NULL, user, mydomain))
+       if (innetgr(ngname, NULL, user, mydomain)) {
+               DEBUG(5,("user_in_netgroup_list: Found\n"));
                return (True);
+       } else {
 
-       /*
-        * Ok, innetgr is case sensitive. Try once more with lowercase
-        * just in case. Attempt to fix #703. JRA.
-        */
+               /*
+                * Ok, innetgr is case sensitive. Try once more with lowercase
+                * just in case. Attempt to fix #703. JRA.
+                */
 
-       fstrcpy(lowercase_user, user);
-       strlower_m(lowercase_user);
-       fstrcpy(lowercase_ngname, ngname);
-       strlower_m(lowercase_ngname);
+               fstrcpy(lowercase_user, user);
+               strlower_m(lowercase_user);
        
-       if (innetgr(lowercase_ngname, NULL, lowercase_user, mydomain))
-               return (True);
+               DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
+                       lowercase_user, mydomain, ngname));
 
+               if (innetgr(ngname, NULL, lowercase_user, mydomain)) {
+                       DEBUG(5,("user_in_netgroup_list: Found\n"));
+                       return (True);
+               }
+       }
 #endif /* HAVE_NETGROUP */
        return False;
 }
index 9d7a2648c5b603874c4128d9c044a5dc9a4bb82f..554f5ee79da30f7ac164dd8f2c74fb1667eaa476 100644 (file)
@@ -1802,6 +1802,9 @@ void set_remote_arch(enum remote_arch_types type)
        case RA_SAMBA:
                fstrcpy(remote_arch,"Samba");
                break;
+       case RA_CIFSFS:
+               fstrcpy(remote_arch,"CIFSFS");
+               break;
        default:
                ra_type = RA_UNKNOWN;
                fstrcpy(remote_arch, "UNKNOWN");
@@ -2432,6 +2435,21 @@ BOOL unix_wild_match(const char *pattern, const char *string)
        return unix_do_match(p2, s2) == 0;      
 }
 
+/**********************************************************************
+ Converts a name to a fully qalified domain name.
+***********************************************************************/
+                                                                                                                                                   
+void name_to_fqdn(fstring fqdn, const char *name)
+{
+       struct hostent *hp = sys_gethostbyname(name);
+       if ( hp && hp->h_name && *hp->h_name ) {
+               DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, hp->h_name));
+               fstrcpy(fqdn,hp->h_name);
+       } else {
+               DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
+               fstrcpy(fqdn, name);
+       }
+}
 
 #ifdef __INSURE__
 
index b6bfdca5cf9fd5d574a7ba6d9a02a8d38ffba485..4b9881a4499bf478e9b4bd0122844afa2dae6f81 100644 (file)
@@ -52,6 +52,23 @@ static char *get_socket_addr(int fd)
        return addr_buf;
 }
 
+static int get_socket_port(int fd)
+{
+       struct sockaddr sa;
+       struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
+       socklen_t length = sizeof(sa);
+
+       if (fd == -1)
+               return -1;
+       
+       if (getsockname(fd, &sa, &length) < 0) {
+               DEBUG(0,("getpeername failed. Error was %s\n", strerror(errno) ));
+               return -1;
+       }
+       
+       return ntohs(sockin->sin_port);
+}
+
 /****************************************************************************
  Determine if a file descriptor is in fact a socket.
 ****************************************************************************/
@@ -837,6 +854,11 @@ char *client_socket_addr(void)
        return get_socket_addr(client_fd);
 }
 
+int client_socket_port(void)
+{
+       return get_socket_port(client_fd);
+}
+
 struct in_addr *client_inaddr(struct sockaddr *sa)
 {
        struct sockaddr_in *sockin = (struct sockaddr_in *) (sa);
index 65ef306ed1799713aefb94e73bca386077809b32..7c5fa11c92d6453e203354b1c6d9ea03aa65fbde 100644 (file)
@@ -62,7 +62,7 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
        /* copy over the token */
        pbuf = buff;
        for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
-               if (*s == '\"' || *s == '\'') {
+               if ( *s == '\"' ) {
                        quoted = !quoted;
                } else {
                        len++;
index e8bf4b08462484dadd7cbedb0630361e0b8a2c65..97b895a2418a976b272512da720c528c2e3beacb 100644 (file)
@@ -79,9 +79,9 @@ int kerberos_kinit_password(const char *principal, const char *password, int tim
                return code;
        }
        
-       if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, NULL
+       if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, password
                                                 kerb_prompter, 
-                                                password, 0, NULL, NULL))) {
+                                                NULL, 0, NULL, NULL))) {
                krb5_free_principal(ctx, me);
                krb5_free_context(ctx);         
                return code;
diff --git a/source/libads/kerberos_keytab.c b/source/libads/kerberos_keytab.c
new file mode 100644 (file)
index 0000000..eec5f10
--- /dev/null
@@ -0,0 +1,554 @@
+/*
+   Unix SMB/CIFS implementation.
+   kerberos keytab utility library
+   Copyright (C) Andrew Tridgell 2001
+   Copyright (C) Remus Koos 2001
+   Copyright (C) Luke Howard 2003
+   Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003
+   Copyright (C) Guenther Deschner 2003
+   Copyright (C) Rakesh Patel 2004
+   Copyright (C) Dan Perry 2004
+   Copyright (C) Jeremy Allison 2004
+
+   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
+
+/**********************************************************************
+ Adds a single service principal, i.e. 'host' to the system keytab
+***********************************************************************/
+
+int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc)
+{
+       krb5_error_code ret = 0;
+       krb5_context context = NULL;
+       krb5_keytab keytab = NULL;
+       krb5_kt_cursor cursor;
+       krb5_keytab_entry kt_entry;
+       krb5_principal princ = NULL;
+       krb5_data password;
+       krb5_enctype *enctypes = NULL;
+       krb5_kvno kvno;
+
+       char *principal = NULL;
+       char *princ_s = NULL;
+       char *password_s = NULL;
+#ifndef MAX_KEYTAB_NAME_LEN
+#define MAX_KEYTAB_NAME_LEN 1100
+#endif
+       char keytab_name[MAX_KEYTAB_NAME_LEN];          /* This MAX_NAME_LEN is a constant defined in krb5.h */
+       fstring my_fqdn;
+       int i;
+       char *ktprinc = NULL;
+
+       ZERO_STRUCT(kt_entry);
+       ZERO_STRUCT(cursor);
+
+       initialize_krb5_error_table();
+       ret = krb5_init_context(&context);
+       if (ret) {
+               DEBUG(1,("ads_keytab_add_entry: could not krb5_init_context: %s\n",error_message(ret)));
+               return -1;
+       }
+#ifdef HAVE_WRFILE_KEYTAB       /* MIT */
+       keytab_name[0] = 'W';
+       keytab_name[1] = 'R';
+       ret = krb5_kt_default_name(context, (char *) &keytab_name[2], MAX_KEYTAB_NAME_LEN - 4);
+#else                           /* Heimdal */
+       ret = krb5_kt_default_name(context, (char *) &keytab_name[0], MAX_KEYTAB_NAME_LEN - 2);
+#endif
+       if (ret) {
+               DEBUG(1,("ads_keytab_add_entry: krb5_kt_default_name failed (%s)\n", error_message(ret)));
+               goto out;
+       }
+       DEBUG(2,("ads_keytab_add_entry: Using default system keytab: %s\n", (char *) &keytab_name));
+       ret = krb5_kt_resolve(context, (char *) &keytab_name, &keytab);
+       if (ret) {
+               DEBUG(1,("ads_keytab_add_entry: krb5_kt_resolve failed (%s)\n", error_message(ret)));
+               goto out;
+       }
+
+       /* retrieve the password */
+       if (!secrets_init()) {
+               DEBUG(1,("ads_keytab_add_entry: secrets_init failed\n"));
+               ret = -1;
+               goto out;
+       }
+       password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
+       if (!password_s) {
+               DEBUG(1,("ads_keytab_add_entry: failed to fetch machine password\n"));
+               ret = -1;
+               goto out;
+       }
+       password.data = password_s;
+       password.length = strlen(password_s);
+
+       /* Construct our principal */
+       name_to_fqdn(my_fqdn, global_myname());
+       strlower_m(my_fqdn);
+       asprintf(&princ_s, "%s/%s@%s", srvPrinc, my_fqdn, lp_realm());
+
+       ret = krb5_parse_name(context, princ_s, &princ);
+       if (ret) {
+               DEBUG(1,("ads_keytab_add_entry: krb5_parse_name(%s) failed (%s)\n", princ_s, error_message(ret)));
+               goto out;
+       }
+
+       kvno = (krb5_kvno) ads_get_kvno(ads, global_myname());
+       if (kvno == -1) {       /* -1 indicates failure, everything else is OK */
+               DEBUG(1,("ads_keytab_add_entry: ads_get_kvno failed to determine the system's kvno.\n"));
+               ret = -1;
+               goto out;
+       }
+
+       /* Seek and delete old keytab entries */
+       ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+       if (ret != KRB5_KT_END && ret != ENOENT ) {
+               DEBUG(3,("ads_keytab_add_entry: Will try to delete old keytab entries\n"));
+               while(!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) {
+                       BOOL compare_ok = False;
+
+                       ret = krb5_unparse_name(context, kt_entry.principal, &ktprinc);
+                       if (ret) {
+                               DEBUG(1,("ads_keytab_add_entry: krb5_unparse_name failed (%s)\n", error_message(ret)));
+                               goto out;
+                       }
+
+                       /*---------------------------------------------------------------------------
+                        * Save the entries with kvno - 1.   This is what microsoft does
+                        * to allow people with existing sessions that have kvno - 1 to still
+                        * work.   Otherwise, when the password for the machine changes, all
+                        * kerberizied sessions will 'break' until either the client reboots or
+                        * the client's session key expires and they get a new session ticket
+                        * with the new kvno.
+                        */
+
+#ifdef HAVE_KRB5_KT_COMPARE
+                       compare_ok = ((krb5_kt_compare(context, &kt_entry, princ, 0, 0) == True) && (kt_entry.vno != kvno - 1));
+#else
+                       compare_ok = ((strcmp(ktprinc, princ_s) == 0) && (kt_entry.vno != kvno - 1));
+#endif
+                       krb5_free_unparsed_name(context, ktprinc);
+                       ktprinc = NULL;
+
+                       if (compare_ok) {
+                               DEBUG(3,("ads_keytab_add_entry: Found old entry for principal: %s (kvno %d) - trying to remove it.\n",
+                                       princ_s, kt_entry.vno));
+                               ret = krb5_kt_end_seq_get(context, keytab, &cursor);
+                               ZERO_STRUCT(cursor);
+                               if (ret) {
+                                       DEBUG(1,("ads_keytab_add_entry: krb5_kt_end_seq_get() failed (%s)\n",
+                                               error_message(ret)));
+                                       goto out;
+                               }
+                               ret = krb5_kt_remove_entry(context, keytab, &kt_entry);
+                               if (ret) {
+                                       DEBUG(1,("ads_keytab_add_entry: krb5_kt_remove_entry failed (%s)\n",
+                                               error_message(ret)));
+                                       goto out;
+                               }
+                               ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+                               if (ret) {
+                                       DEBUG(1,("ads_keytab_add_entry: krb5_kt_start_seq failed (%s)\n",
+                                               error_message(ret)));
+                                       goto out;
+                               }
+                               ret = smb_krb5_kt_free_entry(context, &kt_entry);
+                               ZERO_STRUCT(kt_entry);
+                               if (ret) {
+                                       DEBUG(1,("ads_keytab_add_entry: krb5_kt_remove_entry failed (%s)\n",
+                                               error_message(ret)));
+                                       goto out;
+                               }
+                               continue;
+                       }
+
+                       /* Not a match, just free this entry and continue. */
+                       ret = smb_krb5_kt_free_entry(context, &kt_entry);
+                       ZERO_STRUCT(kt_entry);
+                       if (ret) {
+                               DEBUG(1,("ads_keytab_add_entry: smb_krb5_kt_free_entry failed (%s)\n", error_message(ret)));
+                               goto out;
+                       }
+               }
+
+               ret = krb5_kt_end_seq_get(context, keytab, &cursor);
+               ZERO_STRUCT(cursor);
+               if (ret) {
+                       DEBUG(1,("ads_keytab_add_entry: krb5_kt_end_seq_get failed (%s)\n",error_message(ret)));
+                       goto out;
+               }
+       }
+
+       /* Ensure we don't double free. */
+       ZERO_STRUCT(kt_entry);
+       ZERO_STRUCT(cursor);
+
+       /* If we get here, we have deleted all the old entries with kvno's not equal to the current kvno-1. */
+
+       ret = get_kerberos_allowed_etypes(context,&enctypes);
+       if (ret) {
+               DEBUG(1,("ads_keytab_add_entry: get_kerberos_allowed_etypes failed (%s)\n",error_message(ret)));
+               goto out;
+       }
+
+       /* Now add keytab entries for all encryption types */
+       for (i = 0; enctypes[i]; i++) {
+               krb5_keyblock *keyp;
+
+#if !defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) && !defined(HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK)
+#error krb5_keytab_entry has no key or keyblock member
+#endif
+#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEY               /* MIT */
+               keyp = &kt_entry.key;
+#endif
+#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK          /* Heimdal */
+               keyp = &kt_entry.keyblock;
+#endif
+               if (create_kerberos_key_from_string(context, princ, &password, keyp, enctypes[i])) {
+                       continue;
+               }
+
+               kt_entry.principal = princ;
+               kt_entry.vno       = kvno;
+
+               DEBUG(3,("ads_keytab_add_entry: adding keytab entry for (%s) with encryption type (%d) and version (%d)\n",
+                       princ_s, enctypes[i], kt_entry.vno));
+               ret = krb5_kt_add_entry(context, keytab, &kt_entry);
+               krb5_free_keyblock_contents(context, keyp);
+               ZERO_STRUCT(kt_entry);
+               if (ret) {
+                       DEBUG(1,("ads_keytab_add_entry: adding entry to keytab failed (%s)\n", error_message(ret)));
+                       goto out;
+               }
+       }
+
+       krb5_kt_close(context, keytab);
+       keytab = NULL; /* Done with keytab now. No double free. */
+
+       /* Update the LDAP with the SPN */
+       DEBUG(3,("ads_keytab_add_entry: Attempting to add/update '%s'\n", princ_s));
+       if (!ADS_ERR_OK(ads_add_service_principal_name(ads, global_myname(), srvPrinc))) {
+               DEBUG(1,("ads_keytab_add_entry: ads_add_service_principcal_name failed.\n"));
+               goto out;
+       }
+
+out:
+
+       SAFE_FREE(principal);
+       SAFE_FREE(password_s);
+       SAFE_FREE(princ_s);
+
+       {
+               krb5_keytab_entry zero_kt_entry;
+               ZERO_STRUCT(zero_kt_entry);
+               if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) {
+                       smb_krb5_kt_free_entry(context, &kt_entry);
+               }
+       }
+       if (princ) {
+               krb5_free_principal(context, princ);
+       }
+       if (enctypes) {
+               free_kerberos_etypes(context, enctypes);
+       }
+
+       {
+               krb5_kt_cursor zero_csr;
+               ZERO_STRUCT(zero_csr);
+               if ((memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) {
+                       krb5_kt_end_seq_get(context, keytab, &cursor);  
+               }
+       }
+       if (keytab) {
+               krb5_kt_close(context, keytab);
+       }
+       if (context) {
+               krb5_free_context(context);
+       }
+       return (int)ret;
+}
+
+/**********************************************************************
+ Flushes all entries from the system keytab.
+***********************************************************************/
+
+int ads_keytab_flush(ADS_STRUCT *ads)
+{
+       krb5_error_code ret = 0;
+       krb5_context context = NULL;
+       krb5_keytab keytab = NULL;
+       krb5_kt_cursor cursor;
+       krb5_keytab_entry kt_entry;
+       krb5_kvno kvno;
+       char keytab_name[MAX_KEYTAB_NAME_LEN];
+
+       ZERO_STRUCT(kt_entry);
+       ZERO_STRUCT(cursor);
+
+       initialize_krb5_error_table();
+       ret = krb5_init_context(&context);
+       if (ret) {
+               DEBUG(1,("ads_keytab_flush: could not krb5_init_context: %s\n",error_message(ret)));
+               return ret;
+       }
+#ifdef HAVE_WRFILE_KEYTAB
+       keytab_name[0] = 'W';
+       keytab_name[1] = 'R';
+       ret = krb5_kt_default_name(context, (char *) &keytab_name[2], MAX_KEYTAB_NAME_LEN - 4);
+#else
+       ret = krb5_kt_default_name(context, (char *) &keytab_name[0], MAX_KEYTAB_NAME_LEN - 2);
+#endif
+       if (ret) {
+               DEBUG(1,("ads_keytab_flush: krb5_kt_default failed (%s)\n", error_message(ret)));
+               goto out;
+       }
+       DEBUG(3,("ads_keytab_flush: Using default keytab: %s\n", (char *) &keytab_name));
+       ret = krb5_kt_resolve(context, (char *) &keytab_name, &keytab);
+       if (ret) {
+               DEBUG(1,("ads_keytab_flush: krb5_kt_default failed (%s)\n", error_message(ret)));
+               goto out;
+       }
+       ret = krb5_kt_resolve(context, (char *) &keytab_name, &keytab);
+       if (ret) {
+               DEBUG(1,("ads_keytab_flush: krb5_kt_default failed (%s)\n", error_message(ret)));
+               goto out;
+       }
+
+       kvno = (krb5_kvno) ads_get_kvno(ads, global_myname());
+       if (kvno == -1) {       /* -1 indicates a failure */
+               DEBUG(1,("ads_keytab_flush: Error determining the system's kvno.\n"));
+               goto out;
+       }
+
+       ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+       if (ret != KRB5_KT_END && ret != ENOENT) {
+               while (!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) {
+                       ret = krb5_kt_end_seq_get(context, keytab, &cursor);
+                       ZERO_STRUCT(cursor);
+                       if (ret) {
+                               DEBUG(1,("ads_keytab_flush: krb5_kt_end_seq_get() failed (%s)\n",error_message(ret)));
+                               goto out;
+                       }
+                       ret = krb5_kt_remove_entry(context, keytab, &kt_entry);
+                       if (ret) {
+                               DEBUG(1,("ads_keytab_flush: krb5_kt_remove_entry failed (%s)\n",error_message(ret)));
+                               goto out;
+                       }
+                       ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+                       if (ret) {
+                               DEBUG(1,("ads_keytab_flush: krb5_kt_start_seq failed (%s)\n",error_message(ret)));
+                               goto out;
+                       }
+                       ret = smb_krb5_kt_free_entry(context, &kt_entry);
+                       ZERO_STRUCT(kt_entry);
+                       if (ret) {
+                               DEBUG(1,("ads_keytab_flush: krb5_kt_remove_entry failed (%s)\n",error_message(ret)));
+                               goto out;
+                       }
+               }
+       }
+
+       /* Ensure we don't double free. */
+       ZERO_STRUCT(kt_entry);
+       ZERO_STRUCT(cursor);
+
+       if (!ADS_ERR_OK(ads_clear_service_principal_names(ads, global_myname()))) {
+               DEBUG(1,("ads_keytab_flush: Error while clearing service principal listings in LDAP.\n"));
+               goto out;
+       }
+
+out:
+
+       {
+               krb5_keytab_entry zero_kt_entry;
+               ZERO_STRUCT(zero_kt_entry);
+               if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) {
+                       smb_krb5_kt_free_entry(context, &kt_entry);
+               }
+       }
+       {
+               krb5_kt_cursor zero_csr;
+               ZERO_STRUCT(zero_csr);
+               if ((memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) {
+                       krb5_kt_end_seq_get(context, keytab, &cursor);  
+               }
+       }
+       if (keytab) {
+               krb5_kt_close(context, keytab);
+       }
+       if (context) {
+               krb5_free_context(context);
+       }
+       return ret;
+}
+
+/**********************************************************************
+ Adds all the required service principals to the system keytab.
+***********************************************************************/
+
+int ads_keytab_create_default(ADS_STRUCT *ads)
+{
+       krb5_error_code ret = 0;
+       krb5_context context = NULL;
+       krb5_keytab keytab = NULL;
+       krb5_kt_cursor cursor;
+       krb5_keytab_entry kt_entry;
+       krb5_kvno kvno;
+       int i, found = 0;
+       char **oldEntries = NULL;
+
+       ret = ads_keytab_add_entry(ads, "host");
+       if (ret) {
+               DEBUG(1,("ads_keytab_create_default: ads_keytab_add_entry failed while adding 'host'.\n"));
+               return ret;
+       }
+       ret = ads_keytab_add_entry(ads, "cifs");
+       if (ret) {
+               DEBUG(1,("ads_keytab_create_default: ads_keytab_add_entry failed while adding 'cifs'.\n"));
+               return ret;
+       }
+
+       kvno = (krb5_kvno) ads_get_kvno(ads, global_myname());
+       if (kvno == -1) {
+               DEBUG(1,("ads_keytab_create_default: ads_get_kvno failed to determine the system's kvno.\n"));
+               return -1;
+       }
+
+       DEBUG(3,("ads_keytab_create_default: Searching for keytab entries to preserve and update.\n"));
+       /* Now loop through the keytab and update any other existing entries... */
+
+       ZERO_STRUCT(kt_entry);
+       ZERO_STRUCT(cursor);
+
+       initialize_krb5_error_table();
+       ret = krb5_init_context(&context);
+       if (ret) {
+               DEBUG(1,("ads_keytab_create_default: could not krb5_init_context: %s\n",error_message(ret)));
+               return ret;
+       }
+       ret = krb5_kt_default(context, &keytab);
+       if (ret) {
+               DEBUG(1,("ads_keytab_create_default: krb5_kt_default failed (%s)\n",error_message(ret)));
+               goto done;
+       }
+
+       ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+       if (ret != KRB5_KT_END && ret != ENOENT ) {
+               while ((ret = krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) == 0) {
+                       smb_krb5_kt_free_entry(context, &kt_entry);
+                       ZERO_STRUCT(kt_entry);
+                       found++;
+               }
+       }
+       krb5_kt_end_seq_get(context, keytab, &cursor);
+       ZERO_STRUCT(cursor);
+
+       /*
+        * Hmmm. There is no "rewind" function for the keytab. This means we have a race condition
+        * where someone else could add entries after we've counted them. Re-open asap to minimise
+        * the race. JRA.
+        */
+       
+       DEBUG(3, ("ads_keytab_create_default: Found %d entries in the keytab.\n", found));
+       if (!found) {
+               goto done;
+       }
+       oldEntries = (char **) malloc(found * sizeof(char *));
+       if (!oldEntries) {
+               DEBUG(1,("ads_keytab_create_default: Failed to allocate space to store the old keytab entries (malloc failed?).\n"));
+               ret = -1;
+               goto done;
+       }
+       memset(oldEntries, '\0', found * sizeof(char *));
+
+       ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+       if (ret != KRB5_KT_END && ret != ENOENT ) {
+               while (krb5_kt_next_entry(context, keytab, &kt_entry, &cursor) == 0) {
+                       if (kt_entry.vno != kvno) {
+                               char *ktprinc = NULL;
+                               char *p;
+
+                               /* This returns a malloc'ed string in ktprinc. */
+                               ret = krb5_unparse_name(context, kt_entry.principal, &ktprinc);
+                               if (ret) {
+                                       DEBUG(1,("krb5_unparse_name failed (%s)\n", error_message(ret)));
+                                       goto done;
+                               }
+                               /*
+                                * From looking at the krb5 source they don't seem to take locale
+                                * or mb strings into account. Maybe this is because they assume utf8 ?
+                                * In this case we may need to convert from utf8 to mb charset here ? JRA.
+                                */
+                               p = strchr_m(ktprinc, '/');
+                               if (p) {
+                                       *p = '\0';
+                               }
+                               for (i = 0; i < found; i++) {
+                                       if (!oldEntries[i]) {
+                                               oldEntries[i] = ktprinc;
+                                               break;
+                                       }
+                                       if (!strcmp(oldEntries[i], ktprinc)) {
+                                               krb5_free_unparsed_name(context, ktprinc);
+                                               break;
+                                       }
+                               }
+                               if (i == found) {
+                                       krb5_free_unparsed_name(context, ktprinc);
+                               }
+                       }
+                       smb_krb5_kt_free_entry(context, &kt_entry);
+                       ZERO_STRUCT(kt_entry);
+               }
+               ret = 0;
+               for (i = 0; oldEntries[i]; i++) {
+                       ret |= ads_keytab_add_entry(ads, oldEntries[i]);
+                       krb5_free_unparsed_name(context, oldEntries[i]);
+               }
+               krb5_kt_end_seq_get(context, keytab, &cursor);
+       }
+       ZERO_STRUCT(cursor);
+
+done:
+
+       SAFE_FREE(oldEntries);
+
+       {
+               krb5_keytab_entry zero_kt_entry;
+               ZERO_STRUCT(zero_kt_entry);
+               if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) {
+                       smb_krb5_kt_free_entry(context, &kt_entry);
+               }
+       }
+       {
+               krb5_kt_cursor zero_csr;
+               ZERO_STRUCT(zero_csr);
+               if ((memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) {
+                       krb5_kt_end_seq_get(context, keytab, &cursor);  
+               }
+       }
+       if (keytab) {
+               krb5_kt_close(context, keytab);
+       }
+       if (context) {
+               krb5_free_context(context);
+       }
+       return ret;
+}
+#endif /* HAVE_KRB5 */
index 47559c1abb70c4c77ac93536b6c6ac16b0933695..bdac22a90224e4a49452205ee9e45547d8174519 100644 (file)
 
 #ifdef HAVE_KRB5
 
-/*
-  verify an incoming ticket and parse out the principal name and 
-  authorization_data if available 
-*/
+/**********************************************************************************
+ Try to verify a ticket using the system keytab... the system keytab has kvno -1 entries, so
+ it's more like what microsoft does... see comment in utils/net_ads.c in the
+ ads_keytab_add_entry function for details.
+***********************************************************************************/
+
+static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context auth_context,
+                       const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt)
+{
+       krb5_error_code ret = 0;
+       BOOL auth_ok = False;
+
+       krb5_keytab keytab = NULL;
+       krb5_kt_cursor cursor;
+       krb5_keytab_entry kt_entry;
+       char *princ_name = NULL;
+
+       ZERO_STRUCT(kt_entry);
+       ZERO_STRUCT(cursor);
+
+       ret = krb5_kt_default(context, &keytab);
+       if (ret) {
+               DEBUG(1, ("ads_keytab_verify_ticket: krb5_kt_default failed (%s)\n", error_message(ret)));
+               goto out;
+       }
+
+       ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+       if (ret) {
+               DEBUG(1, ("ads_keytab_verify_ticket: krb5_kt_start_seq_get failed (%s)\n", error_message(ret)));
+               goto out;
+       }
+
+       while (!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) {
+               ret = krb5_unparse_name(context, kt_entry.principal, &princ_name);
+               if (ret) {
+                       DEBUG(1, ("ads_keytab_verify_ticket: krb5_unparse_name failed (%s)\n", error_message(ret)));
+                       goto out;
+               }
+               /* Look for a CIFS ticket */
+               if (!StrnCaseCmp(princ_name, "cifs/", 5)) {
+#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK
+                       krb5_auth_con_setuseruserkey(context, auth_context, &kt_entry.keyblock);
+#else
+                       krb5_auth_con_setuseruserkey(context, auth_context, &kt_entry.key);
+#endif
+
+                       p_packet->length = ticket->length;
+                       p_packet->data = (krb5_pointer)ticket->data;
+
+                       if (!(ret = krb5_rd_req(context, &auth_context, p_packet, NULL, NULL, NULL, pp_tkt))) {
+                               unsigned int keytype;
+                               krb5_free_unparsed_name(context, princ_name);
+                               princ_name = NULL;
+#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK
+                               keytype = (unsigned int) kt_entry.keyblock.keytype;
+#else
+                               keytype = (unsigned int) kt_entry.key.enctype;
+#endif
+                               DEBUG(10,("ads_keytab_verify_ticket: enc type [%u] decrypted message !\n",
+                                         keytype));
+                               auth_ok = True;
+                               break;
+                       }
+               }
+               krb5_free_unparsed_name(context, princ_name);
+               princ_name = NULL;
+       }
+       if (ret && ret != KRB5_KT_END) {
+               /* This failed because something went wrong, not because the keytab file was empty. */
+               DEBUG(1, ("ads_keytab_verify_ticket: krb5_kt_next_entry failed (%s)\n", error_message(ret)));
+               goto out;
+       }
+
+  out:
+
+       if (princ_name) {
+               krb5_free_unparsed_name(context, princ_name);
+       }
+       {
+               krb5_kt_cursor zero_csr;
+               ZERO_STRUCT(zero_csr);
+               if ((memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) {
+                       krb5_kt_end_seq_get(context, keytab, &cursor);
+               }
+       }
+       if (keytab) {
+               krb5_kt_close(context, keytab);
+       }
+
+       return auth_ok;
+}
+
+/**********************************************************************************
+ Try to verify a ticket using the secrets.tdb.
+***********************************************************************************/
+
+static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context auth_context,
+                       krb5_principal host_princ,
+                       const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt)
+{
+       krb5_error_code ret = 0;
+       BOOL auth_ok = False;
+       char *password_s = NULL;
+       krb5_data password;
+       krb5_enctype *enctypes = NULL;
+       int i;
+
+       if (!secrets_init()) {
+               DEBUG(1,("ads_secrets_verify_ticket: secrets_init failed\n"));
+               return False;
+       }
+
+       password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
+       if (!password_s) {
+               DEBUG(1,("ads_secrets_verify_ticket: failed to fetch machine password\n"));
+               return False;
+       }
+
+       password.data = password_s;
+       password.length = strlen(password_s);
+
+       /* CIFS doesn't use addresses in tickets. This would break NAT. JRA */
+
+       if ((ret = get_kerberos_allowed_etypes(context, &enctypes))) {
+               DEBUG(1,("ads_secrets_verify_ticket: krb5_get_permitted_enctypes failed (%s)\n", 
+                        error_message(ret)));
+               goto out;
+       }
+
+       p_packet->length = ticket->length;
+       p_packet->data = (krb5_pointer)ticket->data;
+
+       /* We need to setup a auth context with each possible encoding type in turn. */
+       for (i=0;enctypes[i];i++) {
+               krb5_keyblock *key = NULL;
+
+               if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) {
+                       goto out;
+               }
+       
+               if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i])) {
+                       SAFE_FREE(key);
+                       continue;
+               }
+
+               krb5_auth_con_setuseruserkey(context, auth_context, key);
+
+               krb5_free_keyblock(context, key);
+
+               if (!(ret = krb5_rd_req(context, &auth_context, p_packet, 
+                                       NULL,
+                                       NULL, NULL, pp_tkt))) {
+                       DEBUG(10,("ads_secrets_verify_ticket: enc type [%u] decrypted message !\n",
+                               (unsigned int)enctypes[i] ));
+                       auth_ok = True;
+                       break;
+               }
+       
+               DEBUG((ret != KRB5_BAD_ENCTYPE) ? 3 : 10,
+                               ("ads_secrets_verify_ticket: enc type [%u] failed to decrypt with error %s\n",
+                               (unsigned int)enctypes[i], error_message(ret)));
+       }
+
+ out:
+
+       free_kerberos_etypes(context, enctypes);
+       SAFE_FREE(password_s);
+
+       return auth_ok;
+}
+
+/**********************************************************************************
+ Verify an incoming ticket and parse out the principal name and 
+ authorization_data if available.
+***********************************************************************************/
+
 NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket, 
                           char **principal, DATA_BLOB *auth_data,
                           DATA_BLOB *ap_rep,
@@ -41,43 +213,21 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        krb5_data packet;
        krb5_ticket *tkt = NULL;
        krb5_rcache rcache = NULL;
-       int ret, i;
-       krb5_keyblock *key = NULL;
+       int ret;
 
-       krb5_principal host_princ;
+       krb5_principal host_princ = NULL;
        char *host_princ_s = NULL;
-       BOOL free_host_princ = False;
        BOOL got_replay_mutex = False;
 
        fstring myname;
-       char *password_s = NULL;
-       krb5_data password;
-       krb5_enctype *enctypes = NULL;
-#if 0
-       krb5_address local_addr;
-       krb5_address remote_addr;
-#endif
        BOOL auth_ok = False;
 
        ZERO_STRUCT(packet);
-       ZERO_STRUCT(password);
        ZERO_STRUCTP(auth_data);
        ZERO_STRUCTP(ap_rep);
+       ZERO_STRUCTP(session_key);
 
-       if (!secrets_init()) {
-               DEBUG(1,("ads_verify_ticket: secrets_init failed\n"));
-               return NT_STATUS_LOGON_FAILURE;
-       }
-
-       password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
-       if (!password_s) {
-               DEBUG(1,("ads_verify_ticket: failed to fetch machine password\n"));
-               return NT_STATUS_LOGON_FAILURE;
-       }
-
-       password.data = password_s;
-       password.length = strlen(password_s);
-
+       initialize_krb5_error_table();
        ret = krb5_init_context(&context);
        if (ret) {
                DEBUG(1,("ads_verify_ticket: krb5_init_context failed (%s)\n", error_message(ret)));
@@ -87,7 +237,6 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        ret = krb5_set_default_realm(context, realm);
        if (ret) {
                DEBUG(1,("ads_verify_ticket: krb5_set_default_realm failed (%s)\n", error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
                goto out;
        }
 
@@ -98,22 +247,29 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        ret = krb5_auth_con_init(context, &auth_context);
        if (ret) {
                DEBUG(1,("ads_verify_ticket: krb5_auth_con_init failed (%s)\n", error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
                goto out;
        }
 
-       fstrcpy(myname, global_myname());
+       name_to_fqdn(myname, global_myname());
        strlower_m(myname);
-       asprintf(&host_princ_s, "HOST/%s@%s", myname, lp_realm());
+       asprintf(&host_princ_s, "host/%s@%s", myname, lp_realm());
        ret = krb5_parse_name(context, host_princ_s, &host_princ);
        if (ret) {
                DEBUG(1,("ads_verify_ticket: krb5_parse_name(%s) failed (%s)\n",
                                        host_princ_s, error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
                goto out;
        }
 
-       free_host_princ = True;
+
+       /* Lock a mutex surrounding the replay as there is no locking in the MIT krb5
+        * code surrounding the replay cache... */
+
+       if (!grab_server_mutex("replay cache mutex")) {
+               DEBUG(1,("ads_verify_ticket: unable to protect replay cache with mutex.\n"));
+               goto out;
+       }
+
+       got_replay_mutex = True;
 
        /*
         * JRA. We must set the rcache here. This will prevent replay attacks.
@@ -122,67 +278,21 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        ret = krb5_get_server_rcache(context, krb5_princ_component(context, host_princ, 0), &rcache);
        if (ret) {
                DEBUG(1,("ads_verify_ticket: krb5_get_server_rcache failed (%s)\n", error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
                goto out;
        }
 
        ret = krb5_auth_con_setrcache(context, auth_context, rcache);
        if (ret) {
                DEBUG(1,("ads_verify_ticket: krb5_auth_con_setrcache failed (%s)\n", error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
                goto out;
        }
 
-       /* CIFS doesn't use addresses in tickets. This would breat NAT. JRA */
-
-       if ((ret = get_kerberos_allowed_etypes(context, &enctypes))) {
-               DEBUG(1,("ads_verify_ticket: krb5_get_permitted_enctypes failed (%s)\n", 
-                        error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
-               goto out;
+       if (lp_use_kerberos_keytab()) {
+               auth_ok = ads_keytab_verify_ticket(context, auth_context, ticket, &packet, &tkt);
        }
-
-       /* Lock a mutex surrounding the replay as there is no locking in the MIT krb5
-        * code surrounding the replay cache... */
-
-       if (!grab_server_mutex("replay cache mutex")) {
-               DEBUG(1,("ads_verify_ticket: unable to protect replay cache with mutex.\n"));
-               sret = NT_STATUS_LOGON_FAILURE;
-               goto out;
-       }
-
-       got_replay_mutex = True;
-
-       /* We need to setup a auth context with each possible encoding type in turn. */
-       for (i=0;enctypes[i];i++) {
-               if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) {
-                       sret = NT_STATUS_NO_MEMORY;
-                       goto out;
-               }
-       
-               if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i])) {
-                       continue;
-               }
-
-               krb5_auth_con_setuseruserkey(context, auth_context, key);
-
-               krb5_free_keyblock(context, key);
-
-               packet.length = ticket->length;
-               packet.data = (krb5_pointer)ticket->data;
-
-               if (!(ret = krb5_rd_req(context, &auth_context, &packet, 
-                                       NULL,
-                                       NULL, NULL, &tkt))) {
-                       DEBUG(10,("ads_verify_ticket: enc type [%u] decrypted message !\n",
-                               (unsigned int)enctypes[i] ));
-                       auth_ok = True;
-                       break;
-               }
-       
-               DEBUG((ret != KRB5_BAD_ENCTYPE) ? 3 : 10,
-                               ("ads_verify_ticket: enc type [%u] failed to decrypt with error %s\n",
-                               (unsigned int)enctypes[i], error_message(ret)));
+       if (!auth_ok) {
+               auth_ok = ads_secrets_verify_ticket(context, auth_context, host_princ,
+                                                       ticket, &packet, &tkt);
        }
 
        release_server_mutex();
@@ -191,7 +301,6 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        if (!auth_ok) {
                DEBUG(3,("ads_verify_ticket: krb5_rd_req with auth failed (%s)\n", 
                         error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
                goto out;
        }
 
@@ -199,12 +308,12 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        if (ret) {
                DEBUG(3,("ads_verify_ticket: Failed to generate mutual authentication reply (%s)\n",
                        error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
                goto out;
        }
 
        *ap_rep = data_blob(packet.data, packet.length);
-       free(packet.data);
+       SAFE_FREE(packet.data);
+       packet.length = 0;
 
        get_krb5_smb_session_key(context, auth_context, session_key, True);
        dump_data_pw("SMB session key (from ticket)\n", session_key->data, session_key->length);
@@ -241,29 +350,35 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
 
  out:
 
-       if (got_replay_mutex)
+       if (got_replay_mutex) {
                release_server_mutex();
+       }
 
-       if (!NT_STATUS_IS_OK(sret))
+       if (!NT_STATUS_IS_OK(sret)) {
                data_blob_free(auth_data);
+       }
 
-       if (!NT_STATUS_IS_OK(sret))
+       if (!NT_STATUS_IS_OK(sret)) {
                data_blob_free(ap_rep);
+       }
 
-       if (free_host_princ)
+       if (host_princ) {
                krb5_free_principal(context, host_princ);
+       }
 
-       if (tkt != NULL)
+       if (tkt != NULL) {
                krb5_free_ticket(context, tkt);
-       free_kerberos_etypes(context, enctypes);
-       SAFE_FREE(password_s);
+       }
+
        SAFE_FREE(host_princ_s);
 
-       if (auth_context)
+       if (auth_context) {
                krb5_auth_con_free(context, auth_context);
+       }
 
-       if (context)
+       if (context) {
                krb5_free_context(context);
+       }
 
        return sret;
 }
index 5c859f0e9952325ef33a71ab22ed5bf16fe7f58e..84595212e6cbb3e0600f6380ce7c7f3bd272ddb5 100644 (file)
@@ -56,7 +56,7 @@ static DATA_BLOB encode_krb5_setpw(const char *principal, const char *password)
 
        princ = strdup(principal);
 
-       if ((c = strchr(princ, '/')) == NULL) {
+       if ((c = strchr_m(princ, '/')) == NULL) {
            c = princ; 
        } else {
            *c = '\0';
@@ -66,7 +66,7 @@ static DATA_BLOB encode_krb5_setpw(const char *principal, const char *password)
 
        princ_part2 = c;
 
-       if ((c = strchr(c, '@')) != NULL) {
+       if ((c = strchr_m(c, '@')) != NULL) {
            *c = '\0';
            c++;
            realm = c;
@@ -462,14 +462,21 @@ ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ,
 {
 
        ADS_STATUS aret;
-       krb5_error_code ret;
+       krb5_error_code ret = 0;
        krb5_context context = NULL;
-       krb5_principal principal;
-       char *princ_name;
-       char *realm;
-       krb5_creds creds, *credsp;
+       krb5_principal principal = NULL;
+       char *princ_name = NULL;
+       char *realm = NULL;
+       krb5_creds creds, *credsp = NULL;
+#if KRB5_PRINC_REALM_RETURNS_REALM
+       krb5_realm orig_realm;
+#else
+       krb5_data orig_realm;
+#endif
        krb5_ccache ccache = NULL;
 
+       ZERO_STRUCT(creds);
+       
        ret = krb5_init_context(&context);
        if (ret) {
                DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret)));
@@ -487,14 +494,19 @@ ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ,
                return ADS_ERROR_KRB5(ret);
        }
 
-       ZERO_STRUCT(creds);
-       
-       realm = strchr(princ, '@');
+       realm = strchr_m(princ, '@');
+       if (!realm) {
+               krb5_cc_close(context, ccache);
+               krb5_free_context(context);
+               DEBUG(1,("Failed to get realm\n"));
+               return ADS_ERROR_KRB5(-1);
+       }
        realm++;
 
        asprintf(&princ_name, "kadmin/changepw@%s", realm);
        ret = krb5_parse_name(context, princ_name, &creds.server);
        if (ret) {
+               krb5_cc_close(context, ccache);
                 krb5_free_context(context);
                DEBUG(1,("Failed to parse kadmin/changepw (%s)\n", error_message(ret)));
                return ADS_ERROR_KRB5(ret);
@@ -504,16 +516,23 @@ ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ,
        /* parse the principal we got as a function argument */
        ret = krb5_parse_name(context, princ, &principal);
        if (ret) {
+               krb5_cc_close(context, ccache);
+               krb5_free_principal(context, creds.server);
                 krb5_free_context(context);
                DEBUG(1,("Failed to parse %s (%s)\n", princ_name, error_message(ret)));
                return ADS_ERROR_KRB5(ret);
        }
 
-       krb5_princ_set_realm(context, creds.server,
-                            krb5_princ_realm(context, principal));
+       /* The creds.server principal takes ownership of this memory.
+               Remember to set back to original value before freeing. */
+       orig_realm = *krb5_princ_realm(context, creds.server);
+       krb5_princ_set_realm(context, creds.server, krb5_princ_realm(context, principal));
        
        ret = krb5_cc_get_principal(context, ccache, &creds.client);
        if (ret) {
+               krb5_cc_close(context, ccache);
+               krb5_princ_set_realm(context, creds.server, &orig_realm);
+               krb5_free_principal(context, creds.server);
                krb5_free_principal(context, principal);
                 krb5_free_context(context);
                DEBUG(1,("Failed to get principal from ccache (%s)\n", 
@@ -523,7 +542,10 @@ ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ,
        
        ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp); 
        if (ret) {
+               krb5_cc_close(context, ccache);
                krb5_free_principal(context, creds.client);
+               krb5_princ_set_realm(context, creds.server, &orig_realm);
+               krb5_free_principal(context, creds.server);
                krb5_free_principal(context, principal);
                krb5_free_context(context);
                DEBUG(1,("krb5_get_credentials failed (%s)\n", error_message(ret)));
@@ -538,7 +560,10 @@ ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ,
 
        krb5_free_creds(context, credsp);
        krb5_free_principal(context, creds.client);
+       krb5_princ_set_realm(context, creds.server, &orig_realm);
+        krb5_free_principal(context, creds.server);
        krb5_free_principal(context, principal);
+       krb5_cc_close(context, ccache);
        krb5_free_context(context);
 
        return aret;
index e018eeb2da9c93e6822baf05816d73478695436a..78ea9f1497d63c933385fa95ffe5bd666ea4850b 100644 (file)
  * codepoints in UTF-8).  This may have to change at some point
  **/
 
+static SIG_ATOMIC_T gotalarm;
+                                                                                                                   
+/***************************************************************
+ Signal function to tell us we timed out.
+****************************************************************/
+                                                                                                                   
+static void gotalarm_sig(void)
+{
+       gotalarm = 1;
+}
+                                                                                                                   
+ LDAP *ldap_open_with_timeout(const char *server, int port, unsigned int to)
+{
+       LDAP *ldp = NULL;
+                                                                                                                   
+       /* Setup timeout */
+       gotalarm = 0;
+       CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
+       alarm(to);
+       /* End setup timeout. */
+                                                                                                                   
+       ldp = ldap_open(server, port);
+                                                                                                                   
+       /* Teardown timeout. */
+       CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
+       alarm(0);
+                                                                                                                   
+       return ldp;
+}
 
 /*
   try a connection to a given ldap server, returning True and setting the servers IP
@@ -58,7 +87,7 @@ static BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port)
        /* this copes with inet_ntoa brokenness */
        srv = strdup(server);
 
-       ads->ld = ldap_open(srv, port);
+       ads->ld = ldap_open_with_timeout(srv, port, lp_ldap_timeout());
        if (!ads->ld) {
                free(srv);
                return False;
@@ -226,11 +255,10 @@ got_connection:
        ldap_set_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
 
        if (!ads->auth.user_name) {
-               /* by default use the machine account */
-               fstring myname;
-               fstrcpy(myname, global_myname());
-               strlower_m(myname);
-               asprintf(&ads->auth.user_name, "HOST/%s", myname);
+               /* have to use the userPrincipalName value here and 
+                  not servicePrincipalName; found by Guenther Deschner @ Sernet */
+
+               asprintf(&ads->auth.user_name, "host/%s", global_myname() );
        }
 
        if (!ads->auth.realm) {
@@ -730,7 +758,7 @@ char *ads_get_dn(ADS_STRUCT *ads, void *msg)
  * @param host Hostname to search for
  * @return status of search
  **/
-ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, void **res, const char *host)
+ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, void **res, const char *machine)
 {
        ADS_STATUS status;
        char *expr;
@@ -738,13 +766,13 @@ ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, void **res, const char *host)
 
        /* the easiest way to find a machine account anywhere in the tree
           is to look for hostname$ */
-       if (asprintf(&expr, "(samAccountName=%s$)", host) == -1) {
+       if (asprintf(&expr, "(samAccountName=%s$)", machine) == -1) {
                DEBUG(1, ("asprintf failed!\n"));
                return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
        }
        
        status = ads_search(ads, res, expr, attrs);
-       free(expr);
+       SAFE_FREE(expr);
        return status;
 }
 
@@ -979,18 +1007,251 @@ char *ads_ou_string(const char *org_unit)
        return ads_build_path(org_unit, "\\/", "ou=", 1);
 }
 
+/**
+ * Adds (appends) an item to an attribute array, rather then
+ * replacing the whole list
+ * @param ctx An initialized TALLOC_CTX
+ * @param mods An initialized ADS_MODLIST
+ * @param name name of the ldap attribute to append to
+ * @param vals an array of values to add
+ * @return status of addition
+ **/
 
+ADS_STATUS ads_add_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods,
+                               const char *name, const char **vals)
+{
+       return ads_modlist_add(ctx, mods, LDAP_MOD_ADD, name, (const void **) vals);
+}
 
-/*
-  add a machine account to the ADS server
-*/
-static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname, 
+/**
+ * Determines the computer account's current KVNO via an LDAP lookup
+ * @param ads An initialized ADS_STRUCT
+ * @param machine_name the NetBIOS name of the computer, which is used to identify the computer account.
+ * @return the kvno for the computer account, or -1 in case of a failure.
+ **/
+
+uint32 ads_get_kvno(ADS_STRUCT *ads, const char *machine_name)
+{
+       LDAPMessage *res = NULL;
+       uint32 kvno = (uint32)-1;      /* -1 indicates a failure */
+       char *filter;
+       const char *attrs[] = {"msDS-KeyVersionNumber", NULL};
+       char *dn_string = NULL;
+       ADS_STATUS ret = ADS_ERROR(LDAP_SUCCESS);
+
+       DEBUG(5,("ads_get_kvno: Searching for host %s\n", machine_name));
+       if (asprintf(&filter, "(samAccountName=%s$)", machine_name) == -1) {
+               return kvno;
+       }
+       ret = ads_search(ads, (void**) &res, filter, attrs);
+       SAFE_FREE(filter);
+       if (!ADS_ERR_OK(ret) && ads_count_replies(ads, res)) {
+               DEBUG(1,("ads_get_kvno: Computer Account For %s not found.\n", machine_name));
+               ads_msgfree(ads, res);
+               return kvno;
+       }
+
+       dn_string = ads_get_dn(ads, res);
+       if (!dn_string) {
+               DEBUG(0,("ads_get_kvno: out of memory.\n"));
+               ads_msgfree(ads, res);
+               return kvno;
+       }
+       DEBUG(5,("ads_get_kvno: Using: %s\n", dn_string));
+       ads_memfree(ads, dn_string);
+
+       /* ---------------------------------------------------------
+        * 0 is returned as a default KVNO from this point on...
+        * This is done because Windows 2000 does not support key
+        * version numbers.  Chances are that a failure in the next
+        * step is simply due to Windows 2000 being used for a
+        * domain controller. */
+       kvno = 0;
+
+       if (!ads_pull_uint32(ads, res, "msDS-KeyVersionNumber", &kvno)) {
+               DEBUG(3,("ads_get_kvno: Error Determining KVNO!\n"));
+               DEBUG(3,("ads_get_kvno: Windows 2000 does not support KVNO's, so this may be normal.\n"));
+               ads_msgfree(ads, res);
+               return kvno;
+       }
+
+       /* Success */
+       DEBUG(5,("ads_get_kvno: Looked Up KVNO of: %d\n", kvno));
+       ads_msgfree(ads, res);
+       return kvno;
+}
+
+/**
+ * This clears out all registered spn's for a given hostname
+ * @param ads An initilaized ADS_STRUCT
+ * @param machine_name the NetBIOS name of the computer.
+ * @return 0 upon success, non-zero otherwise.
+ **/
+
+ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machine_name)
+{
+       TALLOC_CTX *ctx;
+       LDAPMessage *res = NULL;
+       ADS_MODLIST mods;
+       const char *servicePrincipalName[1] = {NULL};
+       ADS_STATUS ret = ADS_ERROR(LDAP_SUCCESS);
+       char *dn_string = NULL;
+
+       ret = ads_find_machine_acct(ads, (void **)&res, machine_name);
+       if (!ADS_ERR_OK(ret) || ads_count_replies(ads, res) != 1) {
+               DEBUG(5,("ads_clear_service_principal_names: WARNING: Host Account for %s not found... skipping operation.\n", machine_name));
+               DEBUG(5,("ads_clear_service_principal_names: WARNING: Service Principals for %s have NOT been cleared.\n", machine_name));
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+       }
+
+       DEBUG(5,("ads_clear_service_principal_names: Host account for %s found\n", machine_name));
+       ctx = talloc_init("ads_clear_service_principal_names");
+       if (!ctx) {
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       if (!(mods = ads_init_mods(ctx))) {
+               talloc_destroy(ctx);
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+       ret = ads_mod_strlist(ctx, &mods, "servicePrincipalName", servicePrincipalName);
+       if (!ADS_ERR_OK(ret)) {
+               DEBUG(1,("ads_clear_service_principal_names: Error creating strlist.\n"));
+               ads_msgfree(ads, res);
+               talloc_destroy(ctx);
+               return ret;
+       }
+       dn_string = ads_get_dn(ads, res);
+       if (!dn_string) {
+               talloc_destroy(ctx);
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+       ret = ads_gen_mod(ads, dn_string, mods);
+       ads_memfree(ads,dn_string);
+       if (!ADS_ERR_OK(ret)) {
+               DEBUG(1,("ads_clear_service_principal_names: Error: Updating Service Principals for machine %s in LDAP\n",
+                       machine_name));
+               ads_msgfree(ads, res);
+               talloc_destroy(ctx);
+               return ret;
+       }
+
+       ads_msgfree(ads, res);
+       talloc_destroy(ctx);
+       return ret;
+}
+
+/**
+ * This adds a service principal name to an existing computer account
+ * (found by hostname) in AD.
+ * @param ads An initialized ADS_STRUCT
+ * @param machine_name the NetBIOS name of the computer, which is used to identify the computer account.
+ * @param spn A string of the service principal to add, i.e. 'host'
+ * @return 0 upon sucess, or non-zero if a failure occurs
+ **/
+
+ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_name, const char *spn)
+{
+       ADS_STATUS ret;
+       TALLOC_CTX *ctx;
+       LDAPMessage *res = NULL;
+       char *host_spn, *host_upn, *psp1, *psp2;
+       ADS_MODLIST mods;
+       fstring my_fqdn;
+       char *dn_string = NULL;
+       const char *servicePrincipalName[3] = {NULL, NULL, NULL};
+
+       ret = ads_find_machine_acct(ads, (void **)&res, machine_name);
+       if (!ADS_ERR_OK(ret) || ads_count_replies(ads, res) != 1) {
+               DEBUG(1,("ads_add_service_principal_name: WARNING: Host Account for %s not found... skipping operation.\n",
+                       machine_name));
+               DEBUG(1,("ads_add_service_principal_name: WARNING: Service Principal '%s/%s@%s' has NOT been added.\n",
+                       spn, machine_name, ads->config.realm));
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+       }
+
+       DEBUG(1,("ads_add_service_principal_name: Host account for %s found\n", machine_name));
+       if (!(ctx = talloc_init("ads_add_service_principal_name"))) {
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       name_to_fqdn(my_fqdn, machine_name);
+       if (!(host_spn = talloc_asprintf(ctx, "HOST/%s", my_fqdn))) {
+               talloc_destroy(ctx);
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+       }
+       if (!(host_upn = talloc_asprintf(ctx, "%s@%s", host_spn, ads->config.realm))) {
+               talloc_destroy(ctx);
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+       }
+
+       /* Add the extra principal */
+       psp1 = talloc_asprintf(ctx, "%s/%s", spn, machine_name);
+       strupper_m(psp1);
+       strlower_m(&psp1[strlen(spn)]);
+       DEBUG(5,("ads_add_service_principal_name: INFO: Adding %s to host %s\n", psp1, machine_name));
+       servicePrincipalName[0] = psp1;
+       psp2 = talloc_asprintf(ctx, "%s/%s.%s", spn, machine_name, ads->config.realm);
+       strupper_m(psp2);
+       strlower_m(&psp2[strlen(spn)]);
+       DEBUG(5,("ads_add_service_principal_name: INFO: Adding %s to host %s\n", psp2, machine_name));
+       servicePrincipalName[1] = psp2;
+
+       if (!(mods = ads_init_mods(ctx))) {
+               talloc_destroy(ctx);
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+       ret = ads_add_strlist(ctx, &mods, "servicePrincipalName", servicePrincipalName);
+       if (!ADS_ERR_OK(ret)) {
+               DEBUG(1,("ads_add_service_principal_name: Error: Updating Service Principals in LDAP\n"));
+               talloc_destroy(ctx);
+               ads_msgfree(ads, res);
+               return ret;
+       }
+       dn_string = ads_get_dn(ads, res);
+       if (!dn_string) {
+               talloc_destroy(ctx);
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+       ret = ads_gen_mod(ads, dn_string, mods);
+       ads_memfree(ads,dn_string);
+       if (!ADS_ERR_OK(ret)) {
+               DEBUG(1,("ads_add_service_principal_name: Error: Updating Service Principals in LDAP\n"));
+               talloc_destroy(ctx);
+               ads_msgfree(ads, res);
+               return ret;
+       }
+
+       talloc_destroy(ctx);
+       ads_msgfree(ads, res);
+       return ret;
+}
+
+/**
+ * adds a machine account to the ADS server
+ * @param ads An intialized ADS_STRUCT
+ * @param machine_name - the NetBIOS machine name of this account.
+ * @param account_type A number indicating the type of account to create
+ * @param org_unit The LDAP path in which to place this account
+ * @return 0 upon success, or non-zero otherwise
+**/
+
+static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *machine_name, 
                                       uint32 account_type,
                                       const char *org_unit)
 {
        ADS_STATUS ret, status;
        char *host_spn, *host_upn, *new_dn, *samAccountName, *controlstr;
-       char *ou_str;
        TALLOC_CTX *ctx;
        ADS_MODLIST mods;
        const char *objectClass[] = {"top", "person", "organizationalPerson",
@@ -999,87 +1260,106 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,
        char *psp, *psp2;
        unsigned acct_control;
        unsigned exists=0;
-       LDAPMessage *res;
+       fstring my_fqdn;
+       LDAPMessage *res = NULL;
 
-       status = ads_find_machine_acct(ads, (void **)&res, hostname);
+       if (!(ctx = talloc_init("ads_add_machine_acct")))
+               return ADS_ERROR(LDAP_NO_MEMORY);
+
+       ret = ADS_ERROR(LDAP_NO_MEMORY);
+
+       name_to_fqdn(my_fqdn, machine_name);
+
+       status = ads_find_machine_acct(ads, (void **)&res, machine_name);
        if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) {
-               DEBUG(0, ("Host account for %s already exists - modifying old account\n", hostname));
+               char *dn_string = ads_get_dn(ads, res);
+               if (!dn_string) {
+                       DEBUG(1, ("ads_add_machine_acct: ads_get_dn returned NULL (malloc failure?)\n"));
+                       goto done;
+               }
+               new_dn = talloc_strdup(ctx, dn_string);
+               ads_memfree(ads,dn_string);
+               DEBUG(0, ("ads_add_machine_acct: Host account for %s already exists - modifying old account\n",
+                       machine_name));
                exists=1;
-       }
+       } else {
+               char *ou_str = ads_ou_string(org_unit);
+               if (!ou_str) {
+                       DEBUG(1, ("ads_add_machine_acct: ads_ou_string returned NULL (malloc failure?)\n"));
+                       goto done;
+               }
+               new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", machine_name, ou_str, 
+                               ads->config.bind_path);
 
-       if (!(ctx = talloc_init("machine_account")))
-               return ADS_ERROR(LDAP_NO_MEMORY);
+               SAFE_FREE(ou_str);
+       }
 
-       ret = ADS_ERROR(LDAP_NO_MEMORY);
+       if (!new_dn) {
+               goto done;
+       }
 
-       if (!(host_spn = talloc_asprintf(ctx, "HOST/%s", hostname)))
+       if (!(host_spn = talloc_asprintf(ctx, "HOST/%s", machine_name)))
                goto done;
        if (!(host_upn = talloc_asprintf(ctx, "%s@%s", host_spn, ads->config.realm)))
                goto done;
-       ou_str = ads_ou_string(org_unit);
-       if (!ou_str) {
-               DEBUG(1, ("ads_ou_string returned NULL (malloc failure?)\n"));
-               goto done;
-       }
-       new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", hostname, ou_str, 
-                                ads->config.bind_path);
-       servicePrincipalName[0] = talloc_asprintf(ctx, "HOST/%s", hostname);
+       servicePrincipalName[0] = talloc_asprintf(ctx, "HOST/%s", machine_name);
        psp = talloc_asprintf(ctx, "HOST/%s.%s", 
-                             hostname, 
-                             ads->config.realm);
+                               machine_name, 
+                               ads->config.realm);
        strlower_m(&psp[5]);
        servicePrincipalName[1] = psp;
-       servicePrincipalName[2] = talloc_asprintf(ctx, "CIFS/%s", hostname);
+       servicePrincipalName[2] = talloc_asprintf(ctx, "CIFS/%s", machine_name);
        psp2 = talloc_asprintf(ctx, "CIFS/%s.%s", 
-                              hostname, 
+                              machine_name, 
                               ads->config.realm);
        strlower_m(&psp2[5]);
        servicePrincipalName[3] = psp2;
 
-       free(ou_str);
-       if (!new_dn)
-               goto done;
-
-       if (!(samAccountName = talloc_asprintf(ctx, "%s$", hostname)))
+       if (!(samAccountName = talloc_asprintf(ctx, "%s$", machine_name))) {
                goto done;
+       }
 
        acct_control = account_type | UF_DONT_EXPIRE_PASSWD;
 #ifndef ENCTYPE_ARCFOUR_HMAC
        acct_control |= UF_USE_DES_KEY_ONLY;
 #endif
 
-       if (!(controlstr = talloc_asprintf(ctx, "%u", acct_control)))
+       if (!(controlstr = talloc_asprintf(ctx, "%u", acct_control))) {
                goto done;
+       }
 
-       if (!(mods = ads_init_mods(ctx)))
+       if (!(mods = ads_init_mods(ctx))) {
                goto done;
+       }
 
        if (!exists) {
-               ads_mod_str(ctx, &mods, "cn", hostname);
+               ads_mod_str(ctx, &mods, "cn", machine_name);
                ads_mod_str(ctx, &mods, "sAMAccountName", samAccountName);
                ads_mod_str(ctx, &mods, "userAccountControl", controlstr);
                ads_mod_strlist(ctx, &mods, "objectClass", objectClass);
        }
-       ads_mod_str(ctx, &mods, "dNSHostName", hostname);
+       ads_mod_str(ctx, &mods, "dNSHostName", my_fqdn);
        ads_mod_str(ctx, &mods, "userPrincipalName", host_upn);
        ads_mod_strlist(ctx, &mods, "servicePrincipalName", servicePrincipalName);
        ads_mod_str(ctx, &mods, "operatingSystem", "Samba");
        ads_mod_str(ctx, &mods, "operatingSystemVersion", SAMBA_VERSION_STRING);
 
-       if (!exists) 
+       if (!exists)  {
                ret = ads_gen_add(ads, new_dn, mods);
-       else
+       } else {
                ret = ads_gen_mod(ads, new_dn, mods);
+       }
 
-       if (!ADS_ERR_OK(ret))
+       if (!ADS_ERR_OK(ret)) {
                goto done;
+       }
 
        /* Do not fail if we can't set security descriptor
         * it shouldn't be mandatory and probably we just 
         * don't have enough rights to do it.
         */
        if (!exists) {
-               status = ads_set_machine_sd(ads, hostname, new_dn);
+               status = ads_set_machine_sd(ads, machine_name, new_dn);
        
                if (!ADS_ERR_OK(status)) {
                        DEBUG(0, ("Warning: ads_set_machine_sd: %s\n",
@@ -1087,6 +1367,7 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,
                }
        }
 done:
+       ads_msgfree(ads, res);
        talloc_destroy(ctx);
        return ret;
 }
@@ -1303,47 +1584,50 @@ int ads_count_replies(ADS_STRUCT *ads, void *res)
  * Join a machine to a realm
  *  Creates the machine account and sets the machine password
  * @param ads connection to ads server
- * @param hostname name of host to add
+ * @param machine name of host to add
  * @param org_unit Organizational unit to place machine in
  * @return status of join
  **/
-ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *hostname, 
+ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *machine_name, 
                          uint32 account_type, const char *org_unit)
 {
        ADS_STATUS status;
-       LDAPMessage *res;
-       char *host;
+       LDAPMessage *res = NULL;
+       char *machine;
 
-       /* hostname must be lowercase */
-       host = strdup(hostname);
-       strlower_m(host);
+       /* machine name must be lowercase */
+       machine = strdup(machine_name);
+       strlower_m(machine);
 
        /*
-       status = ads_find_machine_acct(ads, (void **)&res, host);
+       status = ads_find_machine_acct(ads, (void **)&res, machine);
        if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) {
-               DEBUG(0, ("Host account for %s already exists - deleting old account\n", host));
-               status = ads_leave_realm(ads, host);
+               DEBUG(0, ("Host account for %s already exists - deleting old account\n", machine));
+               status = ads_leave_realm(ads, machine);
                if (!ADS_ERR_OK(status)) {
                        DEBUG(0, ("Failed to delete host '%s' from the '%s' realm.\n", 
-                                 host, ads->config.realm));
+                                 machine, ads->config.realm));
                        return status;
                }
        }
        */
 
-       status = ads_add_machine_acct(ads, host, account_type, org_unit);
+       status = ads_add_machine_acct(ads, machine, account_type, org_unit);
        if (!ADS_ERR_OK(status)) {
-               DEBUG(0, ("ads_add_machine_acct: %s\n", ads_errstr(status)));
+               DEBUG(0, ("ads_add_machine_acct (%s): %s\n", machine, ads_errstr(status)));
+               SAFE_FREE(machine);
                return status;
        }
 
-       status = ads_find_machine_acct(ads, (void **)&res, host);
+       status = ads_find_machine_acct(ads, (void **)&res, machine);
        if (!ADS_ERR_OK(status)) {
-               DEBUG(0, ("Host account test failed\n"));
+               DEBUG(0, ("Host account test failed for machine %s\n", machine));
+               SAFE_FREE(machine);
                return status;
        }
 
-       free(host);
+       SAFE_FREE(machine);
+       ads_msgfree(ads, res);
 
        return status;
 }
index 18cbb4658871827321eb99721006fc0373258634..8eb2c86bed5e1cac6565a792b2ae77df6e2356db 100644 (file)
@@ -201,14 +201,14 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
 
        /* make sure the server understands kerberos */
        for (i=0;OIDs[i];i++) {
-               DEBUG(3,("got OID=%s\n", OIDs[i]));
+               DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs[i]));
                if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
                    strcmp(OIDs[i], OID_KERBEROS5) == 0) {
                        got_kerberos_mechanism = True;
                }
                free(OIDs[i]);
        }
-       DEBUG(3,("got principal=%s\n", principal));
+       DEBUG(3,("ads_sasl_spnego_bind: got server principal name =%s\n", principal));
 
 #ifdef HAVE_KRB5
        if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
index ecc5e3dee641b949034370d2a0c4dc975707052c..ca14f3fbb7119f9877e6ced1fccd4933fb8322e6 100644 (file)
@@ -320,17 +320,17 @@ int asn1_tag_remaining(ASN1_DATA *data)
 BOOL asn1_read_OID(ASN1_DATA *data, char **OID)
 {
        uint8 b;
-       pstring oid;
+       pstring oid_str;
        fstring el;
 
        if (!asn1_start_tag(data, ASN1_OID)) return False;
        asn1_read_uint8(data, &b);
 
-       oid[0] = 0;
+       oid_str[0] = 0;
        fstr_sprintf(el, "%u",  b/40);
-       pstrcat(oid, el);
+       pstrcat(oid_str, el);
        fstr_sprintf(el, " %u",  b%40);
-       pstrcat(oid, el);
+       pstrcat(oid_str, el);
 
        while (asn1_tag_remaining(data) > 0) {
                unsigned v = 0;
@@ -339,12 +339,12 @@ BOOL asn1_read_OID(ASN1_DATA *data, char **OID)
                        v = (v<<7) | (b&0x7f);
                } while (!data->has_error && b & 0x80);
                fstr_sprintf(el, " %u",  v);
-               pstrcat(oid, el);
+               pstrcat(oid_str, el);
        }
 
        asn1_end_tag(data);
 
-       *OID = strdup(oid);
+       *OID = strdup(oid_str);
 
        return !data->has_error;
 }
index b75d6be0a60eeb8154328f31ce66b0e6c8a2eea7..281ee3af8453f0d655c82399fbf31f5e531b92c1 100644 (file)
@@ -176,7 +176,12 @@ void cli_setup_packet(struct cli_state *cli)
        SSVAL(cli->outbuf,smb_mid,cli->mid);
        if (cli->protocol > PROTOCOL_CORE) {
                uint16 flags2;
-               SCVAL(cli->outbuf,smb_flg,0x8);
+               if (cli->case_sensitive) {
+                       SCVAL(cli->outbuf,smb_flg,0x0);
+               } else {
+                       /* Default setting, case insensitive. */
+                       SCVAL(cli->outbuf,smb_flg,0x8);
+               }
                flags2 = FLAGS2_LONG_PATH_COMPONENTS;
                if (cli->capabilities & CAP_UNICODE)
                        flags2 |= FLAGS2_UNICODE_STRINGS;
@@ -273,6 +278,7 @@ struct cli_state *cli_initialise(struct cli_state *cli)
        cli->outbuf = (char *)malloc(cli->bufsize+SAFETY_MARGIN);
        cli->inbuf = (char *)malloc(cli->bufsize+SAFETY_MARGIN);
        cli->oplock_handler = cli_oplock_ack;
+       cli->case_sensitive = False;
 
        cli->use_spnego = lp_client_use_spnego();
 
@@ -440,6 +446,17 @@ uint16 cli_setpid(struct cli_state *cli, uint16 pid)
        return ret;
 }
 
+/****************************************************************************
+ Set the case sensitivity flag on the packets. Returns old state.
+****************************************************************************/
+
+BOOL cli_set_case_sensitive(struct cli_state *cli, BOOL case_sensitive)
+{
+       BOOL ret = cli->case_sensitive;
+       cli->case_sensitive = case_sensitive;
+       return ret;
+}
+
 /****************************************************************************
 Send a keepalive packet to the server
 ****************************************************************************/
index 9027f192ef7226bd55ca5d8dc8fd6719545416a2..4929bd63ef2c49f3ac2ebe8b6cd134e90f2b2cb2 100644 (file)
 #endif
 
 #if defined(HAVE_KRB5_GET_PERMITTED_ENCTYPES)
-krb5_error_code get_kerberos_allowed_etypes(krb5_context context, 
+ krb5_error_code get_kerberos_allowed_etypes(krb5_context context, 
                                            krb5_enctype **enctypes)
 {
        return krb5_get_permitted_enctypes(context, enctypes);
 }
 #elif defined(HAVE_KRB5_GET_DEFAULT_IN_TKT_ETYPES)
-krb5_error_code get_kerberos_allowed_etypes(krb5_context context, 
+ krb5_error_code get_kerberos_allowed_etypes(krb5_context context, 
                                            krb5_enctype **enctypes)
 {
        return krb5_get_default_in_tkt_etypes(context, enctypes);
@@ -234,6 +234,13 @@ krb5_error_code get_kerberos_allowed_etypes(krb5_context context,
 }
 #endif
 
+#if !defined(HAVE_KRB5_FREE_UNPARSED_NAME)
+ void krb5_free_unparsed_name(krb5_context context, char *val)
+{
+       SAFE_FREE(val);
+}
+#endif
+
 static BOOL ads_cleanup_expired_creds(krb5_context context, 
                                      krb5_ccache  ccache,
                                      krb5_creds  *credsp)
@@ -413,11 +420,12 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset,
 failed:
 
        if ( context ) {
-#if 0  /* JERRY -- disabled since it causes heimdal 0.6.1rc3 to die 
-          SuSE 9.1 Pro */
+/* Removed by jra. They really need to fix their kerberos so we don't leak memory. 
+ JERRY -- disabled since it causes heimdal 0.6.1rc3 to die
+          SuSE 9.1 Pro 
+*/
                if (ccdef)
                        krb5_cc_close(context, ccdef);
-#endif
                if (auth_context)
                        krb5_auth_con_free(context, auth_context);
                krb5_free_context(context);
@@ -465,6 +473,17 @@ failed:
 }
 #endif
 
+ krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry)
+{
+#if defined(HAVE_KRB5_KT_FREE_ENTRY)
+       return krb5_kt_free_entry(context, kt_entry);
+#elif defined(HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS)
+       return krb5_free_keytab_entry_contents(context, kt_entry);
+#else
+#error UNKNOWN_KT_FREE_FUNCTION
+#endif
+}
+
 #else /* HAVE_KRB5 */
  /* this saves a few linking headaches */
 int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
index e6cadc466c17e501e18946913b8dc909511ef5da..85b7bd9e1eec1f3cee0d87cf33bcbd2d43c01d71 100644 (file)
@@ -141,9 +141,9 @@ BOOL spnego_parse_negTokenInit(DATA_BLOB blob,
        asn1_start_tag(&data,ASN1_CONTEXT(0));
        asn1_start_tag(&data,ASN1_SEQUENCE(0));
        for (i=0; asn1_tag_remaining(&data) > 0 && i < ASN1_MAX_OIDS; i++) {
-               char *oid = NULL;
-               asn1_read_OID(&data,&oid);
-               OIDs[i] = oid;
+               char *oid_str = NULL;
+               asn1_read_OID(&data,&oid_str);
+               OIDs[i] = oid_str;
        }
        OIDs[i] = NULL;
        asn1_end_tag(&data);
@@ -230,9 +230,9 @@ BOOL parse_negTokenTarg(DATA_BLOB blob, char *OIDs[ASN1_MAX_OIDS], DATA_BLOB *se
        asn1_start_tag(&data, ASN1_CONTEXT(0));
        asn1_start_tag(&data, ASN1_SEQUENCE(0));
        for (i=0; asn1_tag_remaining(&data) > 0 && i < ASN1_MAX_OIDS; i++) {
-               char *oid = NULL;
-               asn1_read_OID(&data,&oid);
-               OIDs[i] = oid;
+               char *oid_str = NULL;
+               asn1_read_OID(&data,&oid_str);
+               OIDs[i] = oid_str;
        }
        OIDs[i] = NULL;
        asn1_end_tag(&data);
index e6604617d6846595cc93db91b0eb85fd11630f66..15cc75b129e6b64019b894ef06834da22f6ab2ee 100644 (file)
@@ -154,5 +154,3 @@ void flush_negative_conn_cache( void )
        }
 
 }
-
-
index 2bb7359e742e2cbf779fa65936d9d1cfa8217ee9..cee0015e25795daadcf709c2ac83f1d8c5dd4ee9 100644 (file)
@@ -56,7 +56,8 @@ static struct node_status *parse_node_status(char *p, int *num_names, struct nod
                return NULL;
 
        ret = (struct node_status *)malloc(sizeof(struct node_status)* (*num_names));
-       if (!ret) return NULL;
+       if (!ret)
+               return NULL;
 
        p++;
        for (i=0;i< *num_names;i++) {
@@ -556,84 +557,80 @@ XFILE *startlmhosts(char *fname)
 
 BOOL getlmhostsent( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
 {
-  pstring line;
-
-  while(!x_feof(fp) && !x_ferror(fp)) {
-    pstring ip,flags,extra;
-    const char *ptr;
-    char *ptr1;
-    int count = 0;
+       pstring line;
 
-    *name_type = -1;
+       while(!x_feof(fp) && !x_ferror(fp)) {
+               pstring ip,flags,extra;
+               const char *ptr;
+               char *ptr1;
+               int count = 0;
 
-    if (!fgets_slash(line,sizeof(pstring),fp))
-      continue;
+               *name_type = -1;
 
-    if (*line == '#')
-      continue;
+               if (!fgets_slash(line,sizeof(pstring),fp)) {
+                       continue;
+               }
 
-    pstrcpy(ip,"");
-    pstrcpy(name,"");
-    pstrcpy(flags,"");
+               if (*line == '#') {
+                       continue;
+               }
 
-    ptr = line;
+               pstrcpy(ip,"");
+               pstrcpy(name,"");
+               pstrcpy(flags,"");
 
-    if (next_token(&ptr,ip   ,NULL,sizeof(ip)))
-      ++count;
-    if (next_token(&ptr,name ,NULL, sizeof(pstring)))
-      ++count;
-    if (next_token(&ptr,flags,NULL, sizeof(flags)))
-      ++count;
-    if (next_token(&ptr,extra,NULL, sizeof(extra)))
-      ++count;
+               ptr = line;
 
-    if (count <= 0)
-      continue;
+               if (next_token(&ptr,ip   ,NULL,sizeof(ip)))
+                       ++count;
+               if (next_token(&ptr,name ,NULL, sizeof(pstring)))
+                       ++count;
+               if (next_token(&ptr,flags,NULL, sizeof(flags)))
+                       ++count;
+               if (next_token(&ptr,extra,NULL, sizeof(extra)))
+                       ++count;
 
-    if (count > 0 && count < 2)
-    {
-      DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
-      continue;
-    }
+               if (count <= 0)
+                       continue;
 
-    if (count >= 4)
-    {
-      DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
-      continue;
-    }
+               if (count > 0 && count < 2) {
+                       DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
+                       continue;
+               }
 
-    DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
+               if (count >= 4) {
+                       DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
+                       continue;
+               }
 
-    if (strchr_m(flags,'G') || strchr_m(flags,'S'))
-    {
-      DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
-      continue;
-    }
+               DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
 
-    *ipaddr = *interpret_addr2(ip);
+               if (strchr_m(flags,'G') || strchr_m(flags,'S')) {
+                       DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
+                       continue;
+               }
 
-    /* Extra feature. If the name ends in '#XX', where XX is a hex number,
-       then only add that name type. */
-    if((ptr1 = strchr_m(name, '#')) != NULL)
-    {
-      char *endptr;
+               *ipaddr = *interpret_addr2(ip);
 
-      ptr1++;
-      *name_type = (int)strtol(ptr1, &endptr, 16);
+               /* Extra feature. If the name ends in '#XX', where XX is a hex number,
+                       then only add that name type. */
+               if((ptr1 = strchr_m(name, '#')) != NULL) {
+                       char *endptr;
+                       ptr1++;
 
-      if(!*ptr1 || (endptr == ptr1))
-      {
-        DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
-        continue;
-      }
+                       *name_type = (int)strtol(ptr1, &endptr, 16);
+                       if(!*ptr1 || (endptr == ptr1)) {
+                               DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
+                               continue;
+                       }
 
-      *(--ptr1) = '\0'; /* Truncate at the '#' */
-    }
+                       *(--ptr1) = '\0'; /* Truncate at the '#' */
+               }
 
-    return True;
-  }
+               return True;
+       }
 
-  return False;
+       return False;
 }
 
 /********************************************************
@@ -998,145 +995,145 @@ static BOOL internal_resolve_name(const char *name, int name_type,
                                  struct ip_service **return_iplist, 
                                  int *return_count, const char *resolve_order)
 {
-  pstring name_resolve_list;
-  fstring tok;
-  const char *ptr;
-  BOOL allones = (strcmp(name,"255.255.255.255") == 0);
-  BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
-  BOOL is_address = is_ipaddress(name);
-  BOOL result = False;
-  int i;
+       pstring name_resolve_list;
+       fstring tok;
+       const char *ptr;
+       BOOL allones = (strcmp(name,"255.255.255.255") == 0);
+       BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
+       BOOL is_address = is_ipaddress(name);
+       BOOL result = False;
+       int i;
 
-  *return_iplist = NULL;
-  *return_count = 0;
+       *return_iplist = NULL;
+       *return_count = 0;
 
-  DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type));
+       DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type));
 
-  if (allzeros || allones || is_address) {
+       if (allzeros || allones || is_address) {
   
-       if ( (*return_iplist = (struct ip_service *)malloc(sizeof(struct ip_service))) == NULL ) {
-               DEBUG(0,("internal_resolve_name: malloc fail !\n"));
-               return False;
-       }
+               if ( (*return_iplist = (struct ip_service *)malloc(sizeof(struct ip_service))) == NULL ) {
+                       DEBUG(0,("internal_resolve_name: malloc fail !\n"));
+                       return False;
+               }
        
-       if(is_address) { 
-               /* ignore the port here */
-               (*return_iplist)->port = PORT_NONE;
+               if(is_address) { 
+                       /* ignore the port here */
+                       (*return_iplist)->port = PORT_NONE;
                
-               /* if it's in the form of an IP address then get the lib to interpret it */
-               if (((*return_iplist)->ip.s_addr = inet_addr(name)) == 0xFFFFFFFF ){
-                       DEBUG(1,("internal_resolve_name: inet_addr failed on %s\n", name));
-                       return False;
+                       /* if it's in the form of an IP address then get the lib to interpret it */
+                       if (((*return_iplist)->ip.s_addr = inet_addr(name)) == 0xFFFFFFFF ){
+                               DEBUG(1,("internal_resolve_name: inet_addr failed on %s\n", name));
+                               return False;
+                       }
+               } else {
+                       (*return_iplist)->ip.s_addr = allones ? 0xFFFFFFFF : 0;
                }
-       } else {
-               (*return_iplist)->ip.s_addr = allones ? 0xFFFFFFFF : 0;
+               *return_count = 1;
+               return True;
        }
-       *return_count = 1;
-       return True;
-  }
   
-  /* Check name cache */
+       /* Check name cache */
 
-  if (namecache_fetch(name, name_type, return_iplist, return_count)) {
-       /* This could be a negative response */
-       return (*return_count > 0);
-  }
+       if (namecache_fetch(name, name_type, return_iplist, return_count)) {
+               /* This could be a negative response */
+               return (*return_count > 0);
+       }
 
-  /* set the name resolution order */
+       /* set the name resolution order */
 
-  if ( strcmp( resolve_order, "NULL") == 0 ) {
-    DEBUG(8,("internal_resolve_name: all lookups disabled\n"));
-    return False;
-  }
-  
-  if ( !resolve_order )
-    pstrcpy(name_resolve_list, lp_name_resolve_order());
-  else
-    pstrcpy(name_resolve_list, resolve_order);
+       if ( strcmp( resolve_order, "NULL") == 0 ) {
+               DEBUG(8,("internal_resolve_name: all lookups disabled\n"));
+               return False;
+       }
   
-  if ( !name_resolve_list[0] )
-    ptr = "host";
-  else
-    ptr = name_resolve_list;
+       if ( !resolve_order ) {
+               pstrcpy(name_resolve_list, lp_name_resolve_order());
+       } else {
+               pstrcpy(name_resolve_list, resolve_order);
+
+               if ( !name_resolve_list[0] ) {
+                       ptr = "host";
+               } else {
+                       ptr = name_resolve_list;
+               }
 
-  /* iterate through the name resolution backends */
+               /* iterate through the name resolution backends */
   
-  while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
-         if((strequal(tok, "host") || strequal(tok, "hosts"))) {
-                 if (resolve_hosts(name, name_type, return_iplist, return_count)) {
-                         result = True;
-                         goto done;
-                 }
-         } else if(strequal( tok, "ads")) {
-                  /* deal with 0x1c names here.  This will result in a
-                    SRV record lookup for _ldap._tcp.<domain> if we
-                    are using 'security = ads' */
-                 if (resolve_ads(name, name_type, return_iplist, return_count)) {
-                   result = True;
-                   goto done;
-                 }
-         } else if(strequal( tok, "lmhosts")) {
-                 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
-                   result = True;
-                   goto done;
-                 }
-         } else if(strequal( tok, "wins")) {
-                 /* don't resolve 1D via WINS */
-                 if (name_type != 0x1D &&
-                     resolve_wins(name, name_type, return_iplist, return_count)) {
-                   result = True;
-                   goto done;
-                 }
-         } else if(strequal( tok, "bcast")) {
-                 if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
-                   result = True;
-                   goto done;
-                 }
-         } else {
-                 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
-         }
-  }
-
-  /* All of the resolve_* functions above have returned false. */
-
-  SAFE_FREE(*return_iplist);
-  *return_count = 0;
-
-  return False;
+               while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
+                       if((strequal(tok, "host") || strequal(tok, "hosts"))) {
+                               if (resolve_hosts(name, name_type, return_iplist, return_count)) {
+                                       result = True;
+                                       goto done;
+                               }
+                       } else if(strequal( tok, "ads")) {
+                               /* deal with 0x1c names here.  This will result in a
+                                       SRV record lookup for _ldap._tcp.<domain> if we
+                                       are using 'security = ads' */
+                               if (resolve_ads(name, name_type, return_iplist, return_count)) {
+                                       result = True;
+                                       goto done;
+                               }
+                       } else if(strequal( tok, "lmhosts")) {
+                               if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
+                                       result = True;
+                                       goto done;
+                               }
+                       } else if(strequal( tok, "wins")) {
+                               /* don't resolve 1D via WINS */
+                               if (name_type != 0x1D && resolve_wins(name, name_type, return_iplist, return_count)) {
+                                       result = True;
+                                       goto done;
+                               }
+                       } else if(strequal( tok, "bcast")) {
+                               if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
+                                       result = True;
+                                       goto done;
+                               }
+                       } else {
+                               DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
+                       }
+               }
 
- done:
+               /* All of the resolve_* functions above have returned false. */
+
+               SAFE_FREE(*return_iplist);
+               *return_count = 0;
+
+               return False;
 
-  /* Remove duplicate entries.  Some queries, notably #1c (domain
-     controllers) return the PDC in iplist[0] and then all domain
-     controllers including the PDC in iplist[1..n].  Iterating over
-     the iplist when the PDC is down will cause two sets of timeouts. */
+  done:
 
-  if ( *return_count ) {
-    *return_count = remove_duplicate_addrs2( *return_iplist, *return_count );
-  }
+               /* Remove duplicate entries.  Some queries, notably #1c (domain
+                       controllers) return the PDC in iplist[0] and then all domain
+                       controllers including the PDC in iplist[1..n].  Iterating over
+                       the iplist when the PDC is down will cause two sets of timeouts. */
+
+               if ( *return_count ) {
+                       *return_count = remove_duplicate_addrs2( *return_iplist, *return_count );
+               }
  
-  /* Save in name cache */
-  if ( DEBUGLEVEL >= 100 ) {
-    for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++)
-      DEBUG(100, ("Storing name %s of type %d (%s:%d)\n", name,
-                name_type, inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port));
-  }
+               /* Save in name cache */
+               if ( DEBUGLEVEL >= 100 ) {
+                       for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++)
+                               DEBUG(100, ("Storing name %s of type %d (%s:%d)\n", name,
+                                       name_type, inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port));
+               }
    
-  namecache_store(name, name_type, *return_count, *return_iplist);
-
-  /* Display some debugging info */
+               namecache_store(name, name_type, *return_count, *return_iplist);
 
-  if ( DEBUGLEVEL >= 10 ) {
-    DEBUG(10, ("internal_resolve_name: returning %d addresses: ", 
-              *return_count));
+               /* Display some debugging info */
 
-    for (i = 0; i < *return_count; i++)
-         DEBUGADD(10, ("%s:%d ", inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port));
+               if ( DEBUGLEVEL >= 10 ) {
+                       DEBUG(10, ("internal_resolve_name: returning %d addresses: ", *return_count));
 
-    DEBUG(10, ("\n"));
-  }
+                       for (i = 0; i < *return_count; i++) {
+                               DEBUGADD(10, ("%s:%d ", inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port));
+                       }
+                       DEBUG(10, ("\n"));
+               }
+       }
   
-  return result;
+       return result;
 }
 
 /********************************************************
@@ -1218,8 +1215,9 @@ BOOL get_pdc_ip(const char *domain, struct in_addr *ip)
 
        /* Look up #1B name */
 
-       if (!internal_resolve_name(domain, 0x1b, &ip_list, &count, lp_name_resolve_order()))
+       if (!internal_resolve_name(domain, 0x1b, &ip_list, &count, lp_name_resolve_order())) {
                return False;
+       }
 
        /* if we get more than 1 IP back we have to assume it is a
           multi-homed PDC and not a mess up */
@@ -1298,16 +1296,17 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
                                        num_addresses += auto_count;
                                done_auto_lookup = True;
                                DEBUG(8,("Adding %d DC's from auto lookup\n", auto_count));
-                       }
-                       else 
+                       } else  {
                                num_addresses++;
+                       }
                }
 
                /* if we have no addresses and haven't done the auto lookup, then
                   just return the list of DC's */
                   
-               if ( (num_addresses == 0) && !done_auto_lookup )
+               if ( (num_addresses == 0) && !done_auto_lookup ) {
                        return internal_resolve_name(domain, 0x1C, ip_list, count, resolve_order);
+               }
 
                /* maybe we just failed? */
                
@@ -1317,8 +1316,7 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
                }
                
                if ( (return_iplist = (struct ip_service *)
-                       malloc(num_addresses * sizeof(struct ip_service))) == NULL ) 
-               {
+                               malloc(num_addresses * sizeof(struct ip_service))) == NULL ) {
                        DEBUG(3,("get_dc_list: malloc fail !\n"));
                        return False;
                }
@@ -1335,6 +1333,13 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
                        
                        if ( strequal(name, "*") ) {
                                for ( j=0; j<auto_count; j++ ) {
+                                       /* Check for and don't copy any known bad DC IP's. */
+                                       if(!NT_STATUS_IS_OK(check_negative_conn_cache(domain, 
+                                                       inet_ntoa(auto_ip_list[j].ip)))) {
+                                               DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n",
+                                                       inet_ntoa(auto_ip_list[j].ip) ));
+                                               continue;
+                                       }
                                        return_iplist[local_count].ip   = auto_ip_list[j].ip;
                                        return_iplist[local_count].port = auto_ip_list[j].port;
                                        local_count++;
@@ -1356,6 +1361,13 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
 
                        /* explicit lookup; resolve_name() will handle names & IP addresses */
                        if ( resolve_name( name, &name_ip, 0x20 ) ) {
+
+                               /* Check for and don't copy any known bad DC IP's. */
+                               if( !NT_STATUS_IS_OK(check_negative_conn_cache(domain, inet_ntoa(name_ip))) ) {
+                                       DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n",name ));
+                                       continue;
+                               }
+
                                return_iplist[local_count].ip   = name_ip;
                                return_iplist[local_count].port = port;
                                local_count++;
@@ -1368,8 +1380,9 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
                /* need to remove duplicates in the list if we have any 
                   explicit password servers */
                   
-               if ( local_count )
+               if ( local_count ) {
                        local_count = remove_duplicate_addrs2( return_iplist, local_count );
+               }
                
                if ( DEBUGLEVEL >= 4 ) {
                        DEBUG(4,("get_dc_list: returning %d ip addresses in an %sordered list\n", local_count, 
@@ -1392,8 +1405,9 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
 }
 
 /*********************************************************************
- small wrapper function to get the DC list and sort it if neccessary 
+ Small wrapper function to get the DC list and sort it if neccessary.
 *********************************************************************/
+
 BOOL get_sorted_dc_list( const char *domain, struct ip_service **ip_list, int *count, BOOL ads_only )
 {
        BOOL ordered;
@@ -1401,13 +1415,14 @@ BOOL get_sorted_dc_list( const char *domain, struct ip_service **ip_list, int *c
        DEBUG(8,("get_sorted_dc_list: attempting lookup using [%s]\n",
                (ads_only ? "ads" : lp_name_resolve_order())));
        
-       if ( !get_dc_list(domain, ip_list, count, ads_only, &ordered) )
-               return False;
+       if ( !get_dc_list(domain, ip_list, count, ads_only, &ordered) ) {
+               return False; 
+       }
                
        /* only sort if we don't already have an ordered list */
-       if ( !ordered )
+       if ( !ordered ) {
                sort_ip_list2( *ip_list, *count );
+       }
                
        return True;
 }
-
index 52e5cd004ff3176816ad5d4867bbded90893cccd..66d48afc4633a528326128d5686ca3590b3dacfe 100644 (file)
@@ -1102,8 +1102,6 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state)
                NTLMSSP_NEGOTIATE_NTLM |
                NTLMSSP_NEGOTIATE_NTLM2 |
                NTLMSSP_NEGOTIATE_KEY_EXCH |
-               NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED |
-               NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED |
                /*
                 * We need to set this to allow a later SetPassword
                 * via the SAMR pipe to succeed. Strange.... We could
index 7130453c0c9bc0964b9fe46790b82bba381c4d25..8c59e49ebb973f411bca990e89df7193487ecf40 100644 (file)
@@ -42,11 +42,18 @@ struct smb_basic_signing_context {
        struct outstanding_packet_lookup *outstanding_packet_list;
 };
 
-static void store_sequence_for_reply(struct outstanding_packet_lookup **list, 
+static BOOL store_sequence_for_reply(struct outstanding_packet_lookup **list, 
                                     uint16 mid, uint32 reply_seq_num)
 {
        struct outstanding_packet_lookup *t;
 
+       /* Ensure we only add a mid once. */
+       for (t = *list; t; t = t->next) {
+               if (t->mid == mid) {
+                       return False;
+               }
+       }
+
        t = smb_xmalloc(sizeof(*t));
        ZERO_STRUCTP(t);
 
@@ -65,6 +72,7 @@ static void store_sequence_for_reply(struct outstanding_packet_lookup **list,
        DLIST_ADD(*list, t);
        DEBUG(10,("store_sequence_for_reply: stored seq = %u mid = %u\n",
                        (unsigned int)reply_seq_num, (unsigned int)mid ));
+       return True;
 }
 
 static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list,
@@ -489,6 +497,7 @@ BOOL cli_simple_set_signing(struct cli_state *cli,
 void cli_signing_trans_start(struct cli_state *cli, uint16 mid)
 {
        struct smb_basic_signing_context *data = cli->sign_info.signing_context;
+       uint32 reply_seq_num;
 
        if (!cli->sign_info.doing_signing || !data)
                return;
@@ -496,9 +505,16 @@ void cli_signing_trans_start(struct cli_state *cli, uint16 mid)
        data->trans_info = smb_xmalloc(sizeof(struct trans_info_context));
        ZERO_STRUCTP(data->trans_info);
 
-       data->trans_info->send_seq_num = data->send_seq_num-2;
+       /* This ensures the sequence is pulled off the outstanding packet list */
+       if (!get_sequence_for_reply(&data->outstanding_packet_list, 
+                                   mid, &reply_seq_num)) {
+               DEBUG(1, ("get_sequence_for_reply failed - did we enter the trans signing state without sending a packet?\n")); 
+           return;
+       }
+
+       data->trans_info->send_seq_num = reply_seq_num - 1;
        data->trans_info->mid = mid;
-       data->trans_info->reply_seq_num = data->send_seq_num-1;
+       data->trans_info->reply_seq_num = reply_seq_num;
 
        DEBUG(10,("cli_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
 data->send_seq_num = %u\n",
@@ -748,14 +764,16 @@ static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si, BO
        
        if (!good) {
 
-               DEBUG(5, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n",
-                                       (unsigned int)saved_seq));
-               dump_data(5, (const char *)calc_md5_mac, 8);
-               
-               DEBUG(5, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n",
+               if (saved_seq) {
+                       DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n",
                                        (unsigned int)saved_seq));
-               dump_data(5, (const char *)server_sent_mac, 8);
+                       dump_data(5, (const char *)calc_md5_mac, 8);
 
+                       DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n",
+                                               (unsigned int)reply_seq_number));
+                       dump_data(5, (const char *)server_sent_mac, 8);
+               }
+               
 #if 1 /* JRATEST */
                {
                        int i;
@@ -848,9 +866,13 @@ void srv_defer_sign_response(uint16 mid)
        if (!data)
                return;
 
-       store_sequence_for_reply(&data->outstanding_packet_list, 
-                                mid, data->send_seq_num);
-       data->send_seq_num++;
+       /*
+        * Ensure we only store this mid reply once...
+        */
+
+       if (store_sequence_for_reply(&data->outstanding_packet_list, mid, data->send_seq_num)) {
+               data->send_seq_num++;
+       }
 }
 
 /***********************************************************
index 47001c8b89cdfacd0f3d66102052c7efbb814f8f..990a6a25d2fba201bc09e296662bb9c6cfbcbe4e 100644 (file)
@@ -246,8 +246,8 @@ void brl_init(int read_only)
 {
        if (tdb)
                return;
-       tdb = tdb_open_ex(lock_path("brlock.tdb"), 0,  TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST),
-                      read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644, smbd_tdb_log);
+       tdb = tdb_open_log(lock_path("brlock.tdb"), 0,  TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST),
+                      read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 );
        if (!tdb) {
                DEBUG(0,("Failed to open byte range locking database\n"));
                return;
index 42036cc70cf54aeb6714be8e38d13deef571b0bb..8f53b55fc54a45e93cf53bc5ba97f914dbb78c63 100644 (file)
@@ -40,6 +40,17 @@ uint16 global_smbpid;
 /* the locking database handle */
 static TDB_CONTEXT *tdb;
 
+struct locking_data {
+        union {
+                int num_share_mode_entries;
+                share_mode_entry dummy; /* Needed for alignment. */
+        } u;
+        /* the following two entries are implicit
+           share_mode_entry modes[num_share_mode_entries];
+           char file_name[];
+        */
+};
+
 /****************************************************************************
  Debugging aid :-).
 ****************************************************************************/
@@ -283,10 +294,10 @@ BOOL locking_init(int read_only)
        if (tdb)
                return True;
 
-       tdb = tdb_open_ex(lock_path("locking.tdb"), 
+       tdb = tdb_open_log(lock_path("locking.tdb"), 
                       0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), 
                       read_only?O_RDONLY:O_RDWR|O_CREAT,
-                      0644, smbd_tdb_log);
+                      0644);
 
        if (!tdb) {
                DEBUG(0,("ERROR: Failed to initialise locking database\n"));
@@ -432,6 +443,7 @@ int get_share_modes(connection_struct *conn,
        data = (struct locking_data *)dbuf.dptr;
        num_share_modes = data->u.num_share_mode_entries;
        if(num_share_modes) {
+               pstring fname;
                int i;
                int del_count = 0;
 
@@ -443,6 +455,9 @@ int get_share_modes(connection_struct *conn,
                        return 0;
                }
 
+               /* Save off the associated filename. */
+               pstrcpy(fname, dbuf.dptr + sizeof(*data) + num_share_modes * sizeof(share_mode_entry));
+
                /*
                 * Ensure that each entry has a real process attached.
                 */
@@ -454,8 +469,10 @@ int get_share_modes(connection_struct *conn,
                                i++;
                        } else {
                                DEBUG(10,("get_share_modes: deleted %s\n", share_mode_str(i, entry_p) ));
-                               memcpy( &shares[i], &shares[i+1],
-                                       sizeof(share_mode_entry) * (num_share_modes - i - 1));
+                               if (num_share_modes - i - 1 > 0) {
+                                       memcpy( &shares[i], &shares[i+1],
+                                               sizeof(share_mode_entry) * (num_share_modes - i - 1));
+                               }
                                num_share_modes--;
                                del_count++;
                        }
@@ -465,17 +482,28 @@ int get_share_modes(connection_struct *conn,
                if (del_count) {
                        data->u.num_share_mode_entries = num_share_modes;
                        
-                       if (num_share_modes)
+                       if (num_share_modes) {
                                memcpy(dbuf.dptr + sizeof(*data), shares,
                                                num_share_modes * sizeof(share_mode_entry));
+                               /* Append the filename. */
+                               pstrcpy(dbuf.dptr + sizeof(*data) + num_share_modes * sizeof(share_mode_entry), fname);
+                       }
 
                        /* The record has shrunk a bit */
                        dbuf.dsize -= del_count * sizeof(share_mode_entry);
 
-                       if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) {
-                               SAFE_FREE(shares);
-                               SAFE_FREE(dbuf.dptr);
-                               return 0;
+                       if (data->u.num_share_mode_entries == 0) {
+                               if (tdb_delete(tdb, key) == -1) {
+                                       SAFE_FREE(shares);
+                                       SAFE_FREE(dbuf.dptr);
+                                       return 0;
+                               }
+                       } else {
+                               if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) {
+                                       SAFE_FREE(shares);
+                                       SAFE_FREE(dbuf.dptr);
+                                       return 0;
+                               }
                        }
                }
        }
@@ -575,8 +603,10 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode,
                        if (ppse)
                                *ppse = memdup(&shares[i], sizeof(*shares));
                        data->u.num_share_mode_entries--;
-                       memmove(&shares[i], &shares[i+1], 
-                               dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares)));
+                       if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))) > 0) {
+                               memmove(&shares[i], &shares[i+1], 
+                                       dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares)));
+                       }
                        del_count++;
 
                        DEBUG(10,("del_share_entry: deleting entry %d\n", i ));
@@ -843,6 +873,358 @@ BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close)
        return True;
 }
 
+/*******************************************************************
+ Print out a deferred open entry.
+********************************************************************/
+
+char *deferred_open_str(int num, deferred_open_entry *e)
+{
+       static pstring de_str;
+
+       slprintf(de_str, sizeof(de_str)-1, "deferred_open_entry[%d]: \
+pid = %lu, mid = %u, dev = 0x%x, inode = %.0f, port = %u, time = [%u.%06u]",
+               num, (unsigned long)e->pid, (unsigned int)e->mid, (unsigned int)e->dev, (double)e->inode,
+               (unsigned int)e->port,
+               (unsigned int)e->time.tv_sec, (unsigned int)e->time.tv_usec );
+
+       return de_str;
+}
+
+/* Internal data structures for deferred opens... */
+
+struct de_locking_key {
+       char name[4];
+       SMB_DEV_T dev;
+       SMB_INO_T inode;
+};
+
+struct deferred_open_data {
+        union {
+                int num_deferred_open_entries;
+                deferred_open_entry dummy; /* Needed for alignment. */
+        } u;
+        /* the following two entries are implicit
+           deferred_open_entry de_entries[num_deferred_open_entries];
+           char file_name[];
+        */
+};
+
+/*******************************************************************
+ Print out a deferred open table.
+********************************************************************/
+
+static void print_deferred_open_table(struct deferred_open_data *data)
+{
+       int num_de_entries = data->u.num_deferred_open_entries;
+       deferred_open_entry *de_entries = (deferred_open_entry *)(data + 1);
+       int i;
+
+       for (i = 0; i < num_de_entries; i++) {
+               deferred_open_entry *entry_p = &de_entries[i];
+               DEBUG(10,("print_deferred_open_table: %s\n", deferred_open_str(i, entry_p) ));
+       }
+}
+
+
+/*******************************************************************
+ Form a static deferred open locking key for a dev/inode pair.
+******************************************************************/
+
+static TDB_DATA deferred_open_locking_key(SMB_DEV_T dev, SMB_INO_T inode)
+{
+       static struct de_locking_key key;
+       TDB_DATA kbuf;
+
+       memset(&key, '\0', sizeof(key));
+       memcpy(&key.name[0], "DOE", 4);
+       key.dev = dev;
+       key.inode = inode;
+       kbuf.dptr = (char *)&key;
+       kbuf.dsize = sizeof(key);
+       return kbuf;
+}
+
+/*******************************************************************
+ Get all deferred open entries for a dev/inode pair.
+********************************************************************/
+
+int get_deferred_opens(connection_struct *conn, 
+                   SMB_DEV_T dev, SMB_INO_T inode, 
+                   deferred_open_entry **pp_de_entries)
+{
+       TDB_DATA dbuf;
+       struct deferred_open_data *data;
+       int num_de_entries;
+       deferred_open_entry *de_entries = NULL;
+       TDB_DATA key = deferred_open_locking_key(dev, inode);
+
+       *pp_de_entries = NULL;
+
+       dbuf = tdb_fetch(tdb, key);
+       if (!dbuf.dptr)
+               return 0;
+
+       data = (struct deferred_open_data *)dbuf.dptr;
+       num_de_entries = data->u.num_deferred_open_entries;
+       if(num_de_entries) {
+               pstring fname;
+               int i;
+               int del_count = 0;
+
+               de_entries = (deferred_open_entry *)memdup(dbuf.dptr + sizeof(*data),   
+                                               num_de_entries * sizeof(deferred_open_entry));
+
+               if (!de_entries) {
+                       SAFE_FREE(dbuf.dptr);
+                       return 0;
+               }
+
+               /* Save off the associated filename. */
+               pstrcpy(fname, dbuf.dptr + sizeof(*data) + num_de_entries * sizeof(deferred_open_entry));
+
+               /*
+                * Ensure that each entry has a real process attached.
+                */
+
+               for (i = 0; i < num_de_entries; ) {
+                       deferred_open_entry *entry_p = &de_entries[i];
+                       if (process_exists(entry_p->pid)) {
+                               DEBUG(10,("get_deferred_opens: %s\n", deferred_open_str(i, entry_p) ));
+                               i++;
+                       } else {
+                               DEBUG(10,("get_deferred_opens: deleted %s\n", deferred_open_str(i, entry_p) ));
+                               if (num_de_entries - i - 1 > 0) {
+                                       memcpy( &de_entries[i], &de_entries[i+1],
+                                               sizeof(deferred_open_entry) * (num_de_entries - i - 1));
+                               }
+                               num_de_entries--;
+                               del_count++;
+                       }
+               }
+
+               /* Did we delete any ? If so, re-store in tdb. */
+               if (del_count) {
+                       data->u.num_deferred_open_entries = num_de_entries;
+                       
+                       if (num_de_entries) {
+                               memcpy(dbuf.dptr + sizeof(*data), de_entries,
+                                               num_de_entries * sizeof(deferred_open_entry));
+                               /* Append the filename. */
+                               pstrcpy(dbuf.dptr + sizeof(*data) + num_de_entries * sizeof(deferred_open_entry), fname);
+                       }
+
+                       /* The record has shrunk a bit */
+                       dbuf.dsize -= del_count * sizeof(deferred_open_entry);
+
+                       if (data->u.num_deferred_open_entries == 0) {
+                               if (tdb_delete(tdb, key) == -1) {
+                                       SAFE_FREE(de_entries);
+                                       SAFE_FREE(dbuf.dptr);
+                                       return 0;
+                               }
+                       } else {
+                               if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) {
+                                       SAFE_FREE(de_entries);
+                                       SAFE_FREE(dbuf.dptr);
+                                       return 0;
+                               }
+                       }
+               }
+       }
+
+       SAFE_FREE(dbuf.dptr);
+       *pp_de_entries = de_entries;
+       return num_de_entries;
+}
+
+/*******************************************************************
+ Check if two deferred open entries are identical.
+********************************************************************/
+
+static BOOL deferred_open_entries_identical( deferred_open_entry *e1, deferred_open_entry *e2)
+{
+#if 1 /* JRA PARANOIA TEST - REMOVE LATER */
+       if (e1->pid == e2->pid &&
+               e1->port == e2->port &&
+               e1->dev == e2->dev &&
+               e1->inode == e2->inode &&
+               ((e1->time.tv_sec != e2->time.tv_sec) ||
+                (e1->time.tv_usec != e2->time.tv_usec) ||
+                (e1->mid != e2->mid))) {
+               smb_panic("PANIC: deferred_open_entries_identical: logic error.\n");
+       }
+#endif
+
+       return (e1->pid == e2->pid &&
+               e1->mid == e2->mid &&
+               e1->port == e2->port &&
+               e1->dev == e2->dev &&
+               e1->inode == e2->inode &&
+               e1->time.tv_sec == e2->time.tv_sec &&
+               e1->time.tv_usec == e2->time.tv_usec);
+}
+
+
+/*******************************************************************
+ Delete a specific deferred open entry.
+ Ignore if no entry deleted.
+********************************************************************/
+
+BOOL delete_deferred_open_entry(deferred_open_entry *entry)
+{
+       TDB_DATA dbuf;
+       struct deferred_open_data *data;
+       int i, del_count=0;
+       deferred_open_entry *de_entries;
+       BOOL ret = True;
+       TDB_DATA key = deferred_open_locking_key(entry->dev, entry->inode);
+
+       /* read in the existing share modes */
+       dbuf = tdb_fetch(tdb, key);
+       if (!dbuf.dptr)
+               return -1;
+
+       data = (struct deferred_open_data *)dbuf.dptr;
+       de_entries = (deferred_open_entry *)(dbuf.dptr + sizeof(*data));
+
+       /*
+        * Find any with this pid and delete it
+        * by overwriting with the rest of the data 
+        * from the record.
+        */
+
+       DEBUG(10,("delete_deferred_open_entry: num_deferred_open_entries = %d\n",
+               data->u.num_deferred_open_entries ));
+
+       for (i=0;i<data->u.num_deferred_open_entries;) {
+               if (deferred_open_entries_identical(&de_entries[i], entry)) {
+                       DEBUG(10,("delete_deferred_open_entry: deleted %s\n",
+                               deferred_open_str(i, &de_entries[i]) ));
+
+                       data->u.num_deferred_open_entries--;
+                       if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*de_entries))) > 0) {
+                               memmove(&de_entries[i], &de_entries[i+1], 
+                                       dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*de_entries)));
+                       }
+                       del_count++;
+
+                       DEBUG(10,("delete_deferred_open_entry: deleting entry %d\n", i ));
+
+               } else {
+                       i++;
+               }
+       }
+
+       SMB_ASSERT(del_count == 0 || del_count == 1);
+
+       if (del_count) {
+               /* the record may have shrunk a bit */
+               dbuf.dsize -= del_count * sizeof(*de_entries);
+
+               /* store it back in the database */
+               if (data->u.num_deferred_open_entries == 0) {
+                       if (tdb_delete(tdb, key) == -1)
+                               ret = False;
+               } else {
+                       if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1)
+                               ret = False;
+               }
+       }
+       DEBUG(10,("delete_deferred_open_entry: Remaining table.\n"));
+       print_deferred_open_table((struct deferred_open_data*)dbuf.dptr);
+       SAFE_FREE(dbuf.dptr);
+       return ret;
+}
+
+/*******************************************************************
+ Fill a deferred open entry.
+********************************************************************/
+
+static void fill_deferred_open(char *p, uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T inode, uint16 port)
+{
+       deferred_open_entry *e = (deferred_open_entry *)p;
+       void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */
+
+       memset(e, '\0', sizeof(deferred_open_entry));
+       e->mid = mid;
+       e->pid = sys_getpid();
+       memcpy(x, ptv, sizeof(struct timeval));
+       e->dev = dev;
+       e->inode = inode;
+       e->port = port;
+}
+
+/*******************************************************************
+ Add a deferred open record. Return False on fail, True on success.
+********************************************************************/
+
+BOOL add_deferred_open(uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T inode, uint16 port, const char *fname)
+{
+       TDB_DATA dbuf;
+       struct deferred_open_data *data;
+       char *p=NULL;
+       int size;
+       TDB_DATA key = deferred_open_locking_key(dev, inode);
+       BOOL ret = True;
+               
+       /* read in the existing deferred open records if any */
+       dbuf = tdb_fetch(tdb, key);
+       if (!dbuf.dptr) {
+               size_t offset;
+               /* we'll need to create a new record */
+
+               size = sizeof(*data) + sizeof(deferred_open_entry) + strlen(fname) + 1;
+               p = (char *)malloc(size);
+               if (!p)
+                       return False;
+               data = (struct deferred_open_data *)p;
+               data->u.num_deferred_open_entries = 1;
+       
+               DEBUG(10,("add_deferred_open: creating entry for file %s. num_deferred_open_entries = 1\n",
+                       fname ));
+
+               offset = sizeof(*data) + sizeof(deferred_open_entry);
+               safe_strcpy(p + offset, fname, size - offset - 1);
+               fill_deferred_open(p + sizeof(*data), mid, ptv, dev, inode, port);
+               dbuf.dptr = p;
+               dbuf.dsize = size;
+               if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1)
+                       ret = False;
+
+               print_deferred_open_table((struct deferred_open_data *)p);
+
+               SAFE_FREE(p);
+               return ret;
+       }
+
+       /* we're adding to an existing entry - this is a bit fiddly */
+       data = (struct deferred_open_data *)dbuf.dptr;
+
+       data->u.num_deferred_open_entries++;
+       
+       DEBUG(10,("add_deferred_open: adding entry for file %s. new num_deferred_open_entries = %d\n",
+               fname, data->u.num_deferred_open_entries ));
+
+       size = dbuf.dsize + sizeof(deferred_open_entry);
+       p = malloc(size);
+       if (!p) {
+               SAFE_FREE(dbuf.dptr);
+               return False;
+       }
+       memcpy(p, dbuf.dptr, sizeof(*data));
+       fill_deferred_open(p + sizeof(*data), mid, ptv, dev, inode, port);
+       memcpy(p + sizeof(*data) + sizeof(deferred_open_entry), dbuf.dptr + sizeof(*data),
+              dbuf.dsize - sizeof(*data));
+       SAFE_FREE(dbuf.dptr);
+       dbuf.dptr = p;
+       dbuf.dsize = size;
+       if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1)
+               ret = False;
+       print_deferred_open_table((struct deferred_open_data *)p);
+       SAFE_FREE(p);
+       return ret;
+}
+
 /****************************************************************************
  Traverse the whole database with this function, calling traverse_callback
  on each share mode
@@ -858,6 +1240,10 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
 
        SHAREMODE_FN(traverse_callback) = (SHAREMODE_FN_CAST())state;
 
+       /* Ensure this is a locking_key record. */
+       if (kbuf.dsize != sizeof(struct locking_key))
+               return 0;
+
        data = (struct locking_data *)dbuf.dptr;
        shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
        name = dbuf.dptr + sizeof(*data) + data->u.num_share_mode_entries*sizeof(*shares);
index 15827e21bae613f87b739ad8f1efcba5cdb5519b..56ffdc2670f52a06f28611d1d036618f13ac630b 100644 (file)
@@ -103,6 +103,7 @@ static void announce_local_master_browser_to_domain_master_browser( struct work_
 {
        pstring outbuf;
        unstring myname;
+       unstring dmb_name;
        char *p;
 
        if(ismyip(work->dmb_addr)) {
@@ -135,8 +136,10 @@ static void announce_local_master_browser_to_domain_master_browser( struct work_
                                        work->work_group );
        }
 
+       /* Target name for send_mailslot must be in UNIX charset. */
+       pull_ascii_nstring(dmb_name, sizeof(dmb_name), work->dmb_name.name);
        send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
-               global_myname(), 0x0, work->dmb_name.name, 0x0, 
+               global_myname(), 0x0, dmb_name, 0x0, 
                work->dmb_addr, FIRST_SUBNET->myip, DGRAM_PORT);
 }
 
index 582338d710a97871188d55a5b2df18249a886747..0e0289d9a331c496b3137cd68065d212085c6b67 100644 (file)
@@ -1727,11 +1727,16 @@ void initiate_wins_processing(time_t t)
                     && (namerec->data.death_time < t) ) {
 
                        if( namerec->data.source == SELF_NAME ) {
-                               DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF name %s\n", 
+                               DEBUG( 3, ( "initiate_wins_processing: Subnet %s not expiring SELF name %s\n", 
                                           wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
                                namerec->data.death_time += 300;
                                namerec->subnet->namelist_changed = True;
                                continue;
+                       } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
+                               DEBUG(3,("initiate_wins_processing: deleting timed out DNS name %s\n",
+                                               nmb_namestr(&namerec->name)));
+                               remove_name_from_namelist( wins_server_subnet, namerec );
+                               continue;
                        }
 
                        /* handle records, samba is the wins owner */
index a98bd294064397d6bb7e5e7d87fcf7e9128a9246..50b6f0a87fb2c0d03aa2d85c63f430e2fff5ea52 100644 (file)
@@ -869,16 +869,13 @@ int main(int argc, char **argv)
 
        ZERO_STRUCT(server_state);
 
-       if (!winbindd_param_init())
-               return 1;
-
        /* Winbind daemon initialisation */
 
-       if (!winbindd_upgrade_idmap())
-               return 1;
-
-       if (!idmap_init(lp_idmap_backend()))
-               return 1;
+       if ( (!winbindd_param_init()) || (!winbindd_upgrade_idmap()) ||
+            (!idmap_init(lp_idmap_backend())) ) {
+               DEBUG(1, ("Could not init idmap -- netlogon proxy only\n"));
+               idmap_proxyonly();
+       }
 
        generate_wellknown_sids();
 
index 877fa2d995c15d4f940c94495e56884b4766db4f..bbd98a620f6b8317e94464464156eec86f168004 100644 (file)
@@ -363,6 +363,12 @@ static void refresh_sequence_number(struct winbindd_domain *domain, BOOL force)
        if ( NT_STATUS_IS_OK(status) )
                goto done;      
 
+       /* important! make sure that we know if this is a native 
+          mode domain or not */
+
+       if ( !domain->initialized )
+               set_dc_type_and_flags( domain );
+
        status = domain->backend->sequence_number(domain, &domain->sequence_number);
 
        if (!NT_STATUS_IS_OK(status)) {
index eda962088d468c22d081a4a13b7f18774d946a3b..04f87fc1a2fa59ce5144199bd027bdbae40337ee 100644 (file)
@@ -117,21 +117,40 @@ static void cm_get_ipc_userpass(char **username, char **domain, char **password)
 /*
   setup for schannel on any pipes opened on this connection
 */
-static NTSTATUS setup_schannel(struct cli_state *cli)
+static NTSTATUS setup_schannel( struct cli_state *cli, const char *domain )
 {
        NTSTATUS ret;
        uchar trust_password[16];
        uint32 sec_channel_type;
+       DOM_SID sid;
+       time_t lct;
 
-       if (!secrets_fetch_trust_account_password(lp_workgroup(),
-                                                 trust_password,
-                                                 NULL, &sec_channel_type)) {
-               return NT_STATUS_UNSUCCESSFUL;
+       /* use the domain trust password if we're on a DC 
+          and this is not our domain */
+       
+       if ( IS_DC && !strequal(domain, lp_workgroup()) ) {
+               char *pass = NULL;
+               
+               if ( !secrets_fetch_trusted_domain_password( domain, 
+                       &pass, &sid, &lct) )
+               {
+                       return NT_STATUS_UNSUCCESSFUL;
+               }       
+
+               sec_channel_type = SEC_CHAN_DOMAIN;
+               E_md4hash(pass, trust_password);
+               SAFE_FREE( pass );
+               
+       } else {
+               if (!secrets_fetch_trust_account_password(lp_workgroup(),
+                       trust_password, NULL, &sec_channel_type)) 
+               {
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
        }
 
        ret = cli_nt_setup_netsec(cli, sec_channel_type, 
-                                 AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN, 
-                                 trust_password);
+               AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN, trust_password);
 
        return ret;
 }
@@ -216,7 +235,8 @@ static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const i
        /* Initialise SMB connection */
        fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index));
 
-/* grab stored passwords */
+       /* grab stored passwords */
+       
        machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
        
        if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(), lp_realm()) == -1) {
@@ -335,9 +355,13 @@ static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const i
        /* try and use schannel if possible, but continue anyway if it
           failed. This allows existing setups to continue working,
           while solving the win2003 '100 user' limit for systems that
-          are joined properly */
-       if (NT_STATUS_IS_OK(result) && (domain->primary)) {
-               NTSTATUS status = setup_schannel(new_conn->cli);
+          are joined properly.
+       
+          Only do this for our own domain or perhaps a trusted domain
+          if we are on a Samba DC */
+
+       if (NT_STATUS_IS_OK(result) && (domain->primary || IS_DC) ) {
+               NTSTATUS status = setup_schannel( new_conn->cli, domain->name );
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(3,("schannel refused - continuing without schannel (%s)\n", 
                                 nt_errstr(status)));
index 7b4529144e270172dfa8bb0781a35d6bbaf023f4..346a2711b6c8b75aa8a13f6e5b4416e3b4d5c954 100644 (file)
@@ -942,16 +942,14 @@ static void add_gid_to_array_unique(gid_t gid, gid_t **gids, int *num)
        *num += 1;
 }
 
-static void add_gids_from_sid(DOM_SID *sid, gid_t **gids, int *num)
+static void add_local_gids_from_sid(DOM_SID *sid, gid_t **gids, int *num)
 {
        gid_t gid;
        DOM_SID *aliases;
        int j, num_aliases;
 
-       DEBUG(10, ("Adding gids from SID: %s\n", sid_string_static(sid)));
-
-       if (NT_STATUS_IS_OK(idmap_sid_to_gid(sid, &gid, 0)))
-               add_gid_to_array_unique(gid, gids, num);
+       DEBUG(10, ("Adding local gids from SID: %s\n",
+                  sid_string_static(sid)));
 
        /* Don't expand aliases if not explicitly activated -- for now
           -- jerry */
@@ -965,15 +963,44 @@ static void add_gids_from_sid(DOM_SID *sid, gid_t **gids, int *num)
                return;
 
        for (j=0; j<num_aliases; j++) {
+               enum SID_NAME_USE type;
+
+               if (!local_sid_to_gid(&gid, &aliases[j], &type)) {
+                       DEBUG(1, ("Got an alias membership with no alias\n"));
+                       continue;
+               }
 
-               if (!NT_STATUS_IS_OK(sid_to_gid(&aliases[j], &gid)))
+               if ((type != SID_NAME_ALIAS) && (type != SID_NAME_WKN_GRP)) {
+                       DEBUG(1, ("Got an alias membership in a non-alias\n"));
                        continue;
+               }
 
                add_gid_to_array_unique(gid, gids, num);
        }
        SAFE_FREE(aliases);
 }
 
+static void add_gids_from_user_sid(DOM_SID *sid, gid_t **gids, int *num)
+{
+       DEBUG(10, ("Adding gids from user SID: %s\n",
+                  sid_string_static(sid)));
+
+       add_local_gids_from_sid(sid, gids, num);
+}
+
+static void add_gids_from_group_sid(DOM_SID *sid, gid_t **gids, int *num)
+{
+       gid_t gid;
+
+       DEBUG(10, ("Adding gids from group SID: %s\n",
+                  sid_string_static(sid)));
+
+       if (NT_STATUS_IS_OK(idmap_sid_to_gid(sid, &gid, 0)))
+               add_gid_to_array_unique(gid, gids, num);
+
+       add_local_gids_from_sid(sid, gids, num);
+}
+
 /* Get user supplementary groups.  This is much quicker than trying to
    invert the groups database.  We merge the groups from the gids and
    other_sids info3 fields as trusted domain, universal group
@@ -1039,7 +1066,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
                goto done;
        }
 
-       add_gids_from_sid(&user_sid, &gid_list, &num_gids);
+       add_gids_from_user_sid(&user_sid, &gid_list, &num_gids);
 
        /* Treat the info3 cache as authoritative as the
           lookup_usergroups() function may return cached data. */
@@ -1083,8 +1110,8 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
                                continue;
                        }
 
-                       add_gids_from_sid(&info3->other_sids[i].sid,
-                                         &gid_list, &num_gids);
+                       add_gids_from_group_sid(&info3->other_sids[i].sid,
+                                               &gid_list, &num_gids);
 
                        if (gid_list == NULL)
                                goto done;
@@ -1097,7 +1124,8 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
                        sid_copy( &group_sid, &domain->sid );
                        sid_append_rid( &group_sid, info3->gids[i].g_rid );
 
-                       add_gids_from_sid(&group_sid, &gid_list, &num_gids);
+                       add_gids_from_group_sid(&group_sid, &gid_list,
+                                               &num_gids);
 
                        if (gid_list == NULL)
                                goto done;
@@ -1116,8 +1144,8 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
                        goto done;
 
                for (i = 0; i < num_groups; i++) {
-                       add_gids_from_sid(user_grpsids[i],
-                                         &gid_list, &num_gids);
+                       add_gids_from_group_sid(user_grpsids[i],
+                                               &gid_list, &num_gids);
 
                        if (gid_list == NULL)
                                goto done;
index 12f5e0bae2e8aca1b62617e954abad9c12dfd3d2..3adb81caa354eaffc63ec5d455e91b3e705d5482 100644 (file)
@@ -240,7 +240,11 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
        if (!pdb_find_alias(name, sid))
                return NT_STATUS_NONE_MAPPED;
 
-       *type = SID_NAME_ALIAS;
+       if (sid_check_is_in_builtin(sid))
+               *type = SID_NAME_WKN_GRP;
+       else
+               *type = SID_NAME_ALIAS;
+
        return NT_STATUS_OK;
 }
 
@@ -263,7 +267,10 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
 
        *domain_name = talloc_strdup(mem_ctx, domain->name);
        *name = talloc_strdup(mem_ctx, info.acct_name);
-       *type = SID_NAME_ALIAS;
+       if (sid_check_is_in_builtin(sid))
+               *type = SID_NAME_WKN_GRP;
+       else
+               *type = SID_NAME_ALIAS;
 
        return NT_STATUS_OK;
 }
index 76688449209d9dd2ae0ee6eb7abba1a329836240..ba24749fbef07cd036c48a9e6580d14d6148815f 100644 (file)
@@ -707,36 +707,6 @@ done:
 
 #include <ldap.h>
 
-static SIG_ATOMIC_T gotalarm;
-
-/***************************************************************
- Signal function to tell us we timed out.
-****************************************************************/
-
-static void gotalarm_sig(void)
-{
-       gotalarm = 1;
-}
-
-static LDAP *ldap_open_with_timeout(const char *server, int port, unsigned int to)
-{
-       LDAP *ldp = NULL;
-
-       /* Setup timeout */
-       gotalarm = 0;
-       CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
-       alarm(to);
-       /* End setup timeout. */
-
-       ldp = ldap_open(server, port);
-
-       /* Teardown timeout. */
-       CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
-       alarm(0);
-
-       return ldp;
-}
-
 static int get_ldap_seq(const char *server, int port, uint32 *seq)
 {
        int ret = -1;
@@ -749,11 +719,11 @@ static int get_ldap_seq(const char *server, int port, uint32 *seq)
        *seq = DOM_SEQUENCE_NONE;
 
        /*
-        * 10 second timeout on open. This is needed as the search timeout
+        * Parameterised (5) second timeout on open. This is needed as the search timeout
         * doesn't seem to apply to doing an open as well. JRA.
         */
 
-       if ((ldp = ldap_open_with_timeout(server, port, 10)) == NULL)
+       if ((ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout())) == NULL)
                return -1;
 
        /* Timeout if no response within 20 seconds. */
index 96b8ed8c93881c1a6c9e598477ac6512205b808d..faa6e8d8da45720f3663d7cacafd6fcd33bb540f 100644 (file)
@@ -175,7 +175,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
        /* Link to domain list */
        DLIST_ADD(_domain_list, domain);
         
-       DEBUG(1,("Added domain %s %s %s\n", 
+       DEBUG(2,("Added domain %s %s %s\n", 
                 domain->name, domain->alt_name,
                 &domain->sid?sid_string_static(&domain->sid):""));
         
index 6376e4aa9172f16721797babaecf1176d3858909..0710c36514b2e2afe34b6ab62ba83a45e92b3737 100644 (file)
@@ -231,8 +231,10 @@ typedef struct
        char *szLdapFilter;
        char *szLdapAdminDn;
        char *szAclCompat;
+       char *szCupsServer;
        int ldap_passwd_sync; 
        int ldap_replication_sleep;
+       int ldap_timeout; /* This is initialised in init_globals */
        BOOL ldap_delete_dn;
        BOOL bMsAddPrinterWizard;
        BOOL bDNSproxy;
@@ -286,6 +288,8 @@ typedef struct
        BOOL bUnixExtensions;
        BOOL bDisableNetbios;
        BOOL bKernelChangeNotify;
+       BOOL bUseKerberosKeytab;
+       BOOL bDeferSharingViolations;
        int restrict_anonymous;
        int name_cache_timeout;
        int client_signing;
@@ -363,7 +367,7 @@ typedef struct
        int iBlock_size;
        BOOL bPreexecClose;
        BOOL bRootpreexecClose;
-       BOOL bCaseSensitive;
+       int  iCaseSensitive;
        BOOL bCasePreserve;
        BOOL bShortCasePreserve;
        BOOL bHideDotFiles;
@@ -410,6 +414,7 @@ typedef struct
        BOOL bUseClientDriver;
        BOOL bDefaultDevmode;
        BOOL bNTAclSupport;
+       BOOL bForceUnknownAclUser;
        BOOL bUseSendfile;
        BOOL bProfileAcls;
        BOOL bMap_acl_inherit;
@@ -486,7 +491,7 @@ static service sDefault = {
        1024,           /* iBlock_size */
        False,                  /* bPreexecClose */
        False,                  /* bRootpreexecClose */
-       False,                  /* case sensitive */
+       Auto,                   /* case sensitive */
        True,                   /* case preserve */
        True,                   /* short case preserve */
        True,                   /* bHideDotFiles */
@@ -533,7 +538,8 @@ static service sDefault = {
        False,                  /* bUseClientDriver */
        False,                  /* bDefaultDevmode */
        True,                   /* bNTAclSupport */
-       False,                  /* bUseSendfile */
+       False,                  /* bForceUnknownAclUser */
+       True,                   /* bUseSendfile */
        False,                  /* bProfileAcls */
        False,                  /* bMap_acl_inherit */
        False,                  /* bAfs_Share */
@@ -846,6 +852,7 @@ static struct parm_struct parm_table[] = {
        {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
        {"directory security mask", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
        {"force directory security mode", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
+       {"force unknown acl user", P_BOOL, P_LOCAL, &sDefault.bForceUnknownAclUser, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
        {"inherit permissions", P_BOOL, P_LOCAL, &sDefault.bInheritPerms, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
        {"inherit acls", P_BOOL, P_LOCAL, &sDefault.bInheritACLS, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
        {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
@@ -860,6 +867,7 @@ static struct parm_struct parm_table[] = {
        {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
        {"deny hosts", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_HIDE}, 
        {"preload modules", P_LIST, P_GLOBAL, &Globals.szPreloadModules, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
+       {"use kerberos keytab", P_BOOL, P_GLOBAL, &Globals.bUseKerberosKeytab, NULL, NULL, FLAG_ADVANCED}, 
 
        {N_("Logging Options"), P_SEP, P_SEPARATOR}, 
 
@@ -889,6 +897,7 @@ static struct parm_struct parm_table[] = {
        {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED}, 
 
        {"acl compatibility", P_STRING, P_GLOBAL, &Globals.szAclCompat, handle_acl_compatibility,  NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
+       { "defer sharing violations", P_BOOL, P_GLOBAL, &Globals.bDeferSharingViolations, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL},
        {"ea support", P_BOOL, P_LOCAL, &sDefault.bEASupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
        {"nt acl support", P_BOOL, P_LOCAL, &sDefault.bNTAclSupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
        {"nt pipe support", P_BOOL, P_GLOBAL, &Globals.bNTPipeSupport, NULL, NULL, FLAG_ADVANCED}, 
@@ -953,6 +962,7 @@ static struct parm_struct parm_table[] = {
        {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE}, 
        {"printing", P_ENUM, P_LOCAL, &sDefault.iPrinting, handle_printing, enum_printing, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
        {"cups options", P_STRING, P_LOCAL, &sDefault.szCupsOptions, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
+       {"cups server", P_STRING, P_GLOBAL, &Globals.szCupsServer, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
        {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
        {"disable spoolss", P_BOOL, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
        {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
@@ -978,8 +988,8 @@ static struct parm_struct parm_table[] = {
        {"mangle prefix", P_INTEGER, P_GLOBAL, &Globals.mangle_prefix, NULL, NULL, FLAG_ADVANCED}, 
 
        {"default case", P_ENUM, P_LOCAL, &sDefault.iDefaultCase, NULL, enum_case, FLAG_ADVANCED | FLAG_SHARE}, 
-       {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
-       {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL, NULL, FLAG_HIDE}, 
+       {"case sensitive", P_ENUM, P_LOCAL, &sDefault.iCaseSensitive, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
+       {"casesignames", P_ENUM, P_LOCAL, &sDefault.iCaseSensitive, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_HIDE}, 
        {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
        {"short preserve case", P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
        {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
@@ -1070,17 +1080,18 @@ static struct parm_struct parm_table[] = {
        {"ldap server", P_STRING, P_GLOBAL, &Globals.szLdapServer, NULL, NULL, FLAG_ADVANCED}, 
        {"ldap port", P_INTEGER, P_GLOBAL, &Globals.ldap_port, NULL, NULL, FLAG_ADVANCED}, 
 #endif
-       {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, NULL, NULL, FLAG_ADVANCED}, 
-       {"ldap machine suffix", P_STRING, P_GLOBAL, &Globals.szLdapMachineSuffix, NULL, NULL, FLAG_ADVANCED}, 
-       {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, NULL, NULL, FLAG_ADVANCED}, 
+       {"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, FLAG_ADVANCED}, 
+       {"ldap delete dn", P_BOOL, P_GLOBAL, &Globals.ldap_delete_dn, NULL, NULL, FLAG_ADVANCED}, 
+       {"ldap filter", P_STRING, P_GLOBAL, &Globals.szLdapFilter, NULL, NULL, FLAG_ADVANCED}, 
        {"ldap group suffix", P_STRING, P_GLOBAL, &Globals.szLdapGroupSuffix, NULL, NULL, FLAG_ADVANCED}, 
        {"ldap idmap suffix", P_STRING, P_GLOBAL, &Globals.szLdapIdmapSuffix, NULL, NULL, FLAG_ADVANCED}, 
-       {"ldap filter", P_STRING, P_GLOBAL, &Globals.szLdapFilter, NULL, NULL, FLAG_ADVANCED}, 
-       {"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, FLAG_ADVANCED}, 
-       {"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, FLAG_ADVANCED}, 
+       {"ldap machine suffix", P_STRING, P_GLOBAL, &Globals.szLdapMachineSuffix, NULL, NULL, FLAG_ADVANCED}, 
        {"ldap passwd sync", P_ENUM, P_GLOBAL, &Globals.ldap_passwd_sync, NULL, enum_ldap_passwd_sync, FLAG_ADVANCED}, 
-       {"ldap delete dn", P_BOOL, P_GLOBAL, &Globals.ldap_delete_dn, NULL, NULL, FLAG_ADVANCED}, 
        {"ldap replication sleep", P_INTEGER, P_GLOBAL, &Globals.ldap_replication_sleep, NULL, NULL, FLAG_ADVANCED},
+       {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, NULL, NULL, FLAG_ADVANCED}, 
+       {"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, FLAG_ADVANCED}, 
+       {"ldap timeout", P_INTEGER, P_GLOBAL, &Globals.ldap_timeout, NULL, NULL, FLAG_ADVANCED},
+       {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, NULL, NULL, FLAG_ADVANCED}, 
 
        {N_("Miscellaneous Options"), P_SEP, P_SEPARATOR}, 
        {"add share command", P_STRING, P_GLOBAL, &Globals.szAddShareCommand, NULL, NULL, FLAG_ADVANCED}, 
@@ -1289,6 +1300,13 @@ static void init_globals(void)
 
        if (!done_init) {
                int i;
+
+               /* The logfile can be set before this is invoked. Free it if so. */
+               if (Globals.szLogFile != NULL) {
+                       string_free(&Globals.szLogFile);
+                       Globals.szLogFile = NULL;
+               }
+
                memset((void *)&Globals, '\0', sizeof(Globals));
 
                for (i = 0; parm_table[i].label; i++)
@@ -1471,6 +1489,7 @@ static void init_globals(void)
        Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
        Globals.ldap_delete_dn = False;
        Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
+       Globals.ldap_timeout = LDAP_CONNECT_DEFAULT_TIMEOUT;
 
 /* these parameters are set to defaults that are more appropriate
    for the increasing samba install base:
@@ -1506,6 +1525,7 @@ static void init_globals(void)
        string_set(&Globals.szTemplatePrimaryGroup, "nobody");
        string_set(&Globals.szWinbindSeparator, "\\");
        string_set(&Globals.szAclCompat, "");
+       string_set(&Globals.szCupsServer, "");
 
        Globals.winbind_cache_time = 300;       /* 5 minutes */
        Globals.bWinbindEnableLocalAccounts = True;
@@ -1525,6 +1545,7 @@ static void init_globals(void)
        Globals.client_signing = Auto;
        Globals.server_signing = False;
 
+       Globals.bDeferSharingViolations = True;
        string_set(&Globals.smb_ports, SMB_PORTS);
 }
 
@@ -1703,6 +1724,7 @@ FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
 FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
 FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn)
 FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep)
+FN_GLOBAL_INTEGER(lp_ldap_timeout, &Globals.ldap_timeout)
 FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
 FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
 FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
@@ -1758,6 +1780,8 @@ FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
 FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego)
 FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups)
 FN_GLOBAL_BOOL(lp_kernel_change_notify, &Globals.bKernelChangeNotify)
+FN_GLOBAL_BOOL(lp_use_kerberos_keytab, &Globals.bUseKerberosKeytab)
+FN_GLOBAL_BOOL(lp_defer_sharing_violations, &Globals.bDeferSharingViolations)
 FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level)
 FN_GLOBAL_INTEGER(lp_max_ttl, &Globals.max_ttl)
 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
@@ -1802,6 +1826,7 @@ FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers)
 FN_LOCAL_LIST(lp_valid_users, szValidUsers)
 FN_LOCAL_LIST(lp_admin_users, szAdminUsers)
 FN_LOCAL_STRING(lp_cups_options, szCupsOptions)
+FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer)
 FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
 FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
 FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
@@ -1832,7 +1857,7 @@ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
 FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
 FN_LOCAL_BOOL(lp_preexec_close, bPreexecClose)
 FN_LOCAL_BOOL(lp_rootpreexec_close, bRootpreexecClose)
-FN_LOCAL_BOOL(lp_casesensitive, bCaseSensitive)
+FN_LOCAL_INTEGER(lp_casesensitive, iCaseSensitive)
 FN_LOCAL_BOOL(lp_preservecase, bCasePreserve)
 FN_LOCAL_BOOL(lp_shortpreservecase, bShortCasePreserve)
 FN_LOCAL_BOOL(lp_hide_dot_files, bHideDotFiles)
@@ -1875,6 +1900,7 @@ FN_LOCAL_BOOL(lp_inherit_acls, bInheritACLS)
 FN_LOCAL_BOOL(lp_use_client_driver, bUseClientDriver)
 FN_LOCAL_BOOL(lp_default_devmode, bDefaultDevmode)
 FN_LOCAL_BOOL(lp_nt_acl_support, bNTAclSupport)
+FN_LOCAL_BOOL(lp_force_unknown_acl_user, bForceUnknownAclUser)
 FN_LOCAL_BOOL(lp_ea_support, bEASupport)
 FN_LOCAL_BOOL(_lp_use_sendfile, bUseSendfile)
 FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls)
@@ -2315,6 +2341,8 @@ BOOL lp_add_home(const char *pszHomename, int iDefaultService,
 
        ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
 
+       ServicePtrs[i]->autoloaded = True;
+
        DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
               user, newHomedir));
        
@@ -2993,10 +3021,8 @@ static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue
 {
        int i;
 
-       for (i = 0; parm->enum_list[i].name; i++) 
-       {
-               if ( strequal(pszParmValue, parm->enum_list[i].name)) 
-               {
+       for (i = 0; parm->enum_list[i].name; i++) {
+               if ( strequal(pszParmValue, parm->enum_list[i].name)) {
                        *ptr = parm->enum_list[i].value;
                        break;
                }
@@ -3269,9 +3295,9 @@ static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
                                char **list = *(char ***)ptr;
                                
                                for (; *list; list++) {
-                                       /* surround strings with whitespace in single quotes */
+                                       /* surround strings with whitespace in double quotes */
                                        if ( strchr_m( *list, ' ' ) )
-                                               fprintf(f, "\'%s\'%s", *list, ((*(list+1))?", ":""));
+                                               fprintf(f, "\"%s\"%s", *list, ((*(list+1))?", ":""));
                                        else
                                                fprintf(f, "%s%s", *list, ((*(list+1))?", ":""));
                                }
@@ -3697,6 +3723,10 @@ void lp_killunused(BOOL (*snumused) (int))
                if (!VALID(i))
                        continue;
 
+               /* don't kill autoloaded services */
+               if ( ServicePtrs[i]->autoloaded )
+                       continue;
+
                if (!snumused || !snumused(i)) {
                        ServicePtrs[i]->valid = False;
                        free_service(ServicePtrs[i]);
@@ -3866,11 +3896,12 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
        
        /* get the username for substituion -- preference to the current_user_info */
        
-       if ( strlen( current_user_info.smb_name ) != 0 )
+       if ( strlen( current_user_info.smb_name ) != 0 ) {
                username = current_user_info.smb_name;
-       else
+       } else {
                username = sub_get_smb_name();
-               
+       }
+
        standard_sub_basic( username, n2,sizeof(n2) );
 
        add_to_file_list(pszFname, n2);
@@ -3885,8 +3916,7 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
        init_globals();
        debug_init();
 
-       if (save_defaults)
-       {
+       if (save_defaults) {
                init_locals();
                lp_save_defaults();
        }
@@ -4258,7 +4288,10 @@ const char *get_called_name(void)
        extern fstring local_machine;
        static fstring called_name;
 
-       if (!*local_machine) {
+       if ( (!*local_machine) ||
+            (client_socket_port() == 445) ) {
+               /* Everybody coming in on 445 should be able to live with the
+                * IP address */
                fstrcpy(called_name, client_socket_addr());
                DEBUG(8,("get_called_name: assuming that client used IP address [%s] as called name.\n",
                         called_name));
@@ -4289,3 +4322,14 @@ BOOL lp_use_sendfile(int snum)
 {
        return (_lp_use_sendfile(snum) && !srv_is_signing_active());
 }
+
+/*******************************************************************
+ Turn off storing DOS attributes if this share doesn't support it.
+********************************************************************/
+
+void set_store_dos_attributes(int snum, BOOL val)
+{
+       if (!LP_SNUM_OK(snum))
+               return;
+       ServicePtrs[(snum)]->bStoreDosAttributes = val;
+}
index fc05122ccaf6c41937055bd1a0da5a907a3de8c8..0d782912b17d02589a943fac45ec7a3b3f2b2779 100644 (file)
@@ -95,10 +95,13 @@ LOGIN_CACHE * login_cache_read(SAM_ACCOUNT *sampass)
                        &entry->bad_password_count, 
                        &entry->bad_password_time) == -1) {
                DEBUG(7, ("No cache entry found\n"));
+               SAFE_FREE(entry);
                SAFE_FREE(databuf.dptr);
                return NULL;
        }
 
+       SAFE_FREE(databuf.dptr);
+
        DEBUG(5, ("Found login cache entry: timestamp %12u, flags 0x%x, count %d, time %12u\n",
                  (unsigned int)entry->entry_timestamp, entry->acct_ctrl, 
                  entry->bad_password_count, (unsigned int)entry->bad_password_time));
index 842db8de5dc7529d1947b5ccd91732c8fa9ce97e..d536383ef3eceddc65f4fda5521276931917d979 100644 (file)
@@ -445,14 +445,11 @@ NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid)
         * Group mapping can deal with foreign SIDs
         */
 
+       if ( local_sid_to_gid(pgid, psid, &name_type) )
+               goto success;
+       
        if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) {
-               DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n",
-                       sid_to_string(sid_str, psid) ));
-
-               if ( local_sid_to_gid(pgid, psid, &name_type) )
-                       goto success;
-                       
-               DEBUG(10,("sid_to_gid: no one knows this SID\n"));
+               DEBUG(10,("sid_to_gid: no one knows the SID %s (tried local, then winbind)\n", sid_to_string(sid_str, psid)));
                
                return NT_STATUS_UNSUCCESSFUL;
        }
index 75f8171a25db7d16584e63ec8d9e7ead84f666b4..c3a423c2636200f44cb90fd6cb7107a15abfcfe7 100644 (file)
@@ -1287,6 +1287,7 @@ BOOL local_sid_to_gid(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE *name_
        }
 
        *pgid = group.gid;
+       *name_type = group.sid_name_use;
 
        DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u)\n", sid_string_static(psid),
                (unsigned int)*pgid));
index 15635a034ccfb7dd4d16c4823cf4854582868945..d2ee9a2d9dc92b975684d3d7ce30cec29d3631c2 100644 (file)
@@ -1043,9 +1043,13 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                        DEBUG(7, ("bad password count is reset, deleting login cache entry for %s\n", pdb_get_nt_username(sampass)));
                        login_cache_delentry(sampass);
                } else {
-                       LOGIN_CACHE cache_entry ={time(NULL),
-                                                 pdb_get_acct_ctrl(sampass),
-                                                 badcount, badtime};
+                       LOGIN_CACHE cache_entry;
+
+                       cache_entry.entry_timestamp = time(NULL);
+                       cache_entry.acct_ctrl = pdb_get_acct_ctrl(sampass);
+                       cache_entry.bad_password_count = badcount;
+                       cache_entry.bad_password_time = badtime;
+
                        DEBUG(7, ("Updating bad password count and time in login cache\n"));
                        login_cache_write(sampass, cache_entry);
                }
@@ -1130,6 +1134,19 @@ static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT
        return NT_STATUS_OK;
 }
 
+static void append_attr(char ***attr_list, const char *new_attr)
+{
+       int i;
+
+       for (i=0; (*attr_list)[i] != NULL; i++)
+               ;
+
+       (*attr_list) = Realloc((*attr_list), sizeof(**attr_list) * (i+2));
+       SMB_ASSERT((*attr_list) != NULL);
+       (*attr_list)[i] = strdup(new_attr);
+       (*attr_list)[i+1] = NULL;
+}
+
 /**********************************************************************
 Get SAM_ACCOUNT entry from LDAP by username.
 *********************************************************************/
@@ -1145,6 +1162,7 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT
        int rc;
        
        attr_list = get_userattr_list( ldap_state->schema_ver );
+       append_attr(&attr_list, MODIFY_TIMESTAMP_STRING);
        rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
        free_attr_list( attr_list );
 
@@ -1190,6 +1208,7 @@ static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state,
        switch ( ldap_state->schema_ver ) {
                case SCHEMAVER_SAMBASAMACCOUNT:
                        attr_list = get_userattr_list(ldap_state->schema_ver);
+                       append_attr(&attr_list, MODIFY_TIMESTAMP_STRING);
                        rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list);
                        free_attr_list( attr_list );
 
index 26ef191f877a4c9d1b5b363493d196573ae61c1b..8d5be136071eba9a4a04a060416a077e4525ab4e 100644 (file)
@@ -278,7 +278,7 @@ in notify_queue\n", msg->type, msg->field, msg->printer));
                return;
        }
        copy_notify2_msg(pnqueue->msg, msg);
-       gettimeofday(&pnqueue->tv, NULL);
+       GetTimeOfDay(&pnqueue->tv);
        pnqueue->buf = NULL;
        pnqueue->buflen = 0;
 
index 909aed6c86613e1820802ae94909555656e62f53..225ff20ec3eb52b8f7a1fb670308cd0f817ea8f6 100644 (file)
@@ -1003,9 +1003,9 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
        driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
 
        fsp = open_file_shared(conn, filepath, &stat_buf,
-                                                  SET_OPEN_MODE(DOS_OPEN_RDONLY),
+                                                  SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
                                                   (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
-                                                  FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
+                                                  FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
        if (!fsp) {
                /* Old file not found, so by definition new file is in fact newer */
                DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
@@ -1032,9 +1032,9 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
        driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
 
        fsp = open_file_shared(conn, filepath, &stat_buf,
-                                                  SET_OPEN_MODE(DOS_OPEN_RDONLY),
+                                                  SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
                                                   (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
-                                                  FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
+                                                  FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
        if (!fsp) {
                /* New file not found, this shouldn't occur if the caller did its job */
                DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
@@ -1148,9 +1148,9 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_
        driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
 
        fsp = open_file_shared(conn, driverpath, &st,
-                                                  SET_OPEN_MODE(DOS_OPEN_RDONLY),
+                                                  SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
                                                   (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
-                                                  FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
+                                                  FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
        if (!fsp) {
                DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
                                driverpath, errno));
index 9a48296543d0e9d03cbfa41cf925032506d3ce34..3097811fac2ce9e3f27397b8f4434bf63e627c39 100644 (file)
@@ -65,6 +65,17 @@ cups_passwd_cb(const char *prompt)   /* I - Prompt */
   return (NULL);
 }
 
+static const char *cups_server(void)
+{
+       if ((lp_cups_server() != NULL) && (strlen(lp_cups_server()) > 0)) {
+               DEBUG(10, ("cups server explicitly set to %s\n",
+                          lp_cups_server()));
+               return lp_cups_server();
+       }
+
+       DEBUG(10, ("cups server left to default %s\n", cupsServer()));
+       return cupsServer();
+}
 
 /*
  * 'cups_printer_fn()' - Call a function for every printer known to the
@@ -102,10 +113,10 @@ void cups_printer_fn(void (*fn)(char *, char *))
        * Try to connect to the server...
        */
 
-       if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+       if ((http = httpConnect(cups_server(), ippPort())) == NULL)
        {
                DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
-                        cupsServer(), strerror(errno)));
+                        cups_server(), strerror(errno)));
                return;
        }
 
@@ -331,10 +342,10 @@ int cups_printername_ok(const char *name)
        * Try to connect to the server...
        */
 
-       if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+       if ((http = httpConnect(cups_server(), ippPort())) == NULL)
        {
                DEBUG(3,("Unable to connect to CUPS server %s - %s\n", 
-                        cupsServer(), strerror(errno)));
+                        cups_server(), strerror(errno)));
                return (0);
        }
 
@@ -425,10 +436,10 @@ cups_job_delete(int snum, struct printjob *pjob)
        * Try to connect to the server...
        */
 
-       if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+       if ((http = httpConnect(cups_server(), ippPort())) == NULL)
        {
                DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
-                        cupsServer(), strerror(errno)));
+                        cups_server(), strerror(errno)));
                return (1);
        }
 
@@ -515,10 +526,10 @@ cups_job_pause(int snum, struct printjob *pjob)
        * Try to connect to the server...
        */
 
-       if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+       if ((http = httpConnect(cups_server(), ippPort())) == NULL)
        {
                DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
-                        cupsServer(), strerror(errno)));
+                        cups_server(), strerror(errno)));
                return (1);
        }
 
@@ -605,10 +616,10 @@ cups_job_resume(int snum, struct printjob *pjob)
        * Try to connect to the server...
        */
 
-       if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+       if ((http = httpConnect(cups_server(), ippPort())) == NULL)
        {
                DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
-                        cupsServer(), strerror(errno)));
+                        cups_server(), strerror(errno)));
                return (1);
        }
 
@@ -698,10 +709,10 @@ cups_job_submit(int snum, struct printjob *pjob)
        * Try to connect to the server...
        */
 
-       if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+       if ((http = httpConnect(cups_server(), ippPort())) == NULL)
        {
                DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
-                        cupsServer(), strerror(errno)));
+                        cups_server(), strerror(errno)));
                return (1);
        }
 
@@ -848,10 +859,10 @@ cups_queue_get(int snum, print_queue_struct **q, print_status_struct *status)
        * Try to connect to the server...
        */
 
-       if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+       if ((http = httpConnect(cups_server(), ippPort())) == NULL)
        {
                DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
-                        cupsServer(), strerror(errno)));
+                        cups_server(), strerror(errno)));
                return (0);
        }
 
@@ -1153,10 +1164,10 @@ cups_queue_pause(int snum)
         * Try to connect to the server...
         */
 
-       if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+       if ((http = httpConnect(cups_server(), ippPort())) == NULL)
        {
                DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
-                        cupsServer(), strerror(errno)));
+                        cups_server(), strerror(errno)));
                return (1);
        }
 
@@ -1245,10 +1256,10 @@ cups_queue_resume(int snum)
        * Try to connect to the server...
        */
 
-       if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+       if ((http = httpConnect(cups_server(), ippPort())) == NULL)
        {
                DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
-                        cupsServer(), strerror(errno)));
+                        cups_server(), strerror(errno)));
                return (1);
        }
 
index 2274e2d5f452b1c56e616b6e6390165d77cea1e5..8beea9d0cec91334b33509b311530f5c236891d4 100644 (file)
@@ -23,6 +23,9 @@
 #include "includes.h"
 #include "printing.h"
 
+extern SIG_ATOMIC_T got_sig_term;
+extern SIG_ATOMIC_T reload_after_sighup;
+
 /* Current printer interface */
 static BOOL remove_from_jobs_changed(int snum, uint32 jobid);
 
@@ -597,6 +600,7 @@ void pjob_delete(int snum, uint32 jobid)
        tdb_delete(pdb->tdb, print_key(jobid));
        release_print_db(pdb);
        rap_jobid_delete(snum, jobid);
+       remove_from_jobs_changed( snum, jobid );
 }
 
 /****************************************************************************
@@ -1195,6 +1199,22 @@ void start_background_queue(void)
                DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
                while (1) {
                        pause();
+                       
+                       /* check for some essential signals first */
+                       
+                        if (got_sig_term) {
+                                exit_server("Caught TERM signal");
+                        }
+
+                        if (reload_after_sighup) {
+                                change_to_root_user();
+                                DEBUG(1,("Reloading services after SIGHUP\n"));
+                                reload_services(False);
+                                reload_after_sighup = 0;
+                        }
+                       
+                       /* now check for messages */
+                       
                        DEBUG(10,("start_background_queue: background LPQ thread got a message\n"));
                        message_dispatch();
                }
@@ -1211,9 +1231,13 @@ static void print_queue_update(int snum)
         * Otherwise just do the update ourselves 
         */
           
-       if ( background_lpq_updater_pid != -1 )
-               message_send_pid(background_lpq_updater_pid, MSG_PRINTER_UPDATE, &snum, sizeof(snum), False);
-       else
+       if ( background_lpq_updater_pid != -1 ) {
+               become_root();
+               message_send_pid(background_lpq_updater_pid,
+                                MSG_PRINTER_UPDATE, &snum, sizeof(snum),
+                                False);
+               unbecome_root();
+       } else
                print_queue_update_internal( snum );
 }
 
index d402aa366f4e3f7a0dacc0887b7b730a2f9eb3d4..9efb3e8eadfc8c0921630aecb112285eed34ec3e 100644 (file)
@@ -96,8 +96,8 @@ struct tdb_print_db *get_print_db_byname(const char *printername)
                done_become_root = True;
        }
 
-       p->tdb = tdb_open_ex(printdb_path, 5000, TDB_DEFAULT, O_RDWR|O_CREAT, 
-               0600, smbd_tdb_log);
+       p->tdb = tdb_open_log(printdb_path, 5000, TDB_DEFAULT, O_RDWR|O_CREAT, 
+               0600);
 
        if (done_become_root)
                unbecome_root();
index f6d88a195016dc84fa89282319c9fed1f98c7581..02d2611d88cd30cde8b5b858fb86ddfeb670bd21 100644 (file)
@@ -91,18 +91,25 @@ NTSTATUS cli_net_auth2(struct cli_state *cli,
         NET_Q_AUTH_2 q;
         NET_R_AUTH_2 r;
         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       fstring machine_acct;
 
         prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
         prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
 
+       if ( sec_chan == SEC_CHAN_DOMAIN )
+               fstr_sprintf( machine_acct, "%s$", lp_workgroup() );
+       else
+               fstrcpy( machine_acct, cli->mach_acct );
+       
         /* create and send a MSRPC command with api NET_AUTH2 */
 
         DEBUG(4,("cli_net_auth2: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n",
-                 cli->srv_name_slash, cli->mach_acct, sec_chan, global_myname(),
+                 cli->srv_name_slash, machine_acct, sec_chan, global_myname(),
                  credstr(cli->clnt_cred.challenge.data), *neg_flags));
 
         /* store the parameters */
-        init_q_auth_2(&q, cli->srv_name_slash, cli->mach_acct, 
+
+        init_q_auth_2(&q, cli->srv_name_slash, machine_acct, 
                       sec_chan, global_myname(), &cli->clnt_cred.challenge, 
                       *neg_flags);
 
index b24dbb7d25d58841acde4456aa8e8acad289578b..0720f8724198b185253674f9069da713ff907e9e 100644 (file)
@@ -1233,10 +1233,12 @@ static BOOL valid_pipe_name(const int pipe_idx, RPC_IFACE *abstract, RPC_IFACE *
 
 static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFACE *transfer)
 {
-# if 0 /* JERRY -- apparently ASU forgets to fill in the server pipe name sometimes */
-       if ( hdr_ba->addr.len <= 0)
-               return False;
+       if ( hdr_ba->addr.len == 0) {
+               DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
+       }
+
                
+# if 0 /* JERRY -- apparently ASU forgets to fill in the server pipe name sometimes */
        if ( !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].client_pipe) &&
             !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].server_pipe) )
        {
@@ -1621,9 +1623,6 @@ NTSTATUS cli_nt_setup_netsec(struct cli_state *cli, int sec_chan, int auth_flags
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       if (lp_client_schannel() != False)
-               neg_flags |= NETLOGON_NEG_SCHANNEL;
-
        neg_flags |= NETLOGON_NEG_SCHANNEL;
 
        result = cli_nt_setup_creds(cli, sec_chan, trust_password,
index 36d55c7bf675d20793e7c88ffcb96501657a944c..b42b9b2a8b41cba99cca0e2924a55d29d7ba4fcc 100644 (file)
@@ -182,6 +182,50 @@ static BOOL net_io_netinfo_2(const char *desc, NETLOGON_INFO_2 *info, prs_struct
        return True;
 }
 
+static BOOL net_io_ctrl_data_info_5(const char *desc, CTRL_DATA_INFO_5 *info, prs_struct *ps, int depth)
+{
+       if (info == NULL)
+               return False;
+               
+       prs_debug(ps, depth, desc, "net_io_ctrl_data_info_5");
+       depth++;
+       
+       if ( !prs_uint32( "function_code", ps, depth, &info->function_code ) )
+               return False;
+       
+       if(!prs_uint32("ptr_domain", ps, depth, &info->ptr_domain))
+               return False;
+               
+       if ( info->ptr_domain ) {
+               if(!smb_io_unistr2("domain", &info->domain, info->ptr_domain, ps, depth))
+                       return False;
+       }
+               
+       return True;
+}
+
+static BOOL net_io_ctrl_data_info_6(const char *desc, CTRL_DATA_INFO_6 *info, prs_struct *ps, int depth)
+{
+       if (info == NULL)
+               return False;
+               
+       prs_debug(ps, depth, desc, "net_io_ctrl_data_info_6");
+       depth++;
+       
+       if ( !prs_uint32( "function_code", ps, depth, &info->function_code ) )
+               return False;
+       
+       if(!prs_uint32("ptr_domain", ps, depth, &info->ptr_domain))
+               return False;
+               
+       if ( info->ptr_domain ) {
+               if(!smb_io_unistr2("domain", &info->domain, info->ptr_domain, ps, depth))
+                       return False;
+       }
+               
+       return True;
+}
+
 /*******************************************************************
  Reads or writes an NET_Q_LOGON_CTRL2 structure.
 ********************************************************************/
@@ -210,9 +254,23 @@ BOOL net_io_q_logon_ctrl2(const char *desc, NET_Q_LOGON_CTRL2 *q_l, prs_struct *
                return False;
        if(!prs_uint32("query_level  ", ps, depth, &q_l->query_level))
                return False;
-       if(!prs_uint32("switch_value ", ps, depth, &q_l->switch_value))
-               return False;
+       switch ( q_l->function_code ) {
+               case NETLOGON_CONTROL_REDISCOVER:
+                       if ( !net_io_ctrl_data_info_5( "ctrl_data_info5", &q_l->info.info5, ps, depth) ) 
+                               return False;
+                       break;
+                       
+               case NETLOGON_CONTROL_TC_QUERY:
+                       if ( !net_io_ctrl_data_info_6( "ctrl_data_info6", &q_l->info.info6, ps, depth) ) 
+                               return False;
+                       break;
 
+               default:
+                       DEBUG(0,("net_io_q_logon_ctrl2: unknown function_code [%d]\n",
+                               q_l->function_code));
+                       return False;
+       }
+       
        return True;
 }
 
@@ -227,7 +285,6 @@ void init_net_q_logon_ctrl2(NET_Q_LOGON_CTRL2 *q_l, const char *srv_name,
 
        q_l->function_code = 0x01;
        q_l->query_level = query_level;
-       q_l->switch_value  = 0x01;
 
        init_unistr2(&q_l->uni_server_name, srv_name, UNI_STR_TERMINATE);
 }
@@ -241,9 +298,7 @@ void init_net_r_logon_ctrl2(NET_R_LOGON_CTRL2 *r_l, uint32 query_level,
                            uint32 logon_attempts, uint32 tc_status, 
                            const char *trusted_domain_name)
 {
-       DEBUG(5,("init_r_logon_ctrl2\n"));
-
-       r_l->switch_value  = query_level; /* should only be 0x1 */
+       r_l->switch_value  = query_level; 
 
        switch (query_level) {
        case 1:
index 0e5a25fe8c2894607927340ab4cb9066c446fa40..92c5b13632a817a9a67c00483e83d8e5127071d0 100644 (file)
@@ -1101,10 +1101,13 @@ BOOL prs_unistr(const char *name, prs_struct *ps, int depth, UNISTR *str)
 
                /* the test of the value of *ptr helps to catch the circumstance
                   where we have an emtpty (non-existent) string in the buffer */
-               for ( ptr = (uint16 *)q; *ptr && (alloc_len <= max_len); alloc_len++)
+               for ( ptr = (uint16 *)q; *ptr++ && (alloc_len <= max_len); alloc_len++)
                        /* do nothing */ 
                        ;
 
+               if (alloc_len < max_len)
+                       alloc_len += 1;
+
                /* should we allocate anything at all? */
                str->buffer = (uint16 *)prs_alloc_mem(ps,alloc_len * sizeof(uint16));
                if ((str->buffer == NULL) && (alloc_len > 0))
index 85eedc7baabf91286ec8de9adc6ec329e23d9c74..bb4c94404b0e448384a53eaef40f0d003d42519b 100644 (file)
@@ -2204,12 +2204,17 @@ reads or writes a structure.
 BOOL samr_io_group_info1(const char *desc, GROUP_INFO1 * gr1,
                         prs_struct *ps, int depth)
 {
+       uint16 dummy = 1;
+
        if (gr1 == NULL)
                return False;
 
        prs_debug(ps, depth, desc, "samr_io_group_info1");
        depth++;
 
+       if(!prs_uint16("level", ps, depth, &dummy))
+               return False;
+
        if(!prs_align(ps))
                return False;
 
@@ -2235,6 +2240,43 @@ BOOL samr_io_group_info1(const char *desc, GROUP_INFO1 * gr1,
        return True;
 }
 
+/*******************************************************************
+inits a GROUP_INFO2 structure.
+********************************************************************/
+
+void init_samr_group_info2(GROUP_INFO2 * gr2, const char *acct_name)
+{
+       DEBUG(5, ("init_samr_group_info2\n"));
+
+       gr2->level = 2;
+       init_unistr2(&gr2->uni_acct_name, acct_name, UNI_FLAGS_NONE);
+       init_uni_hdr(&gr2->hdr_acct_name, &gr2->uni_acct_name);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL samr_io_group_info2(const char *desc, GROUP_INFO2 *gr2, prs_struct *ps, int depth)
+{
+       if (gr2 == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "samr_io_group_info2");
+       depth++;
+
+       if(!prs_uint16("hdr_level", ps, depth, &gr2->level))
+               return False;
+
+       if(!smb_io_unihdr("hdr_acct_name", &gr2->hdr_acct_name, ps, depth))
+               return False;
+       if(!smb_io_unistr2("uni_acct_name", &gr2->uni_acct_name,
+                          gr2->hdr_acct_name.buffer, ps, depth))
+               return False;
+
+       return True;
+}
+
 /*******************************************************************
 inits a GROUP_INFO3 structure.
 ********************************************************************/
@@ -2328,6 +2370,10 @@ static BOOL samr_group_info_ctr(const char *desc, GROUP_INFO_CTR **ctr,
                if(!samr_io_group_info1("group_info1", &(*ctr)->group.info1, ps, depth))
                        return False;
                break;
+       case 2:
+               if(!samr_io_group_info2("group_info2", &(*ctr)->group.info2, ps, depth))
+                       return False;
+               break;
        case 3:
                if(!samr_io_group_info3("group_info3", &(*ctr)->group.info3, ps, depth))
                        return False;
@@ -6924,8 +6970,7 @@ BOOL samr_io_r_get_dom_pwinfo(const char *desc, SAMR_R_GET_DOM_PWINFO * r_u,
                return False;
 
        /*
-        * We need 16 bytes here according to tests.  Don't know
-        * what they are, but the length is important for the singing
+        * see the Samba4 IDL for what these actually are.
        */
 
        if(!prs_uint16("unk_0", ps, depth, &r_u->unk_0))
index b4e29e674852fb84f8271e39597ee83855645624..6c3157d5c95ba1d30f7ee5731bc9962792fff63d 100644 (file)
@@ -101,7 +101,7 @@ static int init_dom_ref(DOM_R_REF *ref, char *dom_name, DOM_SID *dom_sid)
        if (dom_name != NULL) {
                for (num = 0; num < ref->num_ref_doms_1; num++) {
                        fstring domname;
-                       rpcstr_pull(domname, &ref->ref_dom[num].uni_dom_name, sizeof(domname), -1, 0);
+                       rpcstr_pull(domname, ref->ref_dom[num].uni_dom_name.buffer, sizeof(domname), -1, 0);
                        if (strequal(domname, dom_name))
                                return num;
                }
@@ -719,12 +719,12 @@ done:
 
        /* set up the LSA Lookup RIDs response */
        init_lsa_rid2s(ref, rids, num_entries, names, &mapped_count, p->endian);
-       if (mapped_count == 0)
-               r_u->status = NT_STATUS_NONE_MAPPED;
-       else if (mapped_count != num_entries)
-               r_u->status = STATUS_SOME_UNMAPPED;
-       else
-               r_u->status = NT_STATUS_OK;
+       if (NT_STATUS_IS_OK(r_u->status)) {
+               if (mapped_count == 0)
+                       r_u->status = NT_STATUS_NONE_MAPPED;
+               else if (mapped_count != num_entries)
+                       r_u->status = STATUS_SOME_UNMAPPED;
+       }
        init_reply_lookup_names(r_u, ref, num_entries, rids, mapped_count);
 
        return r_u->status;
index f06a2002e3c37bc372798cfc453721d0a4a2ed59..705b629732a5f729e1fe10a92063f029ed757899 100644 (file)
@@ -227,8 +227,6 @@ static BOOL api_net_trust_dom_list(pipes_struct *p)
        ZERO_STRUCT(q_u);
        ZERO_STRUCT(r_u);
 
-       DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
-
        /* grab the lsa trusted domain list query... */
        if(!net_io_q_trust_dom("", &q_u, data, 0)) {
                DEBUG(0,("api_net_trust_dom_list: Failed to unmarshall NET_Q_TRUST_DOM_LIST.\n"));
@@ -244,8 +242,6 @@ static BOOL api_net_trust_dom_list(pipes_struct *p)
                return False;
        }
 
-       DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
-
        return True;
 }
 
@@ -263,7 +259,6 @@ static BOOL api_net_logon_ctrl2(pipes_struct *p)
        ZERO_STRUCT(q_u);
        ZERO_STRUCT(r_u);
 
-       DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
 
        /* grab the lsa netlogon ctrl2 query... */
        if(!net_io_q_logon_ctrl2("", &q_u, data, 0)) {
@@ -278,8 +273,6 @@ static BOOL api_net_logon_ctrl2(pipes_struct *p)
                return False;
        }
 
-       DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
-
        return True;
 }
 
@@ -297,8 +290,6 @@ static BOOL api_net_logon_ctrl(pipes_struct *p)
        ZERO_STRUCT(q_u);
        ZERO_STRUCT(r_u);
 
-       DEBUG(6,("api_net_logon_ctrl: %d\n", __LINE__));
-
        /* grab the lsa netlogon ctrl query... */
        if(!net_io_q_logon_ctrl("", &q_u, data, 0)) {
                DEBUG(0,("api_net_logon_ctrl: Failed to unmarshall NET_Q_LOGON_CTRL.\n"));
@@ -312,8 +303,6 @@ static BOOL api_net_logon_ctrl(pipes_struct *p)
                return False;
        }
 
-       DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
-
        return True;
 }
 
index be8eda82c9023b9b193607420847f0a462a95e39..264b7a74a7994715b7f90547b9eae98a95643eb7 100644 (file)
@@ -47,6 +47,7 @@ static void init_net_r_req_chal(NET_R_REQ_CHAL *r_c,
 
 #define ERROR_NO_SUCH_DOMAIN   0x54b
 #define ERROR_NO_LOGON_SERVERS 0x51f
+#define NO_ERROR               0x0
 
 /*************************************************************************
  net_reply_logon_ctrl:
@@ -104,25 +105,67 @@ NTSTATUS _net_logon_ctrl2(pipes_struct *p, NET_Q_LOGON_CTRL2 *q_u, NET_R_LOGON_C
         uint32 flags = 0x0;
         uint32 pdc_connection_status = 0x0;
         uint32 logon_attempts = 0x0;
-        uint32 tc_status = ERROR_NO_LOGON_SERVERS;
-        const char *trusted_domain = "test_domain";
+        uint32 tc_status;
+       fstring servername, domain, dc_name, dc_name2;
+       struct in_addr dc_ip;
 
-        DEBUG(0, ("*** net long ctrl2 %d, %d, %d\n",
-                  q_u->function_code, q_u->query_level, q_u->switch_value));
+       /* this should be \\global_myname() */
+       unistr2_to_ascii(servername, &q_u->uni_server_name, sizeof(servername));
 
-       DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__));
-
-
-       /* set up the Logon Control2 response */
-       init_net_r_logon_ctrl2(r_u, q_u->query_level,
-                              flags, pdc_connection_status, logon_attempts,
-                              tc_status, trusted_domain);
+       r_u->status = NT_STATUS_OK;
+       
+       tc_status = ERROR_NO_SUCH_DOMAIN;
+       fstrcpy( dc_name, "" );
+       
+       switch ( q_u->function_code ) {
+               case NETLOGON_CONTROL_TC_QUERY:
+                       unistr2_to_ascii(domain, &q_u->info.info6.domain, sizeof(domain));
+                               
+                       if ( !is_trusted_domain( domain ) )
+                               break;
+                               
+                       if ( !get_dc_name( domain, NULL, dc_name2, &dc_ip ) ) {
+                               tc_status = ERROR_NO_LOGON_SERVERS;
+                               break;
+                       }
+
+                       fstr_sprintf( dc_name, "\\\\%s", dc_name2 );
+                               
+                       tc_status = NO_ERROR;
+                       
+                       break;
+                       
+               case NETLOGON_CONTROL_REDISCOVER:
+                       unistr2_to_ascii(domain, &q_u->info.info6.domain, sizeof(domain));
+                               
+                       if ( !is_trusted_domain( domain ) )
+                               break;
+                               
+                       if ( !get_dc_name( domain, NULL, dc_name2, &dc_ip ) ) {
+                               tc_status = ERROR_NO_LOGON_SERVERS;
+                               break;
+                       }
+
+                       fstr_sprintf( dc_name, "\\\\%s", dc_name2 );
+                               
+                       tc_status = NO_ERROR;
+                       
+                       break;
+                       
+               default:
+                       /* no idea what this should be */
+                       DEBUG(0,("_net_logon_ctrl2: unimplemented function level [%d]\n",
+                               q_u->function_code));
+       }
+       
+       /* prepare the response */
+       
+       init_net_r_logon_ctrl2( r_u, q_u->query_level, flags, 
+               pdc_connection_status, logon_attempts, tc_status, dc_name );
 
         if (lp_server_role() == ROLE_DOMAIN_BDC)
                 send_sync_message();
 
-       DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__));
-
        return r_u->status;
 }
 
index 13d894d2d88ce06affdeb171493905b5a7211f8a..36929150e545c2c7ee1736104cd51e0c940c02ce 100644 (file)
@@ -1397,7 +1397,7 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in)
                           SENDER_IS_INITIATOR,
                           &netsec_chk,
                           prs_data_p(rpc_in)+old_offset, data_len)) {
-               DEBUG(0,("failed to decode PDU\n"));
+               DEBUG(3,("failed to decode PDU\n"));
                return False;
        }
 
index ccf571a0e2cb3b63760685f8742fe1afd3798875..7f7a3025a907e14c5f4b1234fe98244782c46994 100644 (file)
@@ -602,7 +602,7 @@ static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
        }
 
        if (p->netsec_auth_validated && !api_pipe_netsec_process(p, rpc_in_p)) {
-               DEBUG(0,("process_request_pdu: failed to do schannel processing.\n"));
+               DEBUG(3,("process_request_pdu: failed to do schannel processing.\n"));
                set_incoming_fault(p);
                return False;
        }
index 417a712036a8c23121067e92a9d4f849ecb78d83..8cc44074abec64d4c141d1d9b5f1bd81f62ea62f 100644 (file)
@@ -240,6 +240,12 @@ void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from)
        if (from->fields_present & ACCT_FLAGS) {
                DEBUG(10,("INFO_21 ACCT_CTRL: %08X -> %08X\n",pdb_get_acct_ctrl(to),from->acb_info));
                if (from->acb_info != pdb_get_acct_ctrl(to)) {
+                       if (!(from->acb_info & ACB_AUTOLOCK) && (pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) {
+                               /* We're unlocking a previously locked user. Reset bad password counts.
+                                  Patch from Jianliang Lu. <Jianliang.Lu@getronics.com> */
+                               pdb_set_bad_password_count(to, 0, PDB_CHANGED);
+                               pdb_set_bad_password_time(to, 0, PDB_CHANGED);
+                       }
                        pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED);
                }
        }
index 65d5517da45736469356795ad6d523715aedf3fe..06ba5435976cdcd2f46fed469a4b115e7a8ae13b 100644 (file)
@@ -5,7 +5,7 @@
  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
  *  Copyright (C) Jean François Micouleau      1998-2000,
  *  Copyright (C) Jeremy Allison               2001-2002,
- *  Copyright (C) Gerald Carter                       2000-2003,
+ *  Copyright (C) Gerald Carter                       2000-2004,
  *  Copyright (C) Tim Potter                   2001-2002.
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -312,6 +312,7 @@ void invalidate_printer_hnd_cache( char *printername )
        for ( p=printers_list; p; p=p->next )
        {
                if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER 
+                       && p->printer_info
                        && StrCaseCmp(p->dev.handlename, printername)==0)
                {
                        DEBUG(10,("invalidating printer_info cache for handl:\n"));
@@ -507,17 +508,19 @@ static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
                if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
                        continue;
                
+               /* ------ sharename ------ */
+
                fstrcpy(sname, lp_servicename(snum));
 
                DEBUGADD(10, ("share: %s\n",sname));
                
-               /* sharename */
                if ( strequal(sname, aprinter) ) {
                        found = True;
                        break;
                }
                
-               /* printername */
+               /* ------ printername ------ */
+
                printer = NULL;
                result = get_a_printer( NULL, &printer, 2, sname );
                if ( !W_ERROR_IS_OK(result) ) {
@@ -534,10 +537,8 @@ static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
                        continue;
                }
                
-               /* FIXME!! not mb safe here */
                printername++;
                        
-               /* sharename */
                if ( strequal(printername, aprinter) ) {
                        found = True;
                }
@@ -1188,6 +1189,12 @@ static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, siz
                ZERO_STRUCT( notify );
                notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
                msg_ptr += msg_len;
+
+               /* we don't know if the change was from us or not so kill 
+                  any cached printer objects */
+
+               if ( notify.type == PRINTER_NOTIFY_TYPE )
+                       invalidate_printer_hnd_cache( notify.printer );
                
                /* add to correct list in container */
                
@@ -4310,11 +4317,10 @@ static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *p
 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
 {
        char *guid_str = NULL;
-       UUID_FLAT guid;
+       struct uuid guid; 
        
        if (is_printer_published(print_hnd, snum, &guid)) {
-               asprintf(&guid_str, "{%s}", 
-                        smb_uuid_string_static(smb_uuid_unpack_static(guid)));
+               asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
                strupper_m(guid_str);
                init_unistr(&printer->guid, guid_str);
                printer->action = SPOOL_DS_PUBLISH;
index 77b9be99660ba64f3d66ea6831398449e5b96fc2..54cc0d616180e91b25cc0cf5b66b94bed7b92801 100644 (file)
@@ -1886,8 +1886,21 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
 
        unistr2_to_ascii(filename, &q_u->uni_file_name, sizeof(filename));
        unix_convert(filename, conn, NULL, &bad_path, &st);
-       fsp = open_file_shared(conn, filename, &st, SET_OPEN_MODE(DOS_OPEN_RDONLY),
-                               (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
+       if (bad_path) {
+               DEBUG(3,("_srv_net_file_query_secdesc: bad pathname %s\n", filename));
+               r_u->status = WERR_ACCESS_DENIED;
+               goto error_exit;
+       }
+
+       if (!check_name(filename,conn)) {
+               DEBUG(3,("_srv_net_file_query_secdesc: can't access %s\n", filename));
+               r_u->status = WERR_ACCESS_DENIED;
+               goto error_exit;
+       }
+
+       fsp = open_file_shared(conn, filename, &st, SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
+                               (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
+                               &access_mode, &action);
 
        if (!fsp) {
                /* Perhaps it is a directory */
@@ -1989,9 +2002,22 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
 
        unistr2_to_ascii(filename, &q_u->uni_file_name, sizeof(filename));
        unix_convert(filename, conn, NULL, &bad_path, &st);
+       if (bad_path) {
+               DEBUG(3,("_srv_net_file_set_secdesc: bad pathname %s\n", filename));
+               r_u->status = WERR_ACCESS_DENIED;
+               goto error_exit;
+       }
+
+       if (!check_name(filename,conn)) {
+               DEBUG(3,("_srv_net_file_set_secdesc: can't access %s\n", filename));
+               r_u->status = WERR_ACCESS_DENIED;
+               goto error_exit;
+       }
+
 
-       fsp = open_file_shared(conn, filename, &st, SET_OPEN_MODE(DOS_OPEN_RDWR),
-                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
+       fsp = open_file_shared(conn, filename, &st, SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDWR),
+                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
+                       &access_mode, &action);
 
        if (!fsp) {
                /* Perhaps it is a directory */
index f5a440c024c455ffb36168555aa55a3f236660b1..38558ec3d472466aea8f8f7f2d63a8ca5cb97f25 100644 (file)
@@ -314,7 +314,7 @@ static WERROR cmd_spoolss_enum_printers(struct cli_state *cli,
                return WERR_OK;
        }
 
-       if (argc == 2)
+       if (argc >= 2)
                info_level = atoi(argv[1]);
 
        if (argc == 3)
@@ -546,6 +546,76 @@ static WERROR cmd_spoolss_setprinter(struct cli_state *cli,
        return result;
 }
 
+/***********************************************************************
+ * Set printer name - use a level2 set.
+ */
+static WERROR cmd_spoolss_setprintername(struct cli_state *cli,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc, const char **argv)
+{
+       POLICY_HND      pol;
+       WERROR          result;
+       uint32          needed;
+       uint32          info_level = 2;
+       BOOL            opened_hnd = False;
+       PRINTER_INFO_CTR ctr;
+       fstring         printername,
+                       servername,
+                       user,
+                       new_printername;
+
+       if (argc == 1 || argc > 3) {
+               printf("Usage: %s printername new_printername\n", argv[0]);
+
+               return WERR_OK;
+       }
+
+       /* Open a printer handle */
+       if (argc == 3) {
+               fstrcpy(new_printername, argv[2]);
+       }
+
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       strupper_m(servername);
+       fstrcpy(printername, argv[1]);
+       fstrcpy(user, cli->user_name);
+
+       /* get a printer handle */
+       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
+                               PRINTER_ALL_ACCESS, servername,
+                               user, &pol);
+                               
+       if (!W_ERROR_IS_OK(result))
+               goto done;
+
+       opened_hnd = True;
+
+       /* Get printer info */
+        result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, info_level, &ctr);
+
+        if (W_ERROR_V(result) == ERRinsufficientbuffer)
+                result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, info_level, &ctr);
+
+        if (!W_ERROR_IS_OK(result))
+                goto done;
+
+
+       /* Modify the printername. */
+       init_unistr(&ctr.printers_2->printername, new_printername);
+       ctr.printers_2->devmode = NULL;
+       ctr.printers_2->secdesc = NULL;
+
+       result = cli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
+       if (W_ERROR_IS_OK(result))
+               printf("Success in setting printername.\n");
+
+ done:
+       if (opened_hnd)
+               cli_spoolss_close_printer(cli, mem_ctx, &pol);
+
+       return result;
+}
+
 /***********************************************************************
  * Get printer information
  */
@@ -1844,6 +1914,7 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
        PRINTER_INFO_CTR ctr;
        PRINTER_INFO_0 info;
        REGISTRY_VALUE value;
+       UNISTR2 data;
 
        /* parse the command arguements */
        if (argc != 4) {
@@ -1881,10 +1952,11 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
 
        /* Set the printer data */
        
+       init_unistr2(&data, argv[3], UNI_STR_TERMINATE);
        fstrcpy(value.valuename, argv[2]);
        value.type = REG_SZ;
-       value.size = strlen(argv[3]) + 1;
-       value.data_p = talloc_memdup(mem_ctx, argv[3], value.size);
+       value.size = data.uni_str_len * 2;
+       value.data_p = talloc_memdup(mem_ctx, data.buffer, value.size);
 
        result = cli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
                
@@ -2331,6 +2403,7 @@ struct cmd_set spoolss_commands[] = {
        { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         PI_SPOOLSS, "Delete form",                         "" },
        { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         PI_SPOOLSS, "Enumerate forms",                     "" },
        { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         PI_SPOOLSS, "Set printer comment",                 "" },
+       { "setprintername",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername,         PI_SPOOLSS, "Set printername",                 "" },
        { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     PI_SPOOLSS, "Set REG_SZ printer data",             "" },
        { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           PI_SPOOLSS, "Rffpcnex test", "" },
 
index 4d8b768c2fa96350051bcfb74e22c03afdde0c47..bbb4980c766293ec70cf3991c12939539dab43f2 100644 (file)
@@ -36,6 +36,8 @@ static struct idmap_function_entry *backends = NULL;
 static struct idmap_methods *cache_map;
 static struct idmap_methods *remote_map;
 
+static BOOL proxyonly = False;
+
 /**********************************************************************
  Get idmap methods. Don't allow tdb to be a remote method.
 **********************************************************************/
@@ -143,6 +145,15 @@ BOOL idmap_init(const char *remote_backend)
        return True;
 }
 
+/**************************************************************************
+ Don't do id mapping. This is used to make winbind a netlogon proxy only.
+**************************************************************************/
+
+void idmap_proxyonly(void)
+{
+       proxyonly = True;
+}
+
 /**************************************************************************
  This is a rare operation, designed to allow an explicit mapping to be
  set up for a sid to a POSIX id.
@@ -153,6 +164,9 @@ NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
        struct idmap_methods *map = remote_map;
        DOM_SID tmp_sid;
 
+       if (proxyonly)
+               return NT_STATUS_UNSUCCESSFUL;
+
        DEBUG(10, ("idmap_set_mapping: Set %s to %s %lu\n",
                   sid_string_static(sid),
                   ((id_type & ID_TYPEMASK) == ID_USERID) ? "UID" : "GID",
@@ -186,6 +200,9 @@ NTSTATUS idmap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
        NTSTATUS ret;
        int loc_type;
 
+       if (proxyonly)
+               return NT_STATUS_UNSUCCESSFUL;
+
        loc_type = *id_type;
 
        if (remote_map) {
@@ -227,6 +244,9 @@ NTSTATUS idmap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
        NTSTATUS ret;
        int loc_type;
 
+       if (proxyonly)
+               return NT_STATUS_UNSUCCESSFUL;
+
        loc_type = id_type;
        if (remote_map) {
                loc_type = id_type | ID_QUERY_ONLY;
@@ -260,6 +280,9 @@ NTSTATUS idmap_allocate_id(unid_t *id, int id_type)
 {
        /* we have to allocate from the authoritative backend */
        
+       if (proxyonly)
+               return NT_STATUS_UNSUCCESSFUL;
+
        if ( remote_map )
                return remote_map->allocate_id( id, id_type );
 
@@ -274,6 +297,9 @@ NTSTATUS idmap_allocate_rid(uint32 *rid, int type)
 {
        /* we have to allocate from the authoritative backend */
        
+       if (proxyonly)
+               return NT_STATUS_UNSUCCESSFUL;
+
        if ( remote_map )
                return remote_map->allocate_rid( rid, type );
 
@@ -288,6 +314,9 @@ NTSTATUS idmap_close(void)
 {
        NTSTATUS ret;
 
+       if (proxyonly)
+               return NT_STATUS_OK;
+
        ret = cache_map->close();
        if (!NT_STATUS_IS_OK(ret)) {
                DEBUG(3, ("idmap_close: failed to close local tdb cache!\n"));
index 2124fb687937583fba2985b2dcdc5aeb6e80f221..d83c0bdc4d81ab2cd4136cc2ba06e4f6445a9088 100644 (file)
@@ -711,8 +711,12 @@ static NTSTATUS verify_idpool( void )
                        get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER), uid_str );
                smbldap_set_mod( &mods, LDAP_MOD_ADD,
                        get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER), gid_str );
-               
-               rc = smbldap_modify(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), mods);
+               if (mods) {
+                       rc = smbldap_modify(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), mods);
+                       ldap_mods_free( mods, True );
+               } else {
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
        }
 
        return ( rc==LDAP_SUCCESS ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
index b38f405e0da854c6389cc1b08eaa473a446193fc..4c9507dcf9b6c61b2719c3f753d5e40a7c20fd86 100644 (file)
@@ -124,7 +124,7 @@ END {
     gotstart = 1;
   }
 
-  if( $0 ~ /^smb_iconv_t|^long|^char|^uint|^NTSTATUS|^WERROR|^CLI_POLICY_HND|^struct|^BOOL|^void|^time|^smb_shm_offset_t|^shm_offset_t|^FILE|^XFILE|^SMB_OFF_T|^size_t|^ssize_t|^SMB_BIG_UINT/ ) {
+  if( $0 ~ /^smb_iconv_t|^long|^char|^uint|^NTSTATUS|^WERROR|^CLI_POLICY_HND|^struct|^BOOL|^void|^time|^smb_shm_offset_t|^shm_offset_t|^FILE|^XFILE|^SMB_OFF_T|^size_t|^ssize_t|^SMB_BIG_UINT|^SMB_BIG_INT/ ) {
     gotstart = 1;
   }
 
@@ -132,7 +132,7 @@ END {
     gotstart = 1;
   }
 
-  if( $0 ~ /^WINBINDD_PW|^WINBINDD_GR|^NT_PRINTER_INFO_LEVEL_2|^LOGIN_CACHE/ ) {
+  if( $0 ~ /^WINBINDD_PW|^WINBINDD_GR|^NT_PRINTER_INFO_LEVEL_2|^LOGIN_CACHE|^krb5_error_code|^LDAP/ ) {
     gotstart = 1;
   }
 
index c0512d5539b4d47280fc23d0e468e87788f51085..3983a4cbdfbadeca884e7f7f80f6b155e5e95877 100644 (file)
@@ -680,7 +680,7 @@ void process_blocking_lock_queue(time_t t)
                        continue;
                }
 
-               if(!set_current_service(conn,True)) {
+               if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) {
                        DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));
                        /*
                         * Remove the entry and return an error to the client.
index 8b3010c1b2e83c8ab48f47056f2ce61c9ac2fdb3..6de277464425a564ebd9df2600c7af668cb05f23 100644 (file)
@@ -2,6 +2,7 @@
    Unix SMB/CIFS implementation.
    file closing
    Copyright (C) Andrew Tridgell 1992-1998
+   Copyright (C) Jeremy Allison 1992-2004.
    
    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
@@ -104,6 +105,36 @@ static int close_filestruct(files_struct *fsp)
        return ret;
 }    
 
+/****************************************************************************
+ If any deferred opens are waiting on this close, notify them.
+****************************************************************************/
+
+static void notify_deferred_opens(files_struct *fsp)
+{
+       deferred_open_entry *de_array = NULL;
+       int num_de_entries, i;
+       pid_t mypid = sys_getpid();
+
+       if (!lp_defer_sharing_violations()) {
+               return;
+       }
+
+       num_de_entries = get_deferred_opens(fsp->conn, fsp->dev, fsp->inode, &de_array);
+       for (i = 0; i < num_de_entries; i++) {
+               deferred_open_entry *entry = &de_array[i];
+               if (entry->pid == mypid) {
+                       /*
+                        * We need to notify ourself to retry the open.
+                        * Do this by finding the queued SMB record, moving it
+                        * to the head of the queue and changing the wait time to zero.
+                        */
+                       schedule_sharing_violation_open_smb_message(entry->mid);
+               } else {
+                       send_deferred_open_retry_message(entry);
+               }
+       }
+}
+
 /****************************************************************************
  Close a file.
 
@@ -177,6 +208,9 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
 
        SAFE_FREE(share_entry);
 
+       /* Notify any deferred opens waiting on this close. */
+       notify_deferred_opens(fsp);
+
        /*
         * NT can set delete_on_close of the last open
         * reference to a file.
index e083e144263a27b0c26ea90aa49494236e2f7682..34e19a3ca6bbecdd81ea552af1e55386b3b9dbb2 100644 (file)
@@ -161,7 +161,7 @@ void conn_close_all(void)
        connection_struct *conn, *next;
        for (conn=Connections;conn;conn=next) {
                next=conn->next;
-               set_current_service(conn, True);
+               set_current_service(conn, 0, True);
                close_cnum(conn, conn->vuid);
        }
 }
index a9ab14246150f95d2df848dbe947e58cc685cf5a..5bb76eb3bd83a6cf43093dcb2b015e26f3acc1d5 100644 (file)
@@ -29,8 +29,8 @@ static TDB_CONTEXT *tdb;
 TDB_CONTEXT *conn_tdb_ctx(void)
 {
        if (!tdb)
-               tdb = tdb_open_ex(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, 
-                              O_RDWR | O_CREAT, 0644, smbd_tdb_log);
+               tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, 
+                              O_RDWR | O_CREAT, 0644);
 
        return tdb;
 }
@@ -131,8 +131,8 @@ BOOL claim_connection(connection_struct *conn, const char *name,int max_connecti
        TDB_DATA kbuf, dbuf;
 
        if (!tdb)
-               tdb = tdb_open_ex(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, 
-                              O_RDWR | O_CREAT, 0644, smbd_tdb_log);
+               tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, 
+                              O_RDWR | O_CREAT, 0644);
 
        if (!tdb)
                return False;
index 06ef23ab8cd64e2661cf4a5ad4d1fd368154092e..b88f687766d88ba9766956024a5159f4950a51c2 100644 (file)
@@ -763,7 +763,8 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_
                return True;
        else
                fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
-                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
+                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
+                       &access_mode, &smb_action);
 
        if (!fsp)
                return False;
index d7dc63bb2fd746a0092481b9facde94c2b40da5f..33c75fffd53d0535297a7408a3e5fe43513d82de 100644 (file)
@@ -182,6 +182,7 @@ static BOOL get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_S
                if ((errno != ENOTSUP) && (errno != ENOATTR) && (errno != EACCES)) {
                        DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
                                path, strerror(errno) ));
+                       set_store_dos_attributes(SNUM(conn), False);
                }
 #endif
                return False;
@@ -224,9 +225,21 @@ static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_
        files_struct *fsp = NULL;
        BOOL ret = False;
 
+       if (!lp_store_dos_attributes(SNUM(conn))) {
+               return False;
+       }
+
        snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK);
        if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == -1) {
                if((errno != EPERM) && (errno != EACCES)) {
+                       if (errno == ENOSYS
+#if defined(ENOTSUP)
+                               || errno == ENOTSUP) {
+#else
+                               ) {
+#endif
+                               set_store_dos_attributes(SNUM(conn), False);
+                       }
                        return False;
                }
 
index 9c81d465e7ae32efbf21e2b68003038288489ccb..d611e0ef873af4812b3b52439612d8d975720761 100644 (file)
@@ -28,6 +28,17 @@ NTSTATUS unix_ERR_ntstatus = NT_STATUS_OK;
 /* From lib/error.c */
 extern struct unix_error_map unix_dos_nt_errmap[];
 
+/****************************************************************************
+ Ensure we don't have any errors cached.
+****************************************************************************/
+void clear_cached_errors(void)
+{
+       unix_ERR_class = SMB_SUCCESS;
+       unix_ERR_code = 0;
+       unix_ERR_ntstatus = NT_STATUS_OK;
+}
+
 /****************************************************************************
  Create an error packet from a cached error.
 ****************************************************************************/
index 5e5f5726913a69e09067e61b7142b7f68c45708c..ab75d9c06aec989442d7a28fcf0a66d088b9d492 100644 (file)
@@ -135,7 +135,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
                if (SMB_VFS_STAT(conn,name,&st) == 0) {
                        *pst = st;
                }
-               DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
+               DEBUG(5,("conversion finished \"\" -> %s\n",name));
                return(True);
        }
 
@@ -237,6 +237,15 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
                                 */
                                DEBUG(5,("Not a dir %s\n",start));
                                *end = '/';
+                               /* 
+                                * We need to return the fact that the intermediate
+                                * name resolution failed. This is used to return an
+                                * error of ERRbadpath rather than ERRbadfile. Some
+                                * Windows applications depend on the difference between
+                                * these two errors.
+                                */
+                               errno = ENOTDIR;
+                               *bad_path = True;
                                return(False);
                        }
 
@@ -265,6 +274,9 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
                        if (end)
                                pstrcpy(rest,end+1);
 
+                       /* Reset errno so we can detect directory open errors. */
+                       errno = 0;
+
                        /*
                         * Try to find this part of the path in the directory.
                         */
@@ -292,6 +304,11 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
                                        return(False);
                                }
              
+                               if (errno == ENOTDIR) {
+                                       *bad_path = True;
+                                       return(False);
+                               }
+
                                /* 
                                 * Just the last part of the name doesn't exist.
                                 * We may need to strupper() or strlower() it in case
@@ -392,12 +409,11 @@ BOOL check_name(pstring name,connection_struct *conn)
 {
        BOOL ret = True;
 
-       errno = 0;
-
        if (IS_VETO_PATH(conn, name))  {
                /* Is it not dot or dot dot. */
                if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) {
                        DEBUG(5,("file path name %s vetoed\n",name));
+                       errno = ENOENT;
                        return False;
                }
        }
@@ -416,13 +432,15 @@ BOOL check_name(pstring name,connection_struct *conn)
                if ( (SMB_VFS_LSTAT(conn,name,&statbuf) != -1) &&
                                (S_ISLNK(statbuf.st_mode)) ) {
                        DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
+                       errno = EACCES;
                        ret = False; 
                }
        }
 #endif
 
-       if (!ret)
+       if (!ret) {
                DEBUG(5,("check_name on %s failed\n",name));
+       }
 
        return(ret);
 }
@@ -496,5 +514,6 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength,
        }
 
        CloseDir(cur_dir);
+       errno = ENOENT;
        return(False);
 }
index c4df84e76c70ef265b92c622f92b7403e0585276..dd9708356e7a600b959c3d349b65df20fb33c09c 100644 (file)
@@ -1121,11 +1121,11 @@ static int fill_srv_info(struct srv_info_struct *service,
   switch (uLevel)
     {
     case 0:
-           push_ascii(p,service->name, 15, STR_TERMINATE);
+           push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
            break;
 
     case 1:
-           push_ascii(p,service->name,15, STR_TERMINATE);
+           push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
            SIVAL(p,18,service->type);
            SIVAL(p,22,PTR_DIFF(p2,baseaddr));
            len += CopyAndAdvance(&p2,service->comment,&l2);
index 7b8cbdbddba76bd328ccc1ee3cac1f4fe2ad5df3..d7239b82a79a349dcba855b69e10fecba58218c2 100644 (file)
@@ -546,8 +546,10 @@ static void cache_mangled_name( char *mangled_name, char *raw_name )
        /* Fill the new cache entry, and add it to the cache. */
        s1 = (char *)(new_entry + 1);
        s2 = (char *)&(s1[mangled_len + 1]);
-       safe_strcpy( s1, mangled_name, mangled_len );
-       safe_strcpy( s2, raw_name,     raw_len );
+       memcpy( s1, mangled_name, mangled_len );
+       s1[mangled_len] = '\0';
+       memcpy( s2, raw_name, raw_len );
+       s2[raw_len] = '\0';
        ubi_cachePut( mangled_cache, i, new_entry, s1 );
 }
 
index c66f0477a84073b2ea02dd01a01f8d5e4a12508b..6c132897f982c1ec0b52b124eb2783736a5a72db 100644 (file)
@@ -65,7 +65,7 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp)
        DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename));
 
        /* rest is reqpath */
-       check_path_syntax(pdp->reqpath, p+1);
+       check_path_syntax(pdp->reqpath, p+1,True);
 
        DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath));
        return True;
@@ -111,7 +111,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp)
        DEBUG(10,("parse_processed_dfs_path: servicename: %s\n",pdp->servicename));
 
        /* rest is reqpath */
-       check_path_syntax(pdp->reqpath, p+1);
+       check_path_syntax(pdp->reqpath, p+1,True);
 
        DEBUG(10,("parse_processed_dfs_path: rest of the path: %s\n",pdp->reqpath));
        return True;
index 1843c174bb5b8482ee4f3cd053aeda0422270275..5ff53f63007113dd579e76842a58216d9193d937 100644 (file)
@@ -401,8 +401,9 @@ protocol [LANMAN2.1]
 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
 #define ARCH_SAMBA    0x20
+#define ARCH_CIFSFS   0x40
  
-#define ARCH_ALL      0x3F
+#define ARCH_ALL      0x7F
  
 /* List of supported protocols, most desired first */
 static const struct {
@@ -413,6 +414,7 @@ static const struct {
 } supported_protocols[] = {
        {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
        {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
+       {"POSIX 2",                 "NT1",      reply_nt1,      PROTOCOL_NT1},
        {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
        {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
        {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
@@ -460,7 +462,7 @@ int reply_negprot(connection_struct *conn,
                else if (strcsequal(p,"DOS LANMAN2.1"))
                        arch &= ( ARCH_WFWG | ARCH_WIN95 );
                else if (strcsequal(p,"NT LM 0.12"))
-                       arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
+                       arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS);
                else if (strcsequal(p,"LANMAN2.1"))
                        arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
                else if (strcsequal(p,"LM1.2X002"))
@@ -472,12 +474,23 @@ int reply_negprot(connection_struct *conn,
                else if (strcsequal(p,"Samba")) {
                        arch = ARCH_SAMBA;
                        break;
+               } else if (strcsequal(p,"POSIX 2")) {
+                       arch = ARCH_CIFSFS;
+                       break;
                }
  
                p += strlen(p) + 2;
        }
-    
+
+       /* CIFSFS can send one arch only, NT LM 0.12. */
+       if (Index == 1 && (arch & ARCH_CIFSFS)) {
+               arch = ARCH_CIFSFS;
+       }
+
        switch ( arch ) {
+               case ARCH_CIFSFS:
+                       set_remote_arch(RA_CIFSFS);
+                       break;
                case ARCH_SAMBA:
                        set_remote_arch(RA_SAMBA);
                        break;
index ec414454f9eac09acb168229e24301bcdae9b68c..843580f6edfc1df3e2b93e1a8750dd1233ed8524 100644 (file)
@@ -164,7 +164,7 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path,
 
        if (!change_to_user(conn,vuid))
                return True;
-       if (!set_current_service(conn,True)) {
+       if (!set_current_service(conn,FLAG_CASELESS_PATHNAMES,True)) {
                change_to_root_user();
                return True;
        }
index 26be4434fdb19b844d86352bf24f5b1fab09617e..f717efac63eb9f88b1096621afc0411c57e0ff61 100644 (file)
@@ -651,7 +651,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
 
                if(!dir_fsp->is_directory) {
 
-                       srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
+                       srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status,False);
                        if (!NT_STATUS_IS_OK(status)) {
                                END_PROFILE(SMBntcreateX);
                                return ERROR_NT(status);
@@ -693,14 +693,14 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                        dir_name_len++;
                }
 
-               srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status);
+               srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status,False);
                if (!NT_STATUS_IS_OK(status)) {
                        END_PROFILE(SMBntcreateX);
                        return ERROR_NT(status);
                }
                pstrcat(fname, rel_fname);
        } else {
-               srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
+               srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status,False);
                if (!NT_STATUS_IS_OK(status)) {
                        END_PROFILE(SMBntcreateX);
                        return ERROR_NT(status);
@@ -762,7 +762,18 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
        set_posix_case_semantics(conn, file_attributes);
                
        unix_convert(fname,conn,0,&bad_path,&sbuf);
-               
+       if (bad_path) {
+               restore_case_semantics(conn, file_attributes);
+               END_PROFILE(SMBntcreateX);
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+       }
+       /* All file access must go through check_name() */
+       if (!check_name(fname,conn)) {
+               restore_case_semantics(conn, file_attributes);
+               END_PROFILE(SMBntcreateX);
+               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+       }
+
        /* 
         * If it's a request for a directory open, deal with it separately.
         */
@@ -863,6 +874,11 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
 
                                restore_case_semantics(conn, file_attributes);
                                END_PROFILE(SMBntcreateX);
+                               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+                                       /* We have re-scheduled this call. */
+                                       clear_cached_errors();
+                                       return -1;
+                               }
                                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
                        }
                } 
@@ -1010,7 +1026,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha
                return ERROR_DOS(ERRDOS,ERRnoaccess);
        }
 
-       srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False);
        if (!NT_STATUS_IS_OK(status)) {
                return ERROR_NT(status);
        }
@@ -1213,7 +1229,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                        return ERROR_DOS(ERRDOS,ERRbadfid);
 
                if(!dir_fsp->is_directory) {
-                       srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
+                       srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False);
                        if (!NT_STATUS_IS_OK(status)) {
                                return ERROR_NT(status);
                        }
@@ -1246,14 +1262,14 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
 
                {
                        pstring tmpname;
-                       srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status);
+                       srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status, False);
                        if (!NT_STATUS_IS_OK(status)) {
                                return ERROR_NT(status);
                        }
                        pstrcat(fname, tmpname);
                }
        } else {
-               srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
+               srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False);
                if (!NT_STATUS_IS_OK(status)) {
                        return ERROR_NT(status);
                }
@@ -1287,6 +1303,15 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
        RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
 
        unix_convert(fname,conn,0,&bad_path,&sbuf);
+       if (bad_path) {
+               restore_case_semantics(conn, file_attributes);
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+       }
+       /* All file access must go through check_name() */
+       if (!check_name(fname,conn)) {
+               restore_case_semantics(conn, file_attributes);
+               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+       }
     
        /*
         * If it's a request for a directory open, deal with it separately.
@@ -1347,6 +1372,11 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                                }
                        } else {
                                restore_case_semantics(conn, file_attributes);
+                               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+                                       /* We have re-scheduled this call. */
+                                       clear_cached_errors();
+                                       return -1;
+                               }
                                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
                        }
                } 
@@ -1490,6 +1520,155 @@ int reply_ntcancel(connection_struct *conn,
        return(-1);
 }
 
+/****************************************************************************
+ Copy a file.
+****************************************************************************/
+
+static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint16 attrs)
+{
+       BOOL bad_path_oldname = False;
+       BOOL bad_path_newname = False;
+       SMB_STRUCT_STAT sbuf1, sbuf2;
+       pstring last_component_oldname;
+       pstring last_component_newname;
+       files_struct *fsp1,*fsp2;
+       uint16 fmode;
+       int access_mode;
+       int smb_action;
+       SMB_OFF_T ret=-1;
+       int close_ret;
+       NTSTATUS status = NT_STATUS_OK;
+
+       ZERO_STRUCT(sbuf1);
+       ZERO_STRUCT(sbuf2);
+
+       /* No wildcards. */
+       if (ms_has_wild(newname) || ms_has_wild(oldname)) {
+               return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
+       }
+
+       if (!CAN_WRITE(conn))
+               return NT_STATUS_MEDIA_WRITE_PROTECTED;
+
+       unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
+       if (bad_path_oldname) {
+               return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+       }
+
+       /* Quick check for "." and ".." */
+       if (last_component_oldname[0] == '.') {
+               if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
+                       return NT_STATUS_OBJECT_NAME_INVALID;
+               }
+       }
+
+        /* Source must already exist. */
+       if (!VALID_STAT(sbuf1)) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+       if (!check_name(oldname,conn)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       /* Ensure attributes match. */
+       fmode = dos_mode(conn,oldname,&sbuf1);
+       if ((fmode & ~attrs) & (aHIDDEN | aSYSTEM))
+               return NT_STATUS_NO_SUCH_FILE;
+
+       unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
+       if (bad_path_newname) {
+               return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+       }
+
+       /* Quick check for "." and ".." */
+       if (last_component_newname[0] == '.') {
+               if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
+                       return NT_STATUS_OBJECT_NAME_INVALID;
+               }
+       }
+
+       /* Disallow if newname already exists. */
+       if (VALID_STAT(sbuf2)) {
+               return NT_STATUS_OBJECT_NAME_COLLISION;
+       }
+
+       if (!check_name(newname,conn)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       /* No links from a directory. */
+       if (S_ISDIR(sbuf1.st_mode)) {
+               return NT_STATUS_FILE_IS_A_DIRECTORY;
+       }
+
+       /* Ensure this is within the share. */
+       if (!reduce_name(conn, oldname) != 0) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname));
+
+        fsp1 = open_file_shared1(conn,oldname,&sbuf1,FILE_READ_DATA,SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
+                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0,
+                       &access_mode,&smb_action);
+
+       if (!fsp1) {
+               status = NT_STATUS_ACCESS_DENIED;
+               if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
+                       status = NT_STATUS_SHARING_VIOLATION;
+               unix_ERR_class = 0;
+               unix_ERR_code = 0;
+               unix_ERR_ntstatus = NT_STATUS_OK;
+               return status;
+       }
+
+       fsp2 = open_file_shared1(conn,newname,&sbuf2,FILE_WRITE_DATA,SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
+                       (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL),fmode,INTERNAL_OPEN_ONLY,
+                       &access_mode,&smb_action);
+
+       if (!fsp2) {
+               status = NT_STATUS_ACCESS_DENIED;
+               if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
+                       status = NT_STATUS_SHARING_VIOLATION;
+               unix_ERR_class = 0;
+               unix_ERR_code = 0;
+               unix_ERR_ntstatus = NT_STATUS_OK;
+               close_file(fsp1,False);
+               return status;
+       }
+
+       if (sbuf1.st_size)
+               ret = vfs_transfer_file(fsp1, fsp2, sbuf1.st_size);
+
+       /*
+        * As we are opening fsp1 read-only we only expect
+        * an error on close on fsp2 if we are out of space.
+        * Thus we don't look at the error return from the
+        * close of fsp1.
+        */
+       close_file(fsp1,False);
+
+       /* Ensure the modtime is set correctly on the destination file. */
+       fsp2->pending_modtime = sbuf1.st_mtime;
+
+       close_ret = close_file(fsp2,False);
+
+       /* Grrr. We have to do this as open_file_shared1 adds aARCH when it
+          creates the file. This isn't the correct thing to do in the copy case. JRA */
+       file_set_dosmode(conn, newname, fmode, &sbuf2);
+
+       if (ret < (SMB_OFF_T)sbuf1.st_size) {
+               return NT_STATUS_DISK_FULL;
+       }
+
+       if (close_ret != 0) {
+               status = map_nt_error_from_unix(close_ret);
+               DEBUG(3,("copy_internals: Error %s copy file %s to %s\n",
+                       nt_errstr(status), oldname, newname));
+       }
+       return status;
+}
+
 /****************************************************************************
  Reply to a NT rename request.
 ****************************************************************************/
@@ -1507,13 +1686,8 @@ int reply_ntrename(connection_struct *conn,
 
        START_PROFILE(SMBntrename);
 
-       if ((rename_type != RENAME_FLAG_RENAME) && (rename_type != RENAME_FLAG_HARD_LINK)) {
-               END_PROFILE(SMBntrename);
-               return ERROR_NT(NT_STATUS_ACCESS_DENIED);
-       }
-
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status);
+       p += srvstr_get_path(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, True);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBntrename);
                return ERROR_NT(status);
@@ -1525,8 +1699,13 @@ int reply_ntrename(connection_struct *conn,
                return ERROR_NT(NT_STATUS_ACCESS_DENIED);
        }
 
+       if (ms_has_wild(oldname)) {
+               END_PROFILE(SMBntrename);
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
+       }
+
        p++;
-       p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
+       p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, False);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBntrename);
                return ERROR_NT(status);
@@ -1537,14 +1716,31 @@ int reply_ntrename(connection_struct *conn,
        
        DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname));
        
-       if (rename_type == RENAME_FLAG_RENAME) {
-               status = rename_internals(conn, oldname, newname, attrs, False);
-       } else {
-               status = hardlink_internals(conn, oldname, newname);
+       switch(rename_type) {
+               case RENAME_FLAG_RENAME:
+                       status = rename_internals(conn, oldname, newname, attrs, False);
+                       break;
+               case RENAME_FLAG_HARD_LINK:
+                       status = hardlink_internals(conn, oldname, newname);
+                       break;
+               case RENAME_FLAG_COPY:
+                       status = copy_internals(conn, oldname, newname, attrs);
+                       break;
+               case RENAME_FLAG_MOVE_CLUSTER_INFORMATION:
+                       status = NT_STATUS_INVALID_PARAMETER;
+                       break;
+               default:
+                       status = NT_STATUS_ACCESS_DENIED; /* Default error. */
+                       break;
        }
 
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBntrename);
+               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+                       /* We have re-scheduled this call. */
+                       clear_cached_errors();
+                       return -1;
+               }
                return ERROR_NT(status);
        }
 
@@ -1630,7 +1826,7 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
        fsp = file_fsp(params, 0);
        replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False;
        CHECK_FSP(fsp, conn);
-       srvstr_get_path(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE, &status, True);
        if (!NT_STATUS_IS_OK(status)) {
                return ERROR_NT(status);
        }
index 3b4f50b06566775bd8d32991e2597529cddfc666..65500c65cee6ccc282170c569959bb12f11e99c2 100644 (file)
@@ -2,7 +2,7 @@
    Unix SMB/CIFS implementation.
    file opening and share modes
    Copyright (C) Andrew Tridgell 1992-1998
-   Copyright (C) Jeremy Allison 2001
+   Copyright (C) Jeremy Allison 2001-2004
    
    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
@@ -26,6 +26,11 @@ extern uint16 global_oplock_port;
 extern uint16 global_smbpid;
 extern BOOL global_client_failed_oplock_break;
 
+struct dev_inode_bundle {
+       SMB_DEV_T dev;
+       SMB_INO_T inode;
+};
+
 /****************************************************************************
  fd support routines - attempt to do a dos_open.
 ****************************************************************************/
@@ -239,11 +244,12 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn,
                 BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write),
                 conn->num_files_open + 1));
 
+       errno = 0;
        return True;
 }
 
 /*******************************************************************
-return True if the filename is one of the special executable types
+ Return True if the filename is one of the special executable types.
 ********************************************************************/
 
 static BOOL is_executable(const char *fname)
@@ -262,12 +268,13 @@ static BOOL is_executable(const char *fname)
 enum {AFAIL,AREAD,AWRITE,AALL};
 
 /*******************************************************************
-reproduce the share mode access table
-this is horrendoously complex, and really can't be justified on any
-rational grounds except that this is _exactly_ what NT does. See
-the DENY1 and DENY2 tests in smbtorture for a comprehensive set of
-test routines.
+ Reproduce the share mode access table.
+ This is horrendoously complex, and really can't be justified on any
+ rational grounds except that this is _exactly_ what NT does. See
+ the DENY1 and DENY2 tests in smbtorture for a comprehensive set of
+ test routines.
 ********************************************************************/
+
 static int access_table(int new_deny,int old_deny,int old_mode,
                        BOOL same_pid, BOOL isexe)
 {
@@ -353,9 +360,8 @@ static int access_table(int new_deny,int old_deny,int old_mode,
          return(AFAIL);      
 }
 
-
 /****************************************************************************
-check if we can open a file with a share mode
+ Check if we can open a file with a share mode.
 ****************************************************************************/
 
 static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, int share_mode, uint32 desired_access,
@@ -364,6 +370,8 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i
        int deny_mode = GET_DENY_MODE(share_mode);
        int old_open_mode = GET_OPEN_MODE(share->share_mode);
        int old_deny_mode = GET_DENY_MODE(share->share_mode);
+       BOOL non_io_open_request;
+       BOOL non_io_open_existing;
 
        /*
         * share modes = false means don't bother to check for
@@ -373,6 +381,18 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i
        if(!lp_share_modes(SNUM(conn)))
                return True;
 
+       if (desired_access & ~(SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) {
+               non_io_open_request = False;
+       } else {
+               non_io_open_request = True;
+       }
+
+       if (share->desired_access & ~(SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) {
+               non_io_open_existing = False;
+       } else {
+               non_io_open_existing = True;
+       }
+
        /*
         * Don't allow any opens once the delete on close flag has been
         * set.
@@ -411,8 +431,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i
         * and the existing desired_acces then share modes don't conflict.
         */
 
-       if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) &&
-               !(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) {
+       if (non_io_open_request && non_io_open_existing) {
 
                /*
                 * Wrinkle discovered by smbtorture....
@@ -436,6 +455,13 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i
 and existing desired access (0x%x) are non-data opens\n", 
                        fname, (unsigned int)desired_access, (unsigned int)share->desired_access ));
                return True;
+       } else if (non_io_open_request || non_io_open_existing) {
+               /*
+                * If either are non-io opens then share modes don't conflict.
+                */
+               DEBUG(5,("check_share_mode: One non-io open. Allowing open on file %s as desired access (0x%x) doesn't conflict with\
+existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access ));
+               return True;
        }
 
        /*
@@ -537,6 +563,20 @@ static void validate_my_share_entries(int num, share_mode_entry *share_entry)
 }
 #endif
 
+struct share_mode_entry_list {
+       struct share_mode_entry_list *next, *prev;
+       share_mode_entry entry;
+};
+
+static void free_broken_entry_list(struct share_mode_entry_list *broken_entry_list)
+{
+       while (broken_entry_list) {
+               struct share_mode_entry_list *broken_entry = broken_entry_list;
+               DLIST_REMOVE(broken_entry_list, broken_entry);
+               SAFE_FREE(broken_entry);
+       }
+}
+
 /****************************************************************************
  Deal with open deny mode and oplock break processing.
  Invarient: Share mode must be locked on entry and exit.
@@ -554,8 +594,8 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T
        int oplock_contention_count = 0;
        share_mode_entry *old_shares = 0;
        BOOL fcbopen = False;
-       BOOL broke_oplock;      
-       
+       BOOL broke_oplock;
+
        if(GET_OPEN_MODE(share_mode) == DOS_OPEN_FCB)
                fcbopen = True;
        
@@ -564,17 +604,25 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T
        if(num_share_modes == 0)
                return 0;
        
+       if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) &&
+               ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) {
+               /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */
+               return num_share_modes;
+       }
+
        /*
         * Check if the share modes will give us access.
         */
        
        do {
-               share_mode_entry broken_entry;
-               
+               struct share_mode_entry_list *broken_entry_list = NULL;
+               struct share_mode_entry_list *broken_entry = NULL;
+
                broke_oplock = False;
                *p_all_current_opens_are_level_II = True;
                
                for(i = 0; i < num_share_modes; i++) {
+                       BOOL cause_oplock_break = False;
                        share_mode_entry *share_entry = &old_shares[i];
                        
 #if defined(DEVELOPER)
@@ -589,9 +637,17 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T
                         * it before continuing. 
                         */
                        
-                       if((*p_oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) ||
+                       /* Was this a delete this file request ? */
+                       if (!*p_oplock_request && desired_access == DELETE_ACCESS &&
+                                       !BATCH_OPLOCK_TYPE(share_entry->op_type)) {
+                               /* Don't break the oplock in this case. */
+                               cause_oplock_break = False;
+                       } else if((*p_oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) ||
                           (!*p_oplock_request && (share_entry->op_type != NO_OPLOCK))) {
-                               
+                               cause_oplock_break = True;
+                       }
+
+                       if(cause_oplock_break) {
                                BOOL opb_ret;
 
                                DEBUG(5,("open_mode_check: oplock_request = %d, breaking oplock (%x) on file %s, \
@@ -622,50 +678,65 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
                                        return -1;
                                }
                                
+                               broken_entry = malloc(sizeof(struct share_mode_entry_list));
+                               if (!broken_entry) {
+                                       smb_panic("open_mode_check: malloc fail.\n");
+                               }
+                               broken_entry->entry = *share_entry;
+                               DLIST_ADD(broken_entry_list, broken_entry);
                                broke_oplock = True;
-                               broken_entry = *share_entry;
-                               break;
                                
                        } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) {
                                *p_all_current_opens_are_level_II = False;
                        }
-                       
+               } /* end for */
+               
+               if (broke_oplock) {
+                       /* Update the current open table. */
+                       SAFE_FREE(old_shares);
+                       num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
+               }
+
+               /* Now we check the share modes, after any oplock breaks. */
+               for(i = 0; i < num_share_modes; i++) {
+                       share_mode_entry *share_entry = &old_shares[i];
+
                        /* someone else has a share lock on it, check to see if we can too */
                        if (!check_share_mode(conn, share_entry, share_mode, desired_access,
                                                fname, fcbopen, p_flags)) {
                                SAFE_FREE(old_shares);
+                               free_broken_entry_list(broken_entry_list);
                                errno = EACCES;
                                return -1;
                         }
-                       
-               } /* end for */
-               
-               if(broke_oplock) {
-                       SAFE_FREE(old_shares);
-                       num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
+               }
+
+               for(broken_entry = broken_entry_list; broken_entry; broken_entry = broken_entry->next) {
                        oplock_contention_count++;
                        
                        /* Paranoia check that this is no longer an exlusive entry. */
                        for(i = 0; i < num_share_modes; i++) {
                                share_mode_entry *share_entry = &old_shares[i];
                                
-                               if (share_modes_identical(&broken_entry, share_entry) && 
-                                   EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type) ) {
+                               if (share_modes_identical(&broken_entry->entry, share_entry) && 
+                                           EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type) ) {
                                        
                                        /*
                                         * This should not happen. The target left this oplock
                                         * as exlusive.... The process *must* be dead.... 
                                         */
                                        
-                                       DEBUG(0,("open_mode_check: exlusive oplock left by process %d after break ! For file %s, \
-dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fname, (unsigned int)dev, (double)inode));
+                                       DEBUG(0,("open_mode_check: exlusive oplock left by process %d \
+after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n",
+                                               (int)broken_entry->entry.pid, fname, (unsigned int)dev, (double)inode));
                                        
-                                       if (process_exists(broken_entry.pid)) {
+                                       if (process_exists(broken_entry->entry.pid)) {
                                                DEBUG(0,("open_mode_check: Existent process %lu left active oplock.\n",
-                                                        (unsigned long)broken_entry.pid ));
+                                                        (unsigned long)broken_entry->entry.pid ));
                                        }
                                        
-                                       if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) {
+                                       if (del_share_entry(dev, inode, &broken_entry->entry, NULL) == -1) {
+                                               free_broken_entry_list(broken_entry_list);
                                                errno = EACCES;
                                                unix_ERR_class = ERRDOS;
                                                unix_ERR_code = ERRbadshare;
@@ -683,8 +754,8 @@ dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fn
                                        break;
                                }
                        } /* end for paranoia... */
-               } /* end if broke_oplock */
-               
+               } /* end for broken_entry */
+               free_broken_entry_list(broken_entry_list);
        } while(broke_oplock);
        
        if(old_shares != 0)
@@ -705,9 +776,119 @@ dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fn
 }
 
 /****************************************************************************
-set a kernel flock on a file for NFS interoperability
-this requires a patch to Linux
+ Delete the record for a handled deferred open entry.
 ****************************************************************************/
+
+static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode)
+{
+       uint16 mid = get_current_mid();
+       pid_t mypid = sys_getpid();
+       deferred_open_entry *de_array = NULL;
+       int num_de_entries, i;
+
+       if (!lp_defer_sharing_violations()) {
+               return;
+       }
+
+       num_de_entries = get_deferred_opens(conn, dev, inode, &de_array);
+       for (i = 0; i < num_de_entries; i++) {
+               deferred_open_entry *entry = &de_array[i];
+               if (entry->pid == mypid && entry->mid == mid && entry->dev == dev &&
+                       entry->inode == inode) {
+
+                       /* Remove the deferred open entry from the array. */
+                       delete_deferred_open_entry(entry);
+                       SAFE_FREE(de_array);
+                       return;
+               }
+       }
+       SAFE_FREE(de_array);
+}
+
+/****************************************************************************
+ Handle the 1 second delay in returning a SHARING_VIOLATION error.
+****************************************************************************/
+
+void defer_open_sharing_error(connection_struct *conn, struct timeval *ptv,
+               char *fname, SMB_DEV_T dev, SMB_INO_T inode)
+{
+       uint16 mid = get_current_mid();
+       pid_t mypid = sys_getpid();
+       deferred_open_entry *de_array = NULL;
+       int num_de_entries, i;
+       struct dev_inode_bundle dib;
+
+       if (!lp_defer_sharing_violations()) {
+               return;
+       }
+
+       dib.dev = dev;
+       dib.inode = inode;
+
+       num_de_entries = get_deferred_opens(conn, dev, inode, &de_array);
+       for (i = 0; i < num_de_entries; i++) {
+               deferred_open_entry *entry = &de_array[i];
+               if (entry->pid == mypid && entry->mid == mid) {
+                       /*
+                        * Check if a 1 second timeout has expired.
+                        */
+                       if (usec_time_diff(ptv, &entry->time) > SHARING_VIOLATION_USEC_WAIT) {
+                               DEBUG(10,("defer_open_sharing_error: Deleting deferred open entry for mid %u, \
+file %s\n",
+                                       (unsigned int)mid, fname ));
+
+                               /* Expired, return a real error. */
+                               /* Remove the deferred open entry from the array. */
+
+                               delete_deferred_open_entry(entry);
+                               SAFE_FREE(de_array);
+                               return;
+                       }
+                       /*
+                        * If the timeout hasn't expired yet and we still have a sharing violation,
+                        * just leave the entry in the deferred open array alone. We do need to
+                        * reschedule this open call though (with the original created time).
+                        */
+                       DEBUG(10,("defer_open_sharing_error: time [%u.%06u] updating \
+deferred open entry for mid %u, file %s\n",
+                               (unsigned int)entry->time.tv_sec,
+                               (unsigned int)entry->time.tv_usec,
+                               (unsigned int)mid, fname ));
+
+                       push_sharing_violation_open_smb_message(&entry->time, (char *)&dib, sizeof(dib));
+                       SAFE_FREE(de_array);
+                       return;
+               }
+       }
+
+       DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred open entry for mid %u, file %s\n",
+               (unsigned int)ptv->tv_sec, (unsigned int)ptv->tv_usec, (unsigned int)mid, fname ));
+
+       if (!push_sharing_violation_open_smb_message(ptv, (char *)&dib, sizeof(dib))) {
+               SAFE_FREE(de_array);
+               return;
+       }
+       if (!add_deferred_open(mid, ptv, dev, inode, global_oplock_port, fname)) {
+               remove_sharing_violation_open_smb_message(mid);
+       }
+
+       /*
+        * Push the MID of this packet on the signing queue.
+        * We only do this once, the first time we push the packet
+        * onto the deferred open queue, as this has a side effect
+        * of incrementing the response sequence number.
+        */
+
+       srv_defer_sign_response(mid);
+
+       SAFE_FREE(de_array);
+}
+
+/****************************************************************************
+ Set a kernel flock on a file for NFS interoperability.
+ This requires a patch to Linux.
+****************************************************************************/
+
 static void kernel_flock(files_struct *fsp, int deny_mode)
 {
 #if HAVE_KERNEL_SHARE_MODES
@@ -781,6 +962,8 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
        BOOL file_existed = VALID_STAT(*psbuf);
        BOOL fcbopen = False;
        BOOL def_acl = False;
+       BOOL add_share_mode = True;
+       BOOL internal_only_open = False;
        SMB_DEV_T dev = 0;
        SMB_INO_T inode = 0;
        int num_share_modes = 0;
@@ -792,9 +975,50 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
        mode_t new_mode = (mode_t)0;
        int action;
        uint32 existing_dos_mode = 0;
+       struct pending_message_list *pml = NULL;
+       uint16 mid = get_current_mid();
        /* We add aARCH to this as this mode is only used if the file is created new. */
        mode_t mode = unix_mode(conn,new_dos_mode | aARCH,fname);
 
+       if (oplock_request == INTERNAL_OPEN_ONLY) {
+               internal_only_open = True;
+               oplock_request = 0;
+       }
+
+       if ((pml = get_open_deferred_message(mid)) != NULL) {
+               struct dev_inode_bundle dib;
+
+               memcpy(&dib, pml->private_data.data, sizeof(dib));
+
+               /* There could be a race condition where the dev/inode pair
+                       has changed since we deferred the message. If so, just
+                       remove the deferred open entry and return sharing violation. */
+
+               /* If the timeout value is non-zero, we need to just
+                       return sharing violation. Don't retry the open
+                       as we were not notified of a close and we don't want to
+                       trigger another spurious oplock break. */
+
+               if (!file_existed || dib.dev != psbuf->st_dev || dib.inode != psbuf->st_ino ||
+                               pml->msg_time.tv_sec || pml->msg_time.tv_usec) {
+                       /* Ensure we don't reprocess this message. */
+                       remove_sharing_violation_open_smb_message(mid);
+
+                       /* Now remove the deferred open entry under lock. */
+                       lock_share_entry(conn, dib.dev, dib.inode);
+                       delete_defered_open_entry_record(conn, dib.dev, dib.inode);
+                       unlock_share_entry(conn, dib.dev, dib.inode);
+
+                       unix_ERR_class = ERRDOS;
+                       unix_ERR_code = ERRbadshare;
+                       unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;
+                       return NULL;
+               }
+               /* Ensure we don't reprocess this message. */
+               remove_sharing_violation_open_smb_message(mid);
+
+       }
+
        if (conn->printer) {
                /* printers are handled completely differently. Most of the passed parameters are
                        ignored */
@@ -805,25 +1029,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
                return print_fsp_open(conn, fname);
        }
 
-       if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) &&
-               ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) {
-               /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */
-               oplock_request = 0;
-               fsp = open_file_stat(conn, fname, psbuf);
-               if (!fsp)
-                       return NULL;
-
-               fsp->desired_access = desired_access;
-               if (Access)
-                       *Access = DOS_OPEN_RDONLY;
-               if (paction)
-                       *paction = FILE_WAS_OPENED;
-
-               DEBUG(10,("open_file_shared: stat open for fname = %s share_mode = %x\n",
-                       fname, share_mode ));
-               return fsp;
-       }
-
        fsp = file_new(conn);
        if(!fsp)
                return NULL;
@@ -947,6 +1152,17 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
                return NULL;
        }
 
+       if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) &&
+               ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) {
+               /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */
+               deny_mode = DENY_NONE;
+               if (file_existed) {
+                       oplock_request = 0;
+                       add_share_mode = False;
+                       flags2 &= ~O_CREAT;
+               }
+       }
+
        if (file_existed) {
 
                dev = psbuf->st_dev;
@@ -985,17 +1201,28 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
                                unix_ERR_ntstatus = NT_STATUS_ACCESS_DENIED;
                        }
 
+                       /* 
+                        * If we're returning a share violation, ensure we cope with
+                        * the braindead 1 second delay.
+                        */
+
+                       if (!internal_only_open && NT_STATUS_EQUAL(unix_ERR_ntstatus,NT_STATUS_SHARING_VIOLATION)) {
+                               /* The fsp->open_time here represents the current time of day. */
+                               defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode);
+                       }
+
                        unlock_share_entry(conn, dev, inode);
-                       if (fsp_open)
+                       if (fsp_open) {
                                fd_close(conn, fsp);
+                               /*
+                                * We have detected a sharing violation here
+                                * so return the correct error code
+                                */
+                               unix_ERR_class = ERRDOS;
+                               unix_ERR_code = ERRbadshare;
+                               unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;
+                       }
                        file_free(fsp);
-                       /*
-                        * We have detected a sharing violation here
-                        * so return the correct error code
-                        */
-                        unix_ERR_class = ERRDOS;
-                        unix_ERR_code = ERRbadshare;
-                        unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;
                        return NULL;
                }
 
@@ -1060,6 +1287,16 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
                                                  &flags, &oplock_request, &all_current_opens_are_level_II);
 
                if(num_share_modes == -1) {
+                       /* 
+                        * If we're returning a share violation, ensure we cope with
+                        * the braindead 1 second delay.
+                        */
+
+                       if (!internal_only_open && NT_STATUS_EQUAL(unix_ERR_ntstatus,NT_STATUS_SHARING_VIOLATION)) {
+                               /* The fsp->open_time here represents the current time of day. */
+                               defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode);
+                       }
+
                        unlock_share_entry_fsp(fsp);
                        fd_close(conn,fsp);
                        file_free(fsp);
@@ -1166,14 +1403,18 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
                oplock_request = 0;
        }
 
-       set_share_mode(fsp, port, oplock_request);
+       if (add_share_mode) {
+               set_share_mode(fsp, port, oplock_request);
+       }
 
        if (delete_on_close) {
                NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close);
 
                if (NT_STATUS_V(result) !=  NT_STATUS_V(NT_STATUS_OK)) {
                        /* Remember to delete the mode we just added. */
-                       del_share_mode(fsp, NULL);
+                       if (add_share_mode) {
+                               del_share_mode(fsp, NULL);
+                       }
                        unlock_share_entry_fsp(fsp);
                        fd_close(conn,fsp);
                        file_free(fsp);
@@ -1224,6 +1465,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
                                fname, (int)new_mode));
        }
 
+       /* If this is a successful open, we must remove any deferred open records. */
+       delete_defered_open_entry_record(conn, fsp->dev, fsp->inode);
        unlock_share_entry_fsp(fsp);
 
        conn->num_files_open++;
index 19e6956d9ef8b06864a86fdc194a84f8a4149264..1ffc798b1fc388fb4865456a0b90f2e6953d04c5 100644 (file)
@@ -388,6 +388,30 @@ pid %d, port %d, dev = %x, inode = %.0f, file_id = %lu\n",
                                (int)remotepid, from_port, (unsigned int)dev, (double)inode, file_id));
                        break;
 
+               case RETRY_DEFERRED_OPEN_CMD:
+
+                       /* Request to retry and open that would return SHARING_VIOLATION. */
+                       if (msg_len != DEFERRED_OPEN_MSG_LEN) {
+                               DEBUG(0,("process_local_message: incorrect length for RETRY_DEFERRED_OPEN_CMD (was %d, should be %d).\n",
+                                       (int)msg_len, (int)DEFERRED_OPEN_MSG_LEN));
+                               return False;
+                       }
+                       {
+                               uint16 mid;
+
+                               memcpy((char *)&remotepid, msg_start+DEFERRED_OPEN_PID_OFFSET,sizeof(remotepid));
+                               memcpy((char *)&inode, msg_start+DEFERRED_OPEN_INODE_OFFSET,sizeof(inode));
+                               memcpy((char *)&dev, msg_start+DEFERRED_OPEN_DEV_OFFSET,sizeof(dev));
+                               memcpy((char *)&mid, msg_start+DEFERRED_OPEN_MID_OFFSET,sizeof(mid));
+
+                               DEBUG(5,("process_local_message: RETRY_DEFERRED_OPEN from \
+pid %d, port %d, dev = %x, inode = %.0f, mid = %u\n",
+                                       (int)remotepid, from_port, (unsigned int)dev, (double)inode, (unsigned int)mid));
+
+                               schedule_sharing_violation_open_smb_message(mid);
+                       }
+                       return True;
+
                /* 
                 * Keep this as a debug case - eventually we can remove it.
                 */
@@ -592,6 +616,8 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token)
         */
 
        if (global_client_caps & CAP_LEVEL_II_OPLOCKS) {
+               BOOL sign_state;
+
                /*
                 * If we are sending an oplock break due to an SMB sent
                 * by our own client we ensure that we wait at leat
@@ -603,10 +629,16 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token)
                wait_before_sending_break(local_request);
 
                /* Prepare the SMBlockingX message. */
-
                prepare_break_message( outbuf, fsp, False);
+
+               /* Save the server smb signing state. */
+               sign_state = srv_oplock_set_signing(False);
+
                if (!send_smb(smbd_server_fd(), outbuf))
                        exit_server("oplock_break_level2: send_smb failed.");
+
+               /* Restore the sign state to what it was. */
+               srv_oplock_set_signing(sign_state);
        }
 
        /*
@@ -1215,7 +1247,51 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
 }
 
 /****************************************************************************
-setup oplocks for this process
+ Send a 'retry your open' message to a process with a deferred open entry.
+****************************************************************************/
+
+BOOL send_deferred_open_retry_message(deferred_open_entry *entry)
+{
+       char de_msg[DEFERRED_OPEN_MSG_LEN];
+       struct sockaddr_in addr_out;
+       pid_t pid = sys_getpid();
+
+       memset(de_msg, '\0', DEFERRED_OPEN_MSG_LEN);
+       SSVAL(de_msg,DEFERRED_OPEN_CMD_OFFSET,RETRY_DEFERRED_OPEN_CMD);
+       memcpy(de_msg+DEFERRED_OPEN_PID_OFFSET,(char *)&pid,sizeof(pid));
+       memcpy(de_msg+DEFERRED_OPEN_DEV_OFFSET,(char *)&entry->dev,sizeof(entry->dev));
+       memcpy(de_msg+DEFERRED_OPEN_INODE_OFFSET,(char *)&entry->inode,sizeof(entry->inode));
+       memcpy(de_msg+DEFERRED_OPEN_MID_OFFSET,(char *)&entry->mid,sizeof(entry->mid));
+
+       /* Set the address and port. */
+       memset((char *)&addr_out,'\0',sizeof(addr_out));
+       addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+       addr_out.sin_port = htons( entry->port );
+       addr_out.sin_family = AF_INET;
+   
+       if( DEBUGLVL( 3 ) ) {
+               dbgtext( "send_deferred_open_retry_message: sending a message to ");
+               dbgtext( "pid %d on port %d ", (int)entry->pid, entry->port );
+               dbgtext( "for dev = %x, inode = %.0f, mid = %u\n",
+                       (unsigned int)entry->dev, (double)entry->inode, (unsigned int)entry->mid );
+       }
+
+       if(sys_sendto(oplock_sock,de_msg,DEFERRED_OPEN_MSG_LEN,0,
+                       (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) {
+               if( DEBUGLVL( 0 ) ) {
+                       dbgtext( "send_deferred_open_retry_message: failed sending a message to ");
+                       dbgtext( "pid %d on port %d ", (int)entry->pid, entry->port );
+                       dbgtext( "for dev = %x, inode = %.0f, mid = %u\n",
+                               (unsigned int)entry->dev, (double)entry->inode, (unsigned int)entry->mid );
+                       dbgtext( "Error was %s\n", strerror(errno) );
+               }
+               return False;
+       }
+       return True;
+}
+
+/****************************************************************************
+ Setup oplocks for this process.
 ****************************************************************************/
 
 BOOL init_oplocks(void)
index 584164e93094d53987e716fed3c3c5d211972f73..2d9591e6baa7b3dbfc5a64460934d2b943e73650 100644 (file)
@@ -880,7 +880,7 @@ static mode_t map_nt_perms( SEC_ACCESS sec_access, int type)
  Unpack a SEC_DESC into a UNIX owner and group.
 ****************************************************************************/
 
-static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd)
+static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd)
 {
        DOM_SID owner_sid;
        DOM_SID grp_sid;
@@ -910,15 +910,17 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp,
        if (security_info_sent & OWNER_SECURITY_INFORMATION) {
                sid_copy(&owner_sid, psd->owner_sid);
                if (!NT_STATUS_IS_OK(sid_to_uid(&owner_sid, puser))) {
-#if ACL_FORCE_UNMAPPABLE
-                       /* this allows take ownership to work reasonably */
-                       extern struct current_user current_user;
-                       *puser = current_user.uid;
-#else
-                       DEBUG(3,("unpack_nt_owners: unable to validate owner sid for %s\n",
-                                sid_string_static(&owner_sid)));
-                       return False;
-#endif
+                       if (lp_force_unknown_acl_user(snum)) {
+                               /* this allows take ownership to work
+                                * reasonably */
+                               extern struct current_user current_user;
+                               *puser = current_user.uid;
+                       } else {
+                               DEBUG(3,("unpack_nt_owners: unable to validate"
+                                        " owner sid for %s\n",
+                                        sid_string_static(&owner_sid)));
+                               return False;
+                       }
                }
        }
 
@@ -930,14 +932,16 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp,
        if (security_info_sent & GROUP_SECURITY_INFORMATION) {
                sid_copy(&grp_sid, psd->grp_sid);
                if (!NT_STATUS_IS_OK(sid_to_gid( &grp_sid, pgrp))) {
-#if ACL_FORCE_UNMAPPABLE
-                       /* this allows take group ownership to work reasonably */
-                       extern struct current_user current_user;
-                       *pgrp = current_user.gid;
-#else
-                       DEBUG(3,("unpack_nt_owners: unable to validate group sid.\n"));
-                       return False;
-#endif
+                       if (lp_force_unknown_acl_user(snum)) {
+                               /* this allows take group ownership to work
+                                * reasonably */
+                               extern struct current_user current_user;
+                               *pgrp = current_user.gid;
+                       } else {
+                               DEBUG(3,("unpack_nt_owners: unable to validate"
+                                        " group sid.\n"));
+                               return False;
+                       }
                }
        }
 
@@ -3005,7 +3009,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
         * Unpack the user/group/world id's.
         */
 
-       if (!unpack_nt_owners( &sbuf, &user, &grp, security_info_sent, psd))
+       if (!unpack_nt_owners( SNUM(conn), &sbuf, &user, &grp, security_info_sent, psd))
                return False;
 
        /*
index 12fd809b7849f95e23badc2255dab4c5c783b027..60ce1499e8dc1c3fa48decd153c5b3b22ae7ce3f 100644 (file)
@@ -61,55 +61,215 @@ uint16 get_current_mid(void)
  for processing.
 ****************************************************************************/
 
-typedef struct {
-       ubi_slNode msg_next;
-       char *msg_buf;
-       int msg_len;
-} pending_message_list;
+static struct pending_message_list *smb_oplock_queue;
+static struct pending_message_list *smb_sharing_violation_queue;
 
-static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0};
+enum q_type { OPLOCK_QUEUE, SHARE_VIOLATION_QUEUE };
+
+/****************************************************************************
+ Free up a message.
+****************************************************************************/
+
+static void free_queued_message(struct pending_message_list *msg)
+{
+       data_blob_free(&msg->buf);
+       data_blob_free(&msg->private_data);
+       SAFE_FREE(msg);
+}
 
 /****************************************************************************
  Function to push a message onto the tail of a linked list of smb messages ready
  for processing.
 ****************************************************************************/
 
-static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len)
+static BOOL push_queued_message(enum q_type qt, char *buf, int msg_len, struct timeval *ptv, char *private, size_t private_len)
 {
-       pending_message_list *msg = (pending_message_list *)
-                               malloc(sizeof(pending_message_list));
+       struct pending_message_list *tmp_msg;
+       struct pending_message_list *msg = (struct pending_message_list *)
+                               malloc(sizeof(struct pending_message_list));
 
        if(msg == NULL) {
                DEBUG(0,("push_message: malloc fail (1)\n"));
                return False;
        }
 
-       msg->msg_buf = (char *)malloc(msg_len);
-       if(msg->msg_buf == NULL) {
+       memset(msg,'\0',sizeof(*msg));
+
+       msg->buf = data_blob(buf, msg_len);
+       if(msg->buf.data == NULL) {
                DEBUG(0,("push_message: malloc fail (2)\n"));
                SAFE_FREE(msg);
                return False;
        }
 
-       memcpy(msg->msg_buf, buf, msg_len);
-       msg->msg_len = msg_len;
+       if (ptv) {
+               msg->msg_time = *ptv;
+       }
+
+       if (private) {
+               msg->private_data = data_blob(private, private_len);
+               if (msg->private_data.data == NULL) {
+                       DEBUG(0,("push_message: malloc fail (3)\n"));
+                       data_blob_free(&msg->buf);
+                       SAFE_FREE(msg);
+               }
+       }
 
-       ubi_slAddTail( list_head, msg);
+       if (qt == OPLOCK_QUEUE) {
+               DLIST_ADD_END(smb_oplock_queue, msg, tmp_msg);
+       } else {
+               DLIST_ADD_END(smb_sharing_violation_queue, msg, tmp_msg);
+       }
 
-       /* Push the MID of this packet on the signing queue. */
-       srv_defer_sign_response(SVAL(buf,smb_mid));
+       DEBUG(10,("push_message: pushed message length %u on queue %s\n",
+               (unsigned int)msg_len,
+               qt == OPLOCK_QUEUE ? "smb_oplock_queue" : "smb_sharing_violation_queue" ));
 
        return True;
 }
 
 /****************************************************************************
- Function to push a smb message onto a linked list of local smb messages ready
+ Function to push an oplock smb message onto a linked list of local smb messages ready
  for processing.
 ****************************************************************************/
 
 BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
 {
-       return push_message(&smb_oplock_queue, buf, msg_len);
+       BOOL ret = push_queued_message(OPLOCK_QUEUE, buf, msg_len, NULL, NULL, 0);
+       if (ret) {
+               /* Push the MID of this packet on the signing queue. */
+               srv_defer_sign_response(SVAL(buf,smb_mid));
+       }
+       return ret;
+}
+
+/****************************************************************************
+ Function to delete a sharing violation open message by mid.
+****************************************************************************/
+
+void remove_sharing_violation_open_smb_message(uint16 mid)
+{
+       struct pending_message_list *pml;
+
+       if (!lp_defer_sharing_violations()) {
+               return;
+       }
+
+       for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
+               if (mid == SVAL(pml->buf.data,smb_mid)) {
+                       DEBUG(10,("remove_sharing_violation_open_smb_message: deleting mid %u len %u\n",
+                               (unsigned int)mid, (unsigned int)pml->buf.length ));
+                       DLIST_REMOVE(smb_sharing_violation_queue, pml);
+                       free_queued_message(pml);
+                       return;
+               }
+       }
+}
+
+/****************************************************************************
+ Move a sharing violation open retry message to the front of the list and
+ schedule it for immediate processing.
+****************************************************************************/
+
+void schedule_sharing_violation_open_smb_message(uint16 mid)
+{
+       struct pending_message_list *pml;
+       int i = 0;
+
+       if (!lp_defer_sharing_violations()) {
+               return;
+       }
+
+       for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
+               uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
+               DEBUG(10,("schedule_sharing_violation_open_smb_message: [%d] msg_mid = %u\n", i++,
+                       (unsigned int)msg_mid ));
+               if (mid == msg_mid) {
+                       DEBUG(10,("schedule_sharing_violation_open_smb_message: scheduling mid %u\n",
+                               mid ));
+                       pml->msg_time.tv_sec = 0;
+                       pml->msg_time.tv_usec = 0;
+                       DLIST_PROMOTE(smb_sharing_violation_queue, pml);
+                       return;
+               }
+       }
+
+       DEBUG(10,("schedule_sharing_violation_open_smb_message: failed to find message mid %u\n",
+               mid ));
+}
+
+/****************************************************************************
+ Return true if this mid is on the deferred queue.
+****************************************************************************/
+
+BOOL open_was_deferred(uint16 mid)
+{
+       struct pending_message_list *pml;
+
+       if (!lp_defer_sharing_violations()) {
+               return False;
+       }
+
+       for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
+               if (SVAL(pml->buf.data,smb_mid) == mid) {
+                       return True;
+               }
+       }
+       return False;
+}
+
+/****************************************************************************
+ Return the message queued by this mid.
+****************************************************************************/
+
+struct pending_message_list *get_open_deferred_message(uint16 mid)
+{
+       struct pending_message_list *pml;
+
+       if (!lp_defer_sharing_violations()) {
+               return NULL;
+       }
+
+       for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
+               if (SVAL(pml->buf.data,smb_mid) == mid) {
+                       return pml;
+               }
+       }
+       return NULL;
+}
+
+/****************************************************************************
+ Function to push a sharing violation open smb message onto a linked list of local smb messages ready
+ for processing.
+****************************************************************************/
+
+BOOL push_sharing_violation_open_smb_message(struct timeval *ptv, char *private, size_t priv_len)
+{
+       uint16 mid = SVAL(InBuffer,smb_mid);
+       struct timeval tv;
+       SMB_BIG_INT tdif;
+
+       if (!lp_defer_sharing_violations()) {
+               return True;
+       }
+
+       tv = *ptv;
+       tdif = tv.tv_sec;
+       tdif *= 1000000;
+       tdif += tv.tv_usec;
+
+       /* Add on the timeout. */
+       tdif += SHARING_VIOLATION_USEC_WAIT;
+       
+       tv.tv_sec = tdif / 1000000;
+       tv.tv_usec = tdif % 1000000;
+       
+       DEBUG(10,("push_sharing_violation_open_smb_message: pushing message len %u mid %u\
+ timeout time [%u.%06u]\n", (unsigned int) smb_len(InBuffer)+4, (unsigned int)mid,
+               (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec));
+
+       return push_queued_message(SHARE_VIOLATION_QUEUE, InBuffer,
+                       smb_len(InBuffer)+4, &tv, private, priv_len);
 }
 
 /****************************************************************************
@@ -168,12 +328,17 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
        fd_set fds;
        int selrtn;
        struct timeval to;
+       struct timeval *pto;
        int maxfd;
 
        smb_read_error = 0;
 
  again:
 
+       to.tv_sec = timeout / 1000;
+       to.tv_usec = (timeout % 1000) * 1000;
+       pto = timeout > 0 ? &to : NULL;
+
        /*
         * Note that this call must be before processing any SMB
         * messages as we need to synchronously process any messages
@@ -185,18 +350,57 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
         * Check to see if we already have a message on the smb queue.
         * If so - copy and return it.
         */
-       if(ubi_slCount(&smb_oplock_queue) != 0) {
-               pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue);
-               memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len));
+       if(smb_oplock_queue != NULL) {
+               struct pending_message_list *msg = smb_oplock_queue;
+               memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length));
   
                /* Free the message we just copied. */
-               SAFE_FREE(msg->msg_buf);
-               SAFE_FREE(msg);
+               DLIST_REMOVE(smb_oplock_queue, msg);
+               free_queued_message(msg);
                
                DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
                return True;
        }
 
+       /*
+        * Check to see if we already have a message on the deferred open queue
+        * and it's time to schedule.
+        */
+       if(smb_sharing_violation_queue != NULL) {
+               BOOL pop_message = False;
+               struct pending_message_list *msg = smb_sharing_violation_queue;
+
+               if (msg->msg_time.tv_sec == 0 && msg->msg_time.tv_usec == 0) {
+                       pop_message = True;
+               } else {
+                       struct timeval tv;
+                       SMB_BIG_INT tdif;
+
+                       GetTimeOfDay(&tv);
+                       tdif = usec_time_diff(&msg->msg_time, &tv);
+                       if (tdif <= 0) {
+                               /* Timed out. Schedule...*/
+                               pop_message = True;
+                               DEBUG(10,("receive_message_or_smb: queued message timed out.\n"));
+                       } else {
+                               /* Make a more accurate select timeout. */
+                               to.tv_sec = tdif / 1000000;
+                               to.tv_usec = tdif % 1000000;
+                               pto = &to;
+                               DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n",
+                                       (unsigned int)pto->tv_sec, (unsigned int)pto->tv_usec ));
+                       }
+               }
+
+               if (pop_message) {
+                       memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length));
+  
+                       /* We leave this message on the queue so the open code can
+                          know this is a retry. */
+                       DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n"));
+                       return True;
+               }
+       }
 
        /*
         * Setup the select read fd set.
@@ -227,10 +431,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
        FD_SET(smbd_server_fd(),&fds);
        maxfd = setup_oplock_select_set(&fds);
 
-       to.tv_sec = timeout / 1000;
-       to.tv_usec = (timeout % 1000) * 1000;
-
-       selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,timeout>0?&to:NULL);
+       selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,pto);
 
        /* if we get EINTR then maybe we have received an oplock
           signal - treat this as select returning 1. This is ugly, but
@@ -755,7 +956,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
                        return(ERROR_DOS(ERRSRV,ERRaccess));        
 
                /* load service specific parameters */
-               if (conn && !set_current_service(conn,(flags & (AS_USER|DO_CHDIR)?True:False)))
+               if (conn && !set_current_service(conn,SVAL(inbuf,smb_flg),(flags & (AS_USER|DO_CHDIR)?True:False)))
                        return(ERROR_DOS(ERRSRV,ERRaccess));
 
                /* does this protocol need to be run as guest? */
index e439c1e571a76067aa0a9ea62b780aa5ec40ee07..3c4d4319f637c6ee3797f1f0def14b68d8f19f8f 100644 (file)
@@ -933,6 +933,176 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
 #include <devnm.h>
 #endif
 
+#if defined(__FreeBSD__)
+
+#include <rpc/rpc.h>
+#include <rpc/types.h>
+#include <rpcsvc/rquota.h>
+#include <rpc/nettype.h>
+#include <rpc/xdr.h>
+
+static int quotastat;
+
+static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
+{
+       if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
+               return(0);
+       if (!xdr_int(xdrsp, &args->gqa_uid))
+               return(0);
+       return (1);
+}
+
+static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
+{
+       if (!xdr_int(xdrsp, &quotastat)) {
+               DEBUG(6,("nfs_quotas: Status bad or zero\n"));
+               return 0;
+       }
+       if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
+               DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
+               return 0;
+       }
+       if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
+               DEBUG(6,("nfs_quotas: Active bad or zero\n"));
+               return 0;
+       }
+       if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
+               DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
+               return 0;
+       }
+       if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
+               DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
+               return 0;
+       }
+       if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
+               DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
+               return 0;
+       }
+       return (1);
+}
+
+/* Works on FreeBSD, too. :-) */
+static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
+{
+       uid_t uid = euser_id;
+       struct dqblk D;
+       char *mnttype = nfspath;
+       CLIENT *clnt;
+       struct getquota_rslt gqr;
+       struct getquota_args args;
+       char *cutstr, *pathname, *host, *testpath;
+       int len;
+       static struct timeval timeout = {2,0};
+       enum clnt_stat clnt_stat;
+       BOOL ret = True;
+
+       *bsize = *dfree = *dsize = (SMB_BIG_UINT)0;
+
+       len=strcspn(mnttype, ":");
+       pathname=strstr(mnttype, ":");
+       cutstr = (char *) malloc(len+1);
+       if (!cutstr)
+               return False;
+
+       memset(cutstr, '\0', len+1);
+       host = strncat(cutstr,mnttype, sizeof(char) * len );
+       DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
+       DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
+       testpath=strchr_m(mnttype, ':');
+       args.gqa_pathp = testpath+1;
+       args.gqa_uid = uid;
+
+       DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));
+
+       if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
+               ret = False;
+               goto out;
+       }
+
+       clnt->cl_auth = authunix_create_default();
+       DEBUG(9,("nfs_quotas: auth_success\n"));
+
+       clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, (const xdrproc_t) my_xdr_getquota_args, (caddr_t)&args, (const xdrproc_t) my_xdr_getquota_rslt, (caddr_t)&gqr, timeout);
+
+       if (clnt_stat != RPC_SUCCESS) {
+               DEBUG(9,("nfs_quotas: clnt_call fail\n"));
+               ret = False;
+               goto out;
+       }
+
+       /* 
+        * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
+        * no quota set, and 3 if no permission to get the quota.  If 0 or 3 return
+        * something sensible.
+        */   
+
+       switch ( quotastat ) {
+       case 0:
+               DEBUG(9,("nfs_quotas: Remote Quotas Failed!  Error \"%i\" \n", quotastat ));
+               ret = False;
+               goto out;
+
+       case 1:
+               DEBUG(9,("nfs_quotas: Good quota data\n"));
+               D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
+               D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
+               D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
+               break;
+
+       case 2:
+       case 3:
+               D.dqb_bsoftlimit = 1;
+               D.dqb_curblocks = 1;
+               DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat ));
+               break;
+
+       default:
+               DEBUG(9,("nfs_quotas: Remote Quotas Questionable!  Error \"%i\" \n", quotastat ));
+               break;
+       }
+
+       DEBUG(10,("nfs_quotas: Let`s look at D a bit closer... status \"%i\" bsize \"%i\" active? \"%i\" bhard \"%i\" bsoft \"%i\" curb \"%i\" \n",
+                       quotastat,
+                       gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
+                       gqr.getquota_rslt_u.gqr_rquota.rq_active,
+                       gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
+                       gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
+                       gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
+
+       if (D.dqb_bsoftlimit == 0)
+               D.dqb_bsoftlimit = D.dqb_bhardlimit;
+       if (D.dqb_bsoftlimit == 0)
+               return False;
+
+       *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
+       *dsize = D.dqb_bsoftlimit;
+
+       if (D.dqb_curblocks == D.dqb_curblocks == 1)
+               *bsize = DEV_BSIZE;
+
+       if (D.dqb_curblocks > D.dqb_bsoftlimit) {
+               *dfree = 0;
+               *dsize = D.dqb_curblocks;
+       } else
+               *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
+
+  out:
+
+       if (clnt) {
+               if (clnt->cl_auth)
+                       auth_destroy(clnt->cl_auth);
+               clnt_destroy(clnt);
+       }
+
+       DEBUG(5,("nfs_quotas: For path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
+
+       SAFE_FREE(cutstr);
+       DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
+       return ret;
+}
+
+#endif
+
 /****************************************************************************
 try to get the disk space from disk quotas - default version
 ****************************************************************************/
@@ -976,10 +1146,42 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
   {
     /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
     gid_t egrp_id;
+#if defined(__FreeBSD__)
+    SMB_DEV_T devno;
+    struct statfs *mnts;
+    SMB_STRUCT_STAT st;
+    int mntsize, i;
+    
+    if (sys_stat(path,&st) < 0)
+        return False;
+    devno = st.st_dev;
+
+    mntsize = getmntinfo(&mnts,MNT_NOWAIT);
+    if (mntsize <= 0)
+        return False;
+
+    for (i = 0; i < mntsize; i++) {
+        if (sys_stat(mnts[i].f_mntonname,&st) < 0)
+            return False;
+        if (st.st_dev == devno)
+            break;
+    }
+    if (i == mntsize)
+        return False;
+#endif
+    
     save_re_uid();
     set_effective_uid(0);
 
+#if defined(__FreeBSD__)
+    if (strcmp(mnts[i].f_fstypename,"nfs") == 0) {
+        BOOL retval;
+        retval = nfs_quotas(mnts[i].f_mntfromname,euser_id,bsize,dfree,dsize);
+        restore_re_uid();
+        return retval;
+    }
+#endif
+
     egrp_id = getegid();
     r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
 
index 560208ae157752022336d429e50467deefbd210d..71efb793af0edd1cf78d2e251023f14f4c96f441 100644 (file)
@@ -43,7 +43,7 @@ extern BOOL global_encrypted_passwords_negotiated;
  set.
 ****************************************************************************/
 
-NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
+NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_wcard_names)
 {
        char *d = destname;
        const char *s = srcname;
@@ -119,7 +119,21 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
                        s++;
                } else {
                        if (!(*s & 0x80)) {
-                               *d++ = *s++;
+                               if (allow_wcard_names) {
+                                       *d++ = *s++;
+                               } else {
+                                       switch (*s) {
+                                               case '*':
+                                               case '?':
+                                               case '<':
+                                               case '>':
+                                               case '"':
+                                                       return NT_STATUS_OBJECT_NAME_INVALID;
+                                               default:
+                                                       *d++ = *s++;
+                                                       break;
+                                       }
+                               }
                        } else {
                                switch(next_mb_char_size(s)) {
                                        case 4:
@@ -147,7 +161,7 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
  Pull a string and check the path - provide for error return.
 ****************************************************************************/
 
-size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
+size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL allow_wcard_names)
 {
        pstring tmppath;
        char *tmppath_ptr = tmppath;
@@ -161,7 +175,7 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len
        } else {
                ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
        }
-       *err = check_path_syntax(dest, tmppath);
+       *err = check_path_syntax(dest, tmppath, allow_wcard_names);
        return ret;
 }
 
@@ -516,7 +530,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
 
        START_PROFILE(SMBchkpth);
 
-       srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBchkpth);
                return ERROR_NT(status);
@@ -525,6 +539,10 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
 
        unix_convert(name,conn,0,&bad_path,&sbuf);
+       if (bad_path) {
+               END_PROFILE(SMBchkpth);
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+       }
 
        mode = SVAL(inbuf,smb_vwv0);
 
@@ -548,18 +566,11 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                         * the parent directory is valid but not the
                         * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
                         * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
-                        * if the path is invalid.
+                        * if the path is invalid. This is different from set_bad_path_error()
+                        * in the non-NT error case.
                         */
-                       if (bad_path) {
-                               END_PROFILE(SMBchkpth);
-                               return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
-                       } else {
-                               END_PROFILE(SMBchkpth);
-                               return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
-                       }
-               } else if (errno == ENOTDIR) {
                        END_PROFILE(SMBchkpth);
-                       return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
+                       return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
                }
 
                END_PROFILE(SMBchkpth);
@@ -594,7 +605,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        START_PROFILE(SMBgetatr);
 
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
+       p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBgetatr);
                return ERROR_NT(status);
@@ -613,6 +624,10 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                ok = True;
        } else {
                unix_convert(fname,conn,0,&bad_path,&sbuf);
+               if (bad_path) {
+                       END_PROFILE(SMBgetatr);
+                       return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+               }
                if (check_name(fname,conn)) {
                        if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
                                mode = dos_mode(conn,fname,&sbuf);
@@ -669,13 +684,17 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        START_PROFILE(SMBsetatr);
 
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
+       p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBsetatr);
                return ERROR_NT(status);
        }
 
        unix_convert(fname,conn,0,&bad_path,&sbuf);
+       if (bad_path) {
+               END_PROFILE(SMBsetatr);
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+       }
 
        mode = SVAL(inbuf,smb_vwv0);
        mtime = make_unix_date3(inbuf+smb_vwv1);
@@ -798,7 +817,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        maxentries = SVAL(inbuf,smb_vwv0); 
        dirtype = SVAL(inbuf,smb_vwv1);
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status);
+       p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
        if (!NT_STATUS_IS_OK(nt_status)) {
                END_PROFILE(SMBsearch);
                return ERROR_NT(nt_status);
@@ -976,7 +995,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
 
        outsize = set_message(outbuf,1,0,True);
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err);
+       p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
        if (!NT_STATUS_IS_OK(err)) {
                END_PROFILE(SMBfclose);
                return ERROR_NT(err);
@@ -1028,7 +1047,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
  
        share_mode = SVAL(inbuf,smb_vwv0);
 
-       srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBopen);
                return ERROR_NT(status);
@@ -1037,12 +1056,21 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
 
        unix_convert(fname,conn,0,&bad_path,&sbuf);
+       if (bad_path) {
+               END_PROFILE(SMBopen);
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+       }
     
        fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
                        (uint32)dos_attr, oplock_request,&rmode,NULL);
 
        if (!fsp) {
                END_PROFILE(SMBopen);
+               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+                       /* We have re-scheduled this call. */
+                       clear_cached_errors();
+                       return -1;
+               }
                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
        }
 
@@ -1117,7 +1145,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
        }
 
        /* XXXX we need to handle passed times, sattr and flags */
-       srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBopenX);
                return ERROR_NT(status);
@@ -1126,12 +1154,21 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
        RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
 
        unix_convert(fname,conn,0,&bad_path,&sbuf);
+       if (bad_path) {
+               END_PROFILE(SMBopenX);
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+       }
     
        fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
                        oplock_request, &rmode,&smb_action);
       
        if (!fsp) {
                END_PROFILE(SMBopenX);
+               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+                       /* We have re-scheduled this call. */
+                       clear_cached_errors();
+                       return -1;
+               }
                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
        }
 
@@ -1230,7 +1267,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        com = SVAL(inbuf,smb_com);
 
        createmode = SVAL(inbuf,smb_vwv0);
-       srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcreate);
                return ERROR_NT(status);
@@ -1239,6 +1276,10 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
 
        unix_convert(fname,conn,0,&bad_path,&sbuf);
+       if (bad_path) {
+               END_PROFILE(SMBcreate);
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+       }
 
        if (createmode & aVOLID)
                DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
@@ -1257,6 +1298,11 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
   
        if (!fsp) {
                END_PROFILE(SMBcreate);
+               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+                       /* We have re-scheduled this call. */
+                       clear_cached_errors();
+                       return -1;
+               }
                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
        }
  
@@ -1297,7 +1343,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        START_PROFILE(SMBctemp);
 
        createattr = SVAL(inbuf,smb_vwv0);
-       srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBctemp);
                return ERROR_NT(status);
@@ -1311,6 +1357,10 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
 
        unix_convert(fname,conn,0,&bad_path,&sbuf);
+       if (bad_path) {
+               END_PROFILE(SMBctemp);
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+       }
   
        tmpfd = smb_mkstemp(fname);
        if (tmpfd == -1) {
@@ -1332,6 +1382,11 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
 
        if (!fsp) {
                END_PROFILE(SMBctemp);
+               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+                       /* We have re-scheduled this call. */
+                       clear_cached_errors();
+                       return -1;
+               }
                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
        }
 
@@ -1373,15 +1428,20 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
  Check if a user is allowed to rename a file.
 ********************************************************************/
 
-static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
+static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype, SMB_STRUCT_STAT *pst)
 {
        int smb_action;
        int access_mode;
        files_struct *fsp;
+       uint16 fmode;
 
        if (!CAN_WRITE(conn))
                return NT_STATUS_MEDIA_WRITE_PROTECTED;
-       
+
+       fmode = dos_mode(conn,fname,pst);
+       if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
+               return NT_STATUS_NO_SUCH_FILE;
+
        if (S_ISDIR(pst->st_mode))
                return NT_STATUS_OK;
 
@@ -1561,7 +1621,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
                                /* Quick check for "." and ".." */
                                if (fname[0] == '.') {
                                        if (!fname[1] || (fname[1] == '.' && !fname[2])) {
-                                               if ((dirtype & aDIR)) {
+                                               if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
                                                        sys_direntry = True;
                                                } else {
                                                        continue;
@@ -1574,6 +1634,8 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
                                
                                if (sys_direntry) {
                                        error = NT_STATUS_OBJECT_NAME_INVALID;
+                                       DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
+                                               fname, mask));
                                        break;
                                }
 
@@ -1612,7 +1674,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        
        dirtype = SVAL(inbuf,smb_vwv0);
        
-       srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBunlink);
                return ERROR_NT(status);
@@ -1623,8 +1685,14 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        DEBUG(3,("reply_unlink : %s\n",name));
        
        status = unlink_internals(conn, dirtype, name);
-       if (!NT_STATUS_IS_OK(status))
+       if (!NT_STATUS_IS_OK(status)) {
+               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+                       /* We have re-scheduled this call. */
+                       clear_cached_errors();
+                       return -1;
+               }
                return ERROR_NT(status);
+       }
 
        /*
         * Win2k needs a changenotify request response before it will
@@ -1661,12 +1729,13 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st
 
 #if defined(WITH_SENDFILE)
        /*
-        * We can only use sendfile on a non-chained packet and on a file
-        * that is exclusively oplocked. reply_readbraw has already checked the length.
+        * We can only use sendfile on a non-chained packet 
+        * but we can use on a non-oplocked file. tridge proved this
+        * on a train in Germany :-). JRA.
+        * reply_readbraw has already checked the length.
         */
 
-       if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
-                       EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
+       if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
                DATA_BLOB header;
 
                _smb_setlen(outbuf,nread);
@@ -1999,12 +2068,13 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
 
 #if defined(WITH_SENDFILE)
        /*
-        * We can only use sendfile on a non-chained packet and on a file
-        * that is exclusively oplocked.
+        * We can only use sendfile on a non-chained packet 
+        * but we can use on a non-oplocked file. tridge proved this
+        * on a train in Germany :-). JRA.
         */
 
-       if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
-                       lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
+       if ((CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
+                       (lp_write_cache_size(SNUM(conn)) == 0) ) {
                SMB_STRUCT_STAT sbuf;
                DATA_BLOB header;
 
@@ -3138,15 +3208,16 @@ NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
                return NT_STATUS_OBJECT_NAME_INVALID;
        }
 
+       if (bad_path) {
+               return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+       }
+
        if (check_name(directory, conn))
                ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
        
        if (ret == -1) {
                if(errno == ENOENT) {
-                       if (bad_path)
-                               return NT_STATUS_OBJECT_PATH_NOT_FOUND;
-                       else
-                               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+                       return NT_STATUS_OBJECT_NAME_NOT_FOUND;
                }
                return map_nt_error_from_unix(errno);
        }
@@ -3165,7 +3236,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        NTSTATUS status;
        START_PROFILE(SMBmkdir);
  
-       srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmkdir);
                return ERROR_NT(status);
@@ -3335,7 +3406,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        NTSTATUS status;
        START_PROFILE(SMBrmdir);
 
-       srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBrmdir);
                return ERROR_NT(status);
@@ -3344,6 +3415,10 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
 
        unix_convert(directory,conn, NULL,&bad_path,&sbuf);
+       if (bad_path) {
+               END_PROFILE(SMBrmdir);
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+       }
   
        if (check_name(directory,conn)) {
                dptr_closepath(directory,SVAL(inbuf,smb_pid));
@@ -3475,7 +3550,7 @@ static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T
  Rename an open file - given an fsp.
 ****************************************************************************/
 
-NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
+NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
 {
        SMB_STRUCT_STAT sbuf;
        BOOL bad_path = False;
@@ -3556,7 +3631,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *
                return NT_STATUS_OBJECT_NAME_COLLISION;
        }
 
-       error = can_rename(newname,conn,&sbuf);
+       error = can_rename(newname,conn,attrs,&sbuf);
 
        if (dest_exists && !NT_STATUS_IS_OK(error)) {
                DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
@@ -3762,7 +3837,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
                        return NT_STATUS_OBJECT_PATH_NOT_FOUND;
                }
 
-               error = can_rename(directory,conn,&sbuf1);
+               error = can_rename(directory,conn,attrs,&sbuf1);
 
                if (!NT_STATUS_IS_OK(error)) {
                        DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
@@ -3853,7 +3928,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
                                        DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
                                        continue;
                                }
-                               error = can_rename(fname,conn,&sbuf1);
+                               error = can_rename(fname,conn,attrs,&sbuf1);
                                if (!NT_STATUS_IS_OK(error)) {
                                        DEBUG(6,("rename %s refused\n", fname));
                                        continue;
@@ -3924,13 +3999,13 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        START_PROFILE(SMBmv);
 
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
+       p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmv);
                return ERROR_NT(status);
        }
        p++;
-       p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
+       p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmv);
                return ERROR_NT(status);
@@ -3944,6 +4019,11 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        status = rename_internals(conn, name, newname, attrs, False);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmv);
+               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+                       /* We have re-scheduled this call. */
+                       clear_cached_errors();
+                       return -1;
+               }
                return ERROR_NT(status);
        }
 
@@ -3989,7 +4069,8 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
                return(False);
 
        fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
-                                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0,&Access,&action);
+                                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
+                                       &Access,&action);
 
        if (!fsp1)
                return(False);
@@ -4002,7 +4083,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
                ZERO_STRUCTP(&sbuf2);
 
        fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
-                       ofun,dosattrs,0,&Access,&action);
+                       ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
 
        if (!fsp2) {
                close_file(fsp1,False);
@@ -4070,12 +4151,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        *directory = *mask = 0;
 
        p = smb_buf(inbuf);
-       p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
+       p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcopy);
                return ERROR_NT(status);
        }
-       p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
+       p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcopy);
                return ERROR_NT(status);
@@ -4235,7 +4316,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return ERROR_DOS(ERRDOS,ERRnoaccess);
        }
 
-       srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(pathworks_setdir);
                return ERROR_NT(status);
index 343a835be8a51f2c55799f89158132bac8619438..c3e0da542e2a4b4bae2ac4cfe29df042b8a051ea 100644 (file)
@@ -494,18 +494,16 @@ BOOL reload_services(BOOL test)
 
        load_interfaces();
 
-       {
-               if (smbd_server_fd() != -1) {      
-                       set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
-                       set_socket_options(smbd_server_fd(), user_socket_options);
-               }
+       if (smbd_server_fd() != -1) {      
+               set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
+               set_socket_options(smbd_server_fd(), user_socket_options);
        }
 
        mangle_reset_cache();
        reset_stat_cache();
 
        /* this forces service parameters to be flushed */
-       set_current_service(NULL,True);
+       set_current_service(NULL,0,True);
 
        return(ret);
 }
index c74537c299e14c67a78863281095661338afc63a..3b499d5cc1d4b25479a0a809deb793682aaf1625 100644 (file)
@@ -28,10 +28,11 @@ extern userdom_struct current_user_info;
  Load parameters specific to a connection/service.
 ****************************************************************************/
 
-BOOL set_current_service(connection_struct *conn,BOOL do_chdir)
+BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir)
 {
        extern char magic_char;
        static connection_struct *last_conn;
+       static uint16 last_flags;
        int snum;
 
        if (!conn)  {
@@ -51,10 +52,24 @@ BOOL set_current_service(connection_struct *conn,BOOL do_chdir)
                return(False);
        }
 
-       if (conn == last_conn)
+       if ((conn == last_conn) && (last_flags == flags)) {
                return(True);
+       }
 
        last_conn = conn;
+       last_flags = flags;
+       
+       /* Obey the client case sensitivity requests - only for clients that support it. */
+       if (lp_casesensitive(snum) == Auto) {
+               /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
+               enum remote_arch_types ra_type = get_remote_arch();
+               if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
+                       /* Client can't support per-packet case sensitive pathnames. */
+                       conn->case_sensitive = False;
+               } else {
+                       conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
+               }
+       }
 
        magic_char = lp_magicchar(snum);
        return(True);
@@ -347,7 +362,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
        conn->dirptr = NULL;
 
        /* Case options for the share. */
-       conn->case_sensitive = lp_casesensitive(snum);
+       if (lp_casesensitive(snum) == Auto) {
+               /* We will be setting this per packet. Set to be case insensitive for now. */
+               conn->case_sensitive = False;
+       } else {
+               conn->case_sensitive = (BOOL)lp_casesensitive(snum);
+       }
+
        conn->case_preserve = lp_preservecase(snum);
        conn->short_case_preserve = lp_shortpreservecase(snum);
 
@@ -499,6 +520,20 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                return NULL;
        }
 
+       /*
+        * If widelinks are disallowed we need to canonicalise the
+        * connect path here to ensure we don't have any symlinks in
+        * the connectpath. We will be checking all paths on this
+        * connection are below this directory. We must do this after
+        * the VFS init as we depend on the realpath() pointer in the vfs table. JRA.
+        */
+       if (!lp_widelinks(snum)) {
+               pstring s;
+               pstrcpy(s,conn->connectpath);
+               canonicalize_path(conn, s);
+               string_set(&conn->connectpath,s);
+       }
+
 /* ROOT Activities: */ 
        /* check number of connections */
        if (!claim_connection(conn,
index 61118f13dd9b2018f3c666cc851aade88ea7745c..91ebaeb830bcf187fb205ce9c5e9cf7a749bedbb 100644 (file)
@@ -34,8 +34,8 @@ BOOL session_init(void)
        if (tdb)
                return True;
 
-       tdb = tdb_open_ex(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, 
-                      O_RDWR | O_CREAT, 0644, smbd_tdb_log);
+       tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, 
+                      O_RDWR | O_CREAT, 0644);
        if (!tdb) {
                DEBUG(1,("session_init: failed to open sessionid tdb\n"));
                return False;
index 8a56478929fe6ed78a3ed6a85815695e3187d89a..0122b662ebfabb7f0ed223b6919f879652ab5157 100644 (file)
@@ -152,7 +152,6 @@ static int reply_spnego_kerberos(connection_struct *conn,
        auth_serversupplied_info *server_info = NULL;
        DATA_BLOB session_key = data_blob(NULL, 0);
        uint8 tok_id[2];
-       BOOL foreign = False;
        DATA_BLOB nullblob = data_blob(NULL, 0);
        fstring real_username;
 
@@ -197,7 +196,6 @@ static int reply_spnego_kerberos(connection_struct *conn,
                        SAFE_FREE(client);
                        return ERROR_NT(NT_STATUS_LOGON_FAILURE);
                }
-               foreign = True;
        }
 
        /* this gives a fully qualified user name (ie. with full realm).
@@ -244,6 +242,8 @@ static int reply_spnego_kerberos(connection_struct *conn,
        
        /* lookup the passwd struct, create a new user if necessary */
 
+       map_username( user );
+
        pw = smb_getpwnam( user, real_username, True );
        
        if (!pw) {
index 738d12e020fd0ba323159100a2d84b7daa2fa9de..a7db9daf7d604f6ad5318bf98576cf7eeabf76f7 100644 (file)
@@ -607,7 +607,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
        if (IS_IPC(conn))
                return(ERROR_DOS(ERRSRV,ERRaccess));
 
-       srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
        if (!NT_STATUS_IS_OK(status)) {
                return ERROR_NT(status);
        }
@@ -618,6 +618,9 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
        /* XXXX we need to handle passed times, sattr and flags */
 
        unix_convert(fname,conn,0,&bad_path,&sbuf);
+       if (bad_path) {
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+       }
     
        if (!check_name(fname,conn)) {
                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
@@ -627,6 +630,11 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
                oplock_request, &rmode,&smb_action);
       
        if (!fsp) {
+               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+                       /* We have re-scheduled this call. */
+                       clear_cached_errors();
+                       return -1;
+               }
                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
        }
 
@@ -1371,7 +1379,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                        return(ERROR_DOS(ERRDOS,ERRunknownlevel));
        }
 
-       srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus);
+       srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
        if (!NT_STATUS_IS_OK(ntstatus)) {
                return ERROR_NT(ntstatus);
        }
@@ -1379,6 +1387,9 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
        RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
 
        unix_convert(directory,conn,0,&bad_path,&sbuf);
+       if (bad_path) {
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+       }
        if(!check_name(directory,conn)) {
                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
        }
@@ -1564,7 +1575,7 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu
 
        *mask = *directory = *resume_name = 0;
 
-       srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus);
+       srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
        if (!NT_STATUS_IS_OK(ntstatus)) {
                return ERROR_NT(ntstatus);
        }
@@ -2257,6 +2268,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
        if (!params)
                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
 
+       ZERO_STRUCT(sbuf);
+
        if (tran_call == TRANSACT2_QFILEINFO) {
                if (total_params < 4)
                        return(ERROR_DOS(ERRDOS,ERRinvalidparam));
@@ -2272,11 +2285,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
                         */
                                                
                        pstrcpy(fname, fsp->fsp_name);
-                       unix_convert(fname,conn,0,&bad_path,&sbuf);
-                       if (!check_name(fname,conn)) {
-                               DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
-                               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
-                       }
+                       /* We know this name is ok, it's already passed the checks. */
                        
                } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
                        /*
@@ -2284,12 +2293,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
                         * handle (returned from an NT SMB). NT5.0 seems
                         * to do this call. JRA.
                         */
+                       /* We know this name is ok, it's already passed the checks. */
                        pstrcpy(fname, fsp->fsp_name);
-                       unix_convert(fname,conn,0,&bad_path,&sbuf);
-                       if (!check_name(fname,conn)) {
-                               DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
-                               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
-                       }
                  
                        if (INFO_LEVEL_IS_UNIX(info_level)) {
                                /* Always do lstat for UNIX calls. */
@@ -2297,7 +2302,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
                                        DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
                                        return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
                                }
-                       } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
+                       } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
                                DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
                                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
                        }
@@ -2329,7 +2334,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
 
                DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
 
-               srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
+               srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
                if (!NT_STATUS_IS_OK(status)) {
                        return ERROR_NT(status);
                }
@@ -2337,6 +2342,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
                RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
 
                unix_convert(fname,conn,0,&bad_path,&sbuf);
+               if (bad_path) {
+                       return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+               }
                if (!check_name(fname,conn)) {
                        DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
                        return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
@@ -2871,7 +2879,6 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
        BOOL bad_path_oldname = False;
        BOOL bad_path_newname = False;
        SMB_STRUCT_STAT sbuf1, sbuf2;
-       BOOL rc, rcdest;
        pstring last_component_oldname;
        pstring last_component_newname;
        NTSTATUS status = NT_STATUS_OK;
@@ -2884,8 +2891,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
                return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
        }
 
-       rc = unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
-       if (!rc && bad_path_oldname) {
+       unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
+       if (bad_path_oldname) {
                return NT_STATUS_OBJECT_PATH_NOT_FOUND;
        }
 
@@ -2905,8 +2912,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       rcdest = unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
-       if (!rcdest && bad_path_newname) {
+       unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
+       if (bad_path_newname) {
                return NT_STATUS_OBJECT_PATH_NOT_FOUND;
        }
 
@@ -2974,6 +2981,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
        if (!params)
                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
 
+       ZERO_STRUCT(sbuf);
+
        if (tran_call == TRANSACT2_SETFILEINFO) {
                if (total_params < 4)
                        return(ERROR_DOS(ERRDOS,ERRinvalidparam));
@@ -2988,8 +2997,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
                         * to do this call. JRA.
                         */
                        pstrcpy(fname, fsp->fsp_name);
-                       unix_convert(fname,conn,0,&bad_path,&sbuf);
-                       if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
+                       if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
                                DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
                                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
                        }
@@ -3027,11 +3035,14 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
                        return(ERROR_DOS(ERRDOS,ERRinvalidparam));
 
                info_level = SVAL(params,0);    
-               srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
+               srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
                if (!NT_STATUS_IS_OK(status)) {
                        return ERROR_NT(status);
                }
                unix_convert(fname,conn,0,&bad_path,&sbuf);
+               if (bad_path) {
+                       return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+               }
 
                /*
                 * For CIFS UNIX extensions the target name may not exist.
@@ -3205,7 +3216,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
                                                                        SET_OPEN_MODE(DOS_OPEN_RDWR),
                                                                        (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
                                                                        FILE_ATTRIBUTE_NORMAL,
-                                                                       0, &access_mode, &action);
+                                                                       INTERNAL_OPEN_ONLY, &access_mode, &action);
  
                                        if (new_fsp == NULL)
                                                return(UNIXERROR(ERRDOS,ERRbadpath));
@@ -3374,14 +3385,15 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                                        return(ERROR_DOS(ERRDOS,ERRnoaccess));
 
                                if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
-                                               file_type != UNIX_TYPE_FIFO)
+                                               file_type != UNIX_TYPE_FIFO &&
+                                               file_type != UNIX_TYPE_SOCKET)
                                        return(ERROR_DOS(ERRDOS,ERRnoaccess));
 
                                DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
 0%o for file %s\n", (double)dev, unixmode, fname ));
 
                                /* Ok - do the mknod. */
-                               if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
+                               if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
                                        return(UNIXERROR(ERRDOS,ERRnoaccess));
 
                                inherit_access_acl(conn, fname, unixmode);
@@ -3482,7 +3494,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                        char *newname = fname;
 
                        /* Set a hard link. */
-                       srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
+                       srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
                        if (!NT_STATUS_IS_OK(status)) {
                                return ERROR_NT(status);
                        }
@@ -3515,7 +3527,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                        overwrite = (CVAL(pdata,0) ? True : False);
                        root_fid = IVAL(pdata,4);
                        len = IVAL(pdata,8);
-                       srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
+                       srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
                        if (!NT_STATUS_IS_OK(status)) {
                                return ERROR_NT(status);
                        }
@@ -3538,7 +3550,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                        if (fsp) {
                                DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
                                        fsp->fnum, fsp->fsp_name, base_name ));
-                               status = rename_internals_fsp(conn, fsp, base_name, overwrite);
+                               status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
                        } else {
                                DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
                                        fname, newname ));
@@ -3654,7 +3666,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                                                SET_OPEN_MODE(DOS_OPEN_RDWR),
                                                (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
                                                FILE_ATTRIBUTE_NORMAL,
-                                               0, &access_mode, &action);
+                                               INTERNAL_OPEN_ONLY, &access_mode, &action);
        
                        if (new_fsp == NULL)
                                return(UNIXERROR(ERRDOS,ERRbadpath));
@@ -3695,7 +3707,7 @@ static int call_trans2mkdir(connection_struct *conn,
        if (total_params < 4)
                return(ERROR_DOS(ERRDOS,ERRinvalidparam));
 
-       srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
        if (!NT_STATUS_IS_OK(status)) {
                return ERROR_NT(status);
        }
@@ -3703,6 +3715,9 @@ static int call_trans2mkdir(connection_struct *conn,
        DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
 
        unix_convert(directory,conn,0,&bad_path,&sbuf);
+       if (bad_path) {
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+       }
        if (check_name(directory,conn))
                ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
   
index e1864c74caaf6aa2f40d2c9f0131ef4f67b4b48a..de2f96450fc7660c03abd83b6907ecd35b6bf3d0 100644 (file)
@@ -125,6 +125,13 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
 
        readonly_share = is_share_read_only_for_user(conn, vuser);
 
+       if (!readonly_share &&
+           !share_access_check(conn, snum, vuser, FILE_WRITE_DATA)) {
+               /* smb.conf allows r/w, but the security descriptor denies
+                * write. Fall back to looking at readonly. */
+               readonly_share = True;
+       }
+
        if (!share_access_check(conn, snum, vuser, readonly_share ? FILE_READ_DATA : FILE_WRITE_DATA)) {
                return False;
        }
index a521d0113d469501d3fbe11c2efa763e35dbbbb7..b1735dfcc49c1e48e0d7fe3851db0b4bdccbee05 100644 (file)
@@ -514,10 +514,10 @@ static BOOL sys_utmp_fill(struct utmp *u,
  *     But note that we do the more precise ut_tv as the final assignment.
  */
 #if defined(HAVE_UT_UT_TIME)
-       gettimeofday(&timeval, NULL);
+       GetTimeOfDay(&timeval);
        u->ut_time = timeval.tv_sec;
 #elif defined(HAVE_UT_UT_TV)
-       gettimeofday(&timeval, NULL);
+       GetTimeOfDay(&timeval);
        u->ut_tv = timeval;
 #else
 #error "with-utmp must have UT_TIME or UT_TV"
index a415e0470e27a7e59fd987169fd6708efcfcefc9..13cfdac0f35de330ff651e7fe2aa99f34b5131c5 100644 (file)
@@ -784,6 +784,31 @@ char *vfs_GetWd(connection_struct *conn, char *path)
        return (path);
 }
 
+BOOL canonicalize_path(connection_struct *conn, pstring path)
+{
+#ifdef REALPATH_TAKES_NULL
+       char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL);
+       if (!resolved_name) {
+               return False;
+       }
+       pstrcpy(path, resolved_name);
+       SAFE_FREE(resolved_name);
+       return True;
+#else
+#ifdef PATH_MAX
+        char resolved_name_buf[PATH_MAX+1];
+#else
+        pstring resolved_name_buf;
+#endif
+       char *resolved_name = SMB_VFS_REALPATH(conn,path,resolved_name_buf);
+       if (!resolved_name) {
+               return False;
+       }
+       pstrcpy(path, resolved_name);
+       return True;
+#endif /* REALPATH_TAKES_NULL */
+}
+
 /*******************************************************************
  Reduce a file name, removing .. elements and checking that
  it is below dir in the heirachy. This uses realpath.
@@ -804,6 +829,7 @@ BOOL reduce_name(connection_struct *conn, pstring fname)
        char *resolved_name = NULL;
        size_t con_path_len = strlen(conn->connectpath);
        char *p = NULL;
+       int saved_errno = errno;
 
        DEBUG(3,("reduce_name [%s] [%s]\n", fname, conn->connectpath));
 
@@ -817,6 +843,7 @@ BOOL reduce_name(connection_struct *conn, pstring fname)
                switch (errno) {
                        case ENOTDIR:
                                DEBUG(3,("reduce_name: Component not a directory in getting realpath for %s\n", fname));
+                               errno = saved_errno;
                                return False;
                        case ENOENT:
                        {
@@ -841,6 +868,7 @@ BOOL reduce_name(connection_struct *conn, pstring fname)
 #endif
                                if (!resolved_name) {
                                        DEBUG(3,("reduce_name: couldn't get realpath for %s\n", fname));
+                                       errno = saved_errno;
                                        return False;
                                }
                                pstrcpy(tmp_fname, resolved_name);
@@ -851,6 +879,7 @@ BOOL reduce_name(connection_struct *conn, pstring fname)
                                resolved_name = strdup(tmp_fname);
                                if (!resolved_name) {
                                        DEBUG(0,("reduce_name: malloc fail for %s\n", tmp_fname));
+                                       errno = saved_errno;
                                        return False;
                                }
 #else
@@ -865,6 +894,7 @@ BOOL reduce_name(connection_struct *conn, pstring fname)
                        }
                        default:
                                DEBUG(1,("reduce_name: couldn't get realpath for %s\n", fname));
+                               errno = saved_errno;
                                return False;
                }
        }
@@ -875,13 +905,15 @@ BOOL reduce_name(connection_struct *conn, pstring fname)
                DEBUG(0,("reduce_name: realpath doesn't return absolute paths !\n"));
                if (free_resolved_name)
                        SAFE_FREE(resolved_name);
+               errno = saved_errno;
                return False;
        }
 
        if (strncmp(conn->connectpath, resolved_name, con_path_len) != 0) {
-               DEBUG(2, ("reduce_name: Bad access attemt: %s is a symlink outside the share path", fname));
+               DEBUG(2, ("reduce_name: Bad access attempt: %s is a symlink outside the share path", fname));
                if (free_resolved_name)
                        SAFE_FREE(resolved_name);
+               errno = EACCES;
                return False;
        }
 
@@ -900,11 +932,13 @@ BOOL reduce_name(connection_struct *conn, pstring fname)
                DEBUG(3,("reduce_name: denied: file path name %s is a symlink\n",fname));
                if (free_resolved_name)
                        SAFE_FREE(resolved_name);
+               errno = EACCES;
                return False;
        }
 
        DEBUG(3,("reduce_name: %s reduced to %s\n", fname, p));
        if (free_resolved_name)
                SAFE_FREE(resolved_name);
+       errno = saved_errno;
        return(True);
 }
index 59fbb079bd041aae081db0e4ac18ec391b8618a3..92bc33a661ec3a8a2049b7a68cb02f60e8eb67cf 100644 (file)
@@ -5,11 +5,14 @@
 CFLAGS = -DSTANDALONE -DTDB_DEBUG -g -DHAVE_MMAP=1
 CC = gcc
 
+ADMINPROGS = tdbdump tdbbackup
 PROGS = tdbtest tdbtool tdbtorture
-TDB_OBJ = tdb.o spinlock.o
+TDB_OBJ = tdb.o spinlock.o tdbback.o
 
 default: $(PROGS)
 
+admintools: $(ADMINPROGS)
+
 tdbtest: tdbtest.o $(TDB_OBJ)
        $(CC) $(CFLAGS) -o tdbtest tdbtest.o $(TDB_OBJ) -lgdbm
 
index 161aa2cd73b1fcb9252c8944a0f13c6f62380fce..e3960d34061818ec996d312f9d63e742bb5ceba2 100644 (file)
@@ -45,12 +45,12 @@ static struct timeval tp1,tp2;
 
 void start_timer(void)
 {
-       gettimeofday(&tp1,NULL);
+       GetTimeOfDay(&tp1);
 }
 
 double end_timer(void)
 {
-       gettimeofday(&tp2,NULL);
+       GetTimeOfDay(&tp2);
        return((tp2.tv_sec - tp1.tv_sec) + 
               (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
 }
index 88fe34864935e7dfa2f5d59830e35a9f80c6c564..48556aa25705de025777ecd6d2d28e269c6c552d 100644 (file)
@@ -466,7 +466,7 @@ BOOL reload_services(BOOL test)
        reset_stat_cache();
 
        /* this forces service parameters to be flushed */
-       set_current_service(NULL,True);
+       set_current_service(NULL,0,True);
 
        return (ret);
 }
index 6eec71aedf34615aaa92a3a726884b7aa260f66d..b25303a97e069fb7d8155f47bb4a875412c077bb 100644 (file)
@@ -55,6 +55,8 @@ int net_ads_usage(int argc, const char **argv)
 "\n\tperform a raw LDAP search and dump the results\n"
 "\nnet ads dn"\
 "\n\tperform a raw LDAP search and dump attributes of a particular DN\n"
+"\nnet ads keytab"\
+"\n\tcreates and updates the kerberos system keytab file\n"
                );
        return -1;
 }
@@ -109,8 +111,8 @@ static int net_ads_info(int argc, const char **argv)
        d_printf("LDAP port: %d\n", ads->ldap_port);
        d_printf("Server time: %s\n", http_timestring(ads->config.current_time));
 
-       d_printf("KDC server: %s\n", ads->auth.kdc_server );
-       d_printf("Server time offset: %d\n", ads->auth.time_offset );
+       d_printf("KDC server: %s\n", ads->auth.kdc_server );
+       d_printf("Server time offset: %d\n", ads->auth.time_offset );
 
        return 0;
 }
@@ -214,6 +216,7 @@ static int net_ads_workgroup(int argc, const char **argv)
        if (!(ads = ads_startup())) return -1;
 
        if (!(ctx = talloc_init("net_ads_workgroup"))) {
+               ads_destroy(&ads);
                return -1;
        }
 
@@ -221,13 +224,14 @@ static int net_ads_workgroup(int argc, const char **argv)
                d_printf("Failed to find workgroup for realm '%s'\n", 
                         ads->config.realm);
                talloc_destroy(ctx);
+               ads_destroy(&ads);
                return -1;
        }
 
        d_printf("Workgroup: %s\n", workgroup);
 
        talloc_destroy(ctx);
-
+       ads_destroy(&ads);
        return 0;
 }
 
@@ -274,7 +278,9 @@ static int ads_user_add(int argc, const char **argv)
 
        if (argc < 1) return net_ads_user_usage(argc, argv);
        
-       if (!(ads = ads_startup())) return -1;
+       if (!(ads = ads_startup())) {
+               return -1;
+       }
 
        status = ads_find_user_acct(ads, &res, argv[0]);
 
@@ -342,13 +348,18 @@ static int ads_user_info(int argc, const char **argv)
        char **grouplist;
        char *escaped_user = escape_ldap_string_alloc(argv[0]);
 
-       if (argc < 1) return net_ads_user_usage(argc, argv);
+       if (argc < 1) {
+               return net_ads_user_usage(argc, argv);
+       }
        
-       if (!(ads = ads_startup())) return -1;
+       if (!(ads = ads_startup())) {
+               return -1;
+       }
 
        if (!escaped_user) {
                d_printf("ads_user_info: failed to escape user %s\n", argv[0]);
-               return -1;
+               ads_destroy(&ads);
+               return -1;
        }
 
        asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user);
@@ -357,6 +368,7 @@ static int ads_user_info(int argc, const char **argv)
 
        if (!ADS_ERR_OK(rc)) {
                d_printf("ads_search: %s\n", ads_errstr(rc));
+               ads_destroy(&ads);
                return -1;
        }
        
@@ -374,7 +386,6 @@ static int ads_user_info(int argc, const char **argv)
        }
        
        ads_msgfree(ads, res);
-
        ads_destroy(&ads);
        return 0;
 }
@@ -386,13 +397,18 @@ static int ads_user_delete(int argc, const char **argv)
        void *res;
        char *userdn;
 
-       if (argc < 1) return net_ads_user_usage(argc, argv);
+       if (argc < 1) {
+               return net_ads_user_usage(argc, argv);
+       }
        
-       if (!(ads = ads_startup())) return -1;
+       if (!(ads = ads_startup())) {
+               return -1;
+       }
 
        rc = ads_find_user_acct(ads, &res, argv[0]);
        if (!ADS_ERR_OK(rc)) {
                DEBUG(0, ("User %s does not exist\n", argv[0]));
+               ads_destroy(&ads);
                return -1;
        }
        userdn = ads_get_dn(ads, res);
@@ -401,10 +417,12 @@ static int ads_user_delete(int argc, const char **argv)
        ads_memfree(ads, userdn);
        if (!ADS_ERR_OK(rc)) {
                d_printf("User %s deleted\n", argv[0]);
+               ads_destroy(&ads);
                return 0;
        }
        d_printf("Error deleting user %s: %s\n", argv[0], 
                 ads_errstr(rc));
+       ads_destroy(&ads);
        return -1;
 }
 
@@ -423,7 +441,9 @@ int net_ads_user(int argc, const char **argv)
        char *disp_fields[2] = {NULL, NULL};
        
        if (argc == 0) {
-               if (!(ads = ads_startup())) return -1;
+               if (!(ads = ads_startup())) {
+                       return -1;
+               }
 
                if (opt_long_list_entries)
                        d_printf("\nUser name             Comment"\
@@ -454,9 +474,13 @@ static int ads_group_add(int argc, const char **argv)
        void *res=NULL;
        int rc = -1;
 
-       if (argc < 1) return net_ads_group_usage(argc, argv);
+       if (argc < 1) {
+               return net_ads_group_usage(argc, argv);
+       }
        
-       if (!(ads = ads_startup())) return -1;
+       if (!(ads = ads_startup())) {
+               return -1;
+       }
 
        status = ads_find_user_acct(ads, &res, argv[0]);
 
@@ -495,13 +519,18 @@ static int ads_group_delete(int argc, const char **argv)
        void *res;
        char *groupdn;
 
-       if (argc < 1) return net_ads_group_usage(argc, argv);
+       if (argc < 1) {
+               return net_ads_group_usage(argc, argv);
+       }
        
-       if (!(ads = ads_startup())) return -1;
+       if (!(ads = ads_startup())) {
+               return -1;
+       }
 
        rc = ads_find_user_acct(ads, &res, argv[0]);
        if (!ADS_ERR_OK(rc)) {
                DEBUG(0, ("Group %s does not exist\n", argv[0]));
+               ads_destroy(&ads);
                return -1;
        }
        groupdn = ads_get_dn(ads, res);
@@ -510,10 +539,12 @@ static int ads_group_delete(int argc, const char **argv)
        ads_memfree(ads, groupdn);
        if (!ADS_ERR_OK(rc)) {
                d_printf("Group %s deleted\n", argv[0]);
+               ads_destroy(&ads);
                return 0;
        }
        d_printf("Error deleting group %s: %s\n", argv[0], 
                 ads_errstr(rc));
+       ads_destroy(&ads);
        return -1;
 }
 
@@ -531,7 +562,9 @@ int net_ads_group(int argc, const char **argv)
        char *disp_fields[2] = {NULL, NULL};
 
        if (argc == 0) {
-               if (!(ads = ads_startup())) return -1;
+               if (!(ads = ads_startup())) {
+                       return -1;
+               }
 
                if (opt_long_list_entries)
                        d_printf("\nGroup name            Comment"\
@@ -555,21 +588,25 @@ static int net_ads_status(int argc, const char **argv)
        ADS_STATUS rc;
        void *res;
 
-       if (!(ads = ads_startup())) return -1;
+       if (!(ads = ads_startup())) {
+               return -1;
+       }
 
        rc = ads_find_machine_acct(ads, &res, global_myname());
        if (!ADS_ERR_OK(rc)) {
                d_printf("ads_find_machine_acct: %s\n", ads_errstr(rc));
+               ads_destroy(&ads);
                return -1;
        }
 
        if (ads_count_replies(ads, res) == 0) {
                d_printf("No machine account for '%s' found\n", global_myname());
+               ads_destroy(&ads);
                return -1;
        }
 
        ads_dump(ads, res);
-
+       ads_destroy(&ads);
        return 0;
 }
 
@@ -593,13 +630,14 @@ static int net_ads_leave(int argc, const char **argv)
 
        rc = ads_leave_realm(ads, global_myname());
        if (!ADS_ERR_OK(rc)) {
-           d_printf("Failed to delete host '%s' from the '%s' realm.\n", 
-                    global_myname(), ads->config.realm);
-           return -1;
+               d_printf("Failed to delete host '%s' from the '%s' realm.\n", 
+                       global_myname(), ads->config.realm);
+               ads_destroy(&ads);
+               return -1;
        }
 
        d_printf("Removed '%s' from realm '%s'\n", global_myname(), ads->config.realm);
-
+       ads_destroy(&ads);
        return 0;
 }
 
@@ -659,7 +697,9 @@ int net_ads_join(int argc, const char **argv)
        const char *short_domain_name = NULL;
        TALLOC_CTX *ctx = NULL;
 
-       if (argc > 0) org_unit = argv[0];
+       if (argc > 0) {
+               org_unit = argv[0];
+       }
 
        if (!secrets_init()) {
                DEBUG(1,("Failed to initialise secrets database\n"));
@@ -669,15 +709,19 @@ int net_ads_join(int argc, const char **argv)
        tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
        password = strdup(tmp_password);
 
-       if (!(ads = ads_startup())) return -1;
+       if (!(ads = ads_startup())) {
+               return -1;
+       }
 
        if (!*lp_realm()) {
                d_printf("realm must be set in in smb.conf for ADS join to succeed.\n");
+               ads_destroy(&ads);
                return -1;
        }
 
        if (strcmp(ads->config.realm, lp_realm()) != 0) {
                d_printf("realm of remote server (%s) and realm in smb.conf (%s) DO NOT match.  Aborting join\n", ads->config.realm, lp_realm());
+               ads_destroy(&ads);
                return -1;
        }
 
@@ -691,35 +735,41 @@ int net_ads_join(int argc, const char **argv)
        if (rc.error_type == ENUM_ADS_ERROR_LDAP && rc.err.rc == LDAP_NO_SUCH_OBJECT) {
                d_printf("ads_join_realm: organizational unit %s does not exist (dn:%s)\n", 
                         org_unit, dn);
+               ads_destroy(&ads);
                return -1;
        }
        free(dn);
 
        if (!ADS_ERR_OK(rc)) {
                d_printf("ads_join_realm: %s\n", ads_errstr(rc));
+               ads_destroy(&ads);
                return -1;
        }       
 
        rc = ads_join_realm(ads, global_myname(), account_type, org_unit);
        if (!ADS_ERR_OK(rc)) {
                d_printf("ads_join_realm: %s\n", ads_errstr(rc));
+               ads_destroy(&ads);
                return -1;
        }
 
        rc = ads_domain_sid(ads, &dom_sid);
        if (!ADS_ERR_OK(rc)) {
                d_printf("ads_domain_sid: %s\n", ads_errstr(rc));       
-       return -1;
+               ads_destroy(&ads);
+               return -1;
        }
 
        if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
                d_printf("asprintf failed\n");
+               ads_destroy(&ads);
                return -1;
        }
 
        rc = ads_set_machine_password(ads, machine_account, password);
        if (!ADS_ERR_OK(rc)) {
                d_printf("ads_set_machine_password: %s\n", ads_errstr(rc));
+               ads_destroy(&ads);
                return -1;
        }
        
@@ -727,6 +777,7 @@ int net_ads_join(int argc, const char **argv)
        
        if ( !(ctx = talloc_init("net ads join")) ) {
                d_printf("talloc_init() failed!\n");
+               ads_destroy(&ads);
                return -1;
        }
        
@@ -738,9 +789,9 @@ int net_ads_join(int argc, const char **argv)
                        d_printf("Using the name [%s] from the server.\n", short_domain_name);
                        d_printf("You should set \"workgroup = %s\" in smb.conf.\n", short_domain_name);
                }
-       }
-       else
+       } else {
                short_domain_name = lp_workgroup();
+       }
        
        d_printf("Using short domain name -- %s\n", short_domain_name);
        
@@ -751,30 +802,41 @@ int net_ads_join(int argc, const char **argv)
            
        if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
                DEBUG(1,("Failed to save domain sid\n"));
+               ads_destroy(&ads);
                return -1;
        }
 
        if (!secrets_store_machine_password(password, lp_workgroup(), sec_channel_type)) {
                DEBUG(1,("Failed to save machine password\n"));
+               ads_destroy(&ads);
                return -1;
        }
 
        if (!secrets_store_domain_sid(short_domain_name, &dom_sid)) {
                DEBUG(1,("Failed to save domain sid\n"));
+               ads_destroy(&ads);
                return -1;
        }
 
        if (!secrets_store_machine_password(password, short_domain_name, sec_channel_type)) {
                DEBUG(1,("Failed to save machine password\n"));
+               ads_destroy(&ads);
                return -1;
        }
        
+       /* Now build the keytab, using the same ADS connection */
+       if (lp_use_kerberos_keytab() && ads_keytab_create_default(ads)) {
+               DEBUG(1,("Error creating host keytab!\n"));
+       }
+
        d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm);
 
        SAFE_FREE(password);
        SAFE_FREE(machine_account);
-       if ( ctx )
+       if ( ctx ) {
                talloc_destroy(ctx);
+       }
+       ads_destroy(&ads);
        return 0;
 }
 
@@ -801,26 +863,29 @@ static int net_ads_printer_search(int argc, const char **argv)
        ADS_STATUS rc;
        void *res = NULL;
 
-       if (!(ads = ads_startup())) 
+       if (!(ads = ads_startup())) {
                return -1;
+       }
 
        rc = ads_find_printers(ads, &res);
 
        if (!ADS_ERR_OK(rc)) {
                d_printf("ads_find_printer: %s\n", ads_errstr(rc));
                ads_msgfree(ads, res);
-               return -1;
+               ads_destroy(&ads);
+               return -1;
        }
 
        if (ads_count_replies(ads, res) == 0) {
                d_printf("No results found\n");
                ads_msgfree(ads, res);
+               ads_destroy(&ads);
                return -1;
        }
 
        ads_dump(ads, res);
        ads_msgfree(ads, res);
-
+       ads_destroy(&ads);
        return 0;
 }
 
@@ -831,34 +896,41 @@ static int net_ads_printer_info(int argc, const char **argv)
        const char *servername, *printername;
        void *res = NULL;
 
-       if (!(ads = ads_startup())) return -1;
+       if (!(ads = ads_startup())) {
+               return -1;
+       }
 
-       if (argc > 0)
+       if (argc > 0) {
                printername = argv[0];
-       else
+       } else {
                printername = "*";
+       }
 
-       if (argc > 1)
+       if (argc > 1) {
                servername =  argv[1];
-       else
+       } else {
                servername = global_myname();
+       }
 
        rc = ads_find_printer_on_server(ads, &res, printername, servername);
 
        if (!ADS_ERR_OK(rc)) {
                d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
                ads_msgfree(ads, res);
+               ads_destroy(&ads);
                return -1;
        }
 
        if (ads_count_replies(ads, res) == 0) {
                d_printf("Printer '%s' not found\n", printername);
                ads_msgfree(ads, res);
+               ads_destroy(&ads);
                return -1;
        }
 
        ads_dump(ads, res);
        ads_msgfree(ads, res);
+       ads_destroy(&ads);
 
        return 0;
 }
@@ -881,17 +953,21 @@ static int net_ads_printer_publish(int argc, const char **argv)
        char *prt_dn, *srv_dn, **srv_cn;
        void *res = NULL;
 
-       if (!(ads = ads_startup())) return -1;
+       if (!(ads = ads_startup())) {
+               return -1;
+       }
 
-       if (argc < 1)
+       if (argc < 1) {
                return net_ads_printer_usage(argc, argv);
+       }
        
        printername = argv[0];
 
-       if (argc == 2)
+       if (argc == 2) {
                servername = argv[1];
-       else
+       } else {
                servername = global_myname();
+       }
                
        /* Get printer data from SPOOLSS */
 
@@ -908,6 +984,7 @@ static int net_ads_printer_publish(int argc, const char **argv)
        if (NT_STATUS_IS_ERR(nt_status)) {
                d_printf("Unable to open a connnection to %s to obtain data "
                         "for %s\n", servername, printername);
+               ads_destroy(&ads);
                return -1;
        }
 
@@ -918,6 +995,7 @@ static int net_ads_printer_publish(int argc, const char **argv)
        if (ads_count_replies(ads, res) == 0) {
                d_printf("Could not find machine account for server %s\n", 
                         servername);
+               ads_destroy(&ads);
                return -1;
        }
 
@@ -932,10 +1010,12 @@ static int net_ads_printer_publish(int argc, const char **argv)
         rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
         if (!ADS_ERR_OK(rc)) {
                 d_printf("ads_publish_printer: %s\n", ads_errstr(rc));
+               ads_destroy(&ads);
                 return -1;
         }
  
         d_printf("published printer\n");
+       ads_destroy(&ads);
  
        return 0;
 }
@@ -948,27 +1028,33 @@ static int net_ads_printer_remove(int argc, const char **argv)
        char *prt_dn;
        void *res = NULL;
 
-       if (!(ads = ads_startup())) return -1;
+       if (!(ads = ads_startup())) {
+               return -1;
+       }
 
-       if (argc < 1)
+       if (argc < 1) {
                return net_ads_printer_usage(argc, argv);
+       }
 
-       if (argc > 1)
+       if (argc > 1) {
                servername = argv[1];
-       else
+       } else {
                servername = global_myname();
+       }
 
        rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
 
        if (!ADS_ERR_OK(rc)) {
                d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
                ads_msgfree(ads, res);
+               ads_destroy(&ads);
                return -1;
        }
 
        if (ads_count_replies(ads, res) == 0) {
                d_printf("Printer '%s' not found\n", argv[1]);
                ads_msgfree(ads, res);
+               ads_destroy(&ads);
                return -1;
        }
 
@@ -979,9 +1065,11 @@ static int net_ads_printer_remove(int argc, const char **argv)
 
        if (!ADS_ERR_OK(rc)) {
                d_printf("ads_del_dn: %s\n", ads_errstr(rc));
+               ads_destroy(&ads);
                return -1;
        }
 
+       ads_destroy(&ads);
        return 0;
 }
 
@@ -1001,116 +1089,123 @@ static int net_ads_printer(int argc, const char **argv)
 
 static int net_ads_password(int argc, const char **argv)
 {
-    ADS_STRUCT *ads;
-    const char *auth_principal = opt_user_name;
-    const char *auth_password = opt_password;
-    char *realm = NULL;
-    char *new_password = NULL;
-    char *c, *prompt;
-    const char *user;
-    ADS_STATUS ret;
-
-    if (opt_user_name == NULL || opt_password == NULL) {
-           d_printf("You must supply an administrator username/password\n");
-           return -1;
-    }
+       ADS_STRUCT *ads;
+       const char *auth_principal = opt_user_name;
+       const char *auth_password = opt_password;
+       char *realm = NULL;
+       char *new_password = NULL;
+       char *c, *prompt;
+       const char *user;
+       ADS_STATUS ret;
+
+       if (opt_user_name == NULL || opt_password == NULL) {
+               d_printf("You must supply an administrator username/password\n");
+               return -1;
+       }
 
+       if (argc < 1) {
+               d_printf("ERROR: You must say which username to change password for\n");
+               return -1;
+       }
+
+       user = argv[0];
+       if (!strchr_m(user, '@')) {
+               asprintf(&c, "%s@%s", argv[0], lp_realm());
+               user = c;
+       }
+
+       use_in_memory_ccache();    
+       c = strchr(auth_principal, '@');
+       if (c) {
+               realm = ++c;
+       } else {
+               realm = lp_realm();
+       }
+
+       /* use the realm so we can eventually change passwords for users 
+       in realms other than default */
+       if (!(ads = ads_init(realm, NULL, NULL))) {
+               return -1;
+       }
+
+       /* we don't actually need a full connect, but it's the easy way to
+               fill in the KDC's addresss */
+       ads_connect(ads);
     
-    if (argc < 1) {
-           d_printf("ERROR: You must say which username to change password for\n");
-           return -1;
-    }
-
-    user = argv[0];
-    if (!strchr(user, '@')) {
-           asprintf(&c, "%s@%s", argv[0], lp_realm());
-           user = c;
-    }
-
-    use_in_memory_ccache();    
-    c = strchr(auth_principal, '@');
-    if (c) {
-           realm = ++c;
-    } else {
-           realm = lp_realm();
-    }
-
-    /* use the realm so we can eventually change passwords for users 
-    in realms other than default */
-    if (!(ads = ads_init(realm, NULL, NULL))) return -1;
-
-    /* we don't actually need a full connect, but it's the easy way to
-       fill in the KDC's addresss */
-    ads_connect(ads);
-    
-    if (!ads || !ads->config.realm) {
-           d_printf("Didn't find the kerberos server!\n");
-           return -1;
-    }
-
-    if (argv[1]) {
-          new_password = (char *)argv[1];
-    } else {
-          asprintf(&prompt, "Enter new password for %s:", user);
-          new_password = getpass(prompt);
-          free(prompt);
-    }
-
-    ret = kerberos_set_password(ads->auth.kdc_server, auth_principal, 
+       if (!ads || !ads->config.realm) {
+               d_printf("Didn't find the kerberos server!\n");
+               return -1;
+       }
+
+       if (argv[1]) {
+               new_password = (char *)argv[1];
+       } else {
+               asprintf(&prompt, "Enter new password for %s:", user);
+               new_password = getpass(prompt);
+               free(prompt);
+       }
+
+       ret = kerberos_set_password(ads->auth.kdc_server, auth_principal, 
                                auth_password, user, new_password, ads->auth.time_offset);
-    if (!ADS_ERR_OK(ret)) {
-       d_printf("Password change failed :-( ...\n");
-       ads_destroy(&ads);
-       return -1;
-    }
+       if (!ADS_ERR_OK(ret)) {
+               d_printf("Password change failed :-( ...\n");
+               ads_destroy(&ads);
+               return -1;
+       }
 
-    d_printf("Password change for %s completed.\n", user);
-    ads_destroy(&ads);
+       d_printf("Password change for %s completed.\n", user);
+       ads_destroy(&ads);
 
-    return 0;
+       return 0;
 }
 
-
 int net_ads_changetrustpw(int argc, const char **argv)
 {    
-    ADS_STRUCT *ads;
-    char *host_principal;
-    char *hostname;
-    ADS_STATUS ret;
+       ADS_STRUCT *ads;
+       char *host_principal;
+       fstring my_fqdn;
+       ADS_STATUS ret;
+
+       if (!secrets_init()) {
+               DEBUG(1,("Failed to initialise secrets database\n"));
+               return -1;
+       }
+
+       net_use_machine_password();
 
-    if (!secrets_init()) {
-           DEBUG(1,("Failed to initialise secrets database\n"));
-           return -1;
-    }
+       use_in_memory_ccache();
 
-    net_use_machine_password();
+       if (!(ads = ads_startup())) {
+               return -1;
+       }
 
-    use_in_memory_ccache();
+       name_to_fqdn(my_fqdn, global_myname());
+       strlower_m(my_fqdn);
+       asprintf(&host_principal, "%s@%s", my_fqdn, ads->config.realm);
+       d_printf("Changing password for principal: HOST/%s\n", host_principal);
 
-    if (!(ads = ads_startup())) {
-           return -1;
-    }
+       ret = ads_change_trust_account_password(ads, host_principal);
 
-    hostname = strdup(global_myname());
-    strlower_m(hostname);
-    asprintf(&host_principal, "%s@%s", hostname, ads->config.realm);
-    SAFE_FREE(hostname);
-    d_printf("Changing password for principal: HOST/%s\n", host_principal);
+       if (!ADS_ERR_OK(ret)) {
+               d_printf("Password change failed :-( ...\n");
+               ads_destroy(&ads);
+               SAFE_FREE(host_principal);
+               return -1;
+       }
     
-    ret = ads_change_trust_account_password(ads, host_principal);
+       d_printf("Password change for principal HOST/%s succeeded.\n", host_principal);
+
+       if (lp_use_kerberos_keytab()) {
+               d_printf("Attempting to update system keytab with new password.\n");
+               if (ads_keytab_create_default(ads)) {
+                       d_printf("Failed to update system keytab.\n");
+               }
+       }
 
-    if (!ADS_ERR_OK(ret)) {
-       d_printf("Password change failed :-( ...\n");
        ads_destroy(&ads);
        SAFE_FREE(host_principal);
-       return -1;
-    }
-    
-    d_printf("Password change for principal HOST/%s succeeded.\n", host_principal);
-    ads_destroy(&ads);
-    SAFE_FREE(host_principal);
 
-    return 0;
+       return 0;
 }
 
 /*
@@ -1157,6 +1252,7 @@ static int net_ads_search(int argc, const char **argv)
                               ldap_exp, attrs, &res);
        if (!ADS_ERR_OK(rc)) {
                d_printf("search failed: %s\n", ads_errstr(rc));
+               ads_destroy(&ads);
                return -1;
        }       
 
@@ -1216,6 +1312,7 @@ static int net_ads_dn(int argc, const char **argv)
                               "(objectclass=*)", attrs, &res);
        if (!ADS_ERR_OK(rc)) {
                d_printf("search failed: %s\n", ads_errstr(rc));
+               ads_destroy(&ads);
                return -1;
        }       
 
@@ -1230,6 +1327,86 @@ static int net_ads_dn(int argc, const char **argv)
        return 0;
 }
 
+static int net_ads_keytab_usage(int argc, const char **argv)
+{
+       d_printf(
+               "net ads keytab <COMMAND>\n"\
+"<COMMAND> can be either:\n"\
+"  CREATE    Creates a fresh keytab\n"\
+"  ADD       Adds new service principal\n"\
+"  FLUSH     Flushes out all keytab entries\n"\
+"  HELP      Prints this help message\n"\
+"The ADD command will take arguments, the other commands\n"\
+"will not take any arguments.   The arguments given to ADD\n"\
+"should be a list of principals to add.  For example, \n"\
+"   net ads keytab add srv1 srv2\n"\
+"will add principals for the services srv1 and srv2 to the\n"\
+"system's keytab.\n"\
+"\n"
+               );
+       return -1;
+}
+
+static int net_ads_keytab_flush(int argc, const char **argv)
+{
+       int ret;
+       ADS_STRUCT *ads;
+
+       if (!(ads = ads_startup())) {
+               return -1;
+       }
+       ret = ads_keytab_flush(ads);
+       ads_destroy(&ads);
+       return ret;
+}
+
+static int net_ads_keytab_add(int argc, const char **argv)
+{
+       int i;
+       int ret = 0;
+       ADS_STRUCT *ads;
+
+       d_printf("Processing principals to add...\n");
+       if (!(ads = ads_startup())) {
+               return -1;
+       }
+       for (i = 0; i < argc; i++) {
+               ret |= ads_keytab_add_entry(ads, argv[i]);
+       }
+       ads_destroy(&ads);
+       return ret;
+}
+
+static int net_ads_keytab_create(int argc, const char **argv)
+{
+       ADS_STRUCT *ads;
+       int ret;
+
+       if (!(ads = ads_startup())) {
+               return -1;
+       }
+       ret = ads_keytab_create_default(ads);
+       ads_destroy(&ads);
+       return ret;
+}
+
+int net_ads_keytab(int argc, const char **argv)
+{
+       struct functable func[] = {
+               {"CREATE", net_ads_keytab_create},
+               {"ADD", net_ads_keytab_add},
+               {"FLUSH", net_ads_keytab_flush},
+               {"HELP", net_ads_keytab_usage},
+               {NULL, NULL}
+       };
+
+       if (!lp_use_kerberos_keytab()) {
+               d_printf("\nWarning: \"use kerberos keytab\" must be set to \"true\" in order to \
+use keytab functions.\n");
+       }
+
+       return net_run_function(argc, argv, func, net_ads_keytab_usage);
+}
 
 int net_ads_help(int argc, const char **argv)
 {
@@ -1269,6 +1446,7 @@ int net_ads(int argc, const char **argv)
                {"DN", net_ads_dn},
                {"WORKGROUP", net_ads_workgroup},
                {"LOOKUP", net_ads_lookup},
+               {"KEYTAB", net_ads_keytab},
                {"HELP", net_ads_help},
                {NULL, NULL}
        };
@@ -1284,6 +1462,11 @@ static int net_ads_noads(void)
        return -1;
 }
 
+int net_ads_keytab(int argc, const char **argv)
+{
+       return net_ads_noads();
+}
+
 int net_ads_usage(int argc, const char **argv)
 {
        return net_ads_noads();
index 817ba912b0551f7966ef566a0ba84eebe7f9180a..e21f79df303a698be265f8b16fb6ea557d0dcc00 100644 (file)
@@ -1867,8 +1867,14 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name,
        do {
                if (!local) break;
 
+               /* The max_size field in cli_samr_enum_als_groups is more like
+                * an account_control field with indiviual bits what to
+                * retrieve. Set this to 0xffff as NT4 usrmgr.exe does to get
+                * everything. I'm too lazy (sorry) to get this through to
+                * rpc_parse/ etc.  Volker */
+
                result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol,
-                                                 &start_idx, max_entries,
+                                                 &start_idx, 0xffff,
                                                  &groups, &num_entries);
 
                if (!NT_STATUS_IS_OK(result) &&
@@ -2203,6 +2209,83 @@ static int rpc_group_members(int argc, const char **argv)
                               argc, argv);
 }
 
+static NTSTATUS 
+rpc_group_rename_internals(const DOM_SID *domain_sid,
+                           const char *domain_name, 
+                           struct cli_state *cli,
+                           TALLOC_CTX *mem_ctx, int argc, const char **argv)
+{
+       NTSTATUS result;
+       POLICY_HND connect_pol, domain_pol, group_pol;
+       uint32 num_rids, *rids, *rid_types;
+       GROUP_INFO_CTR ctr;
+
+       if (argc != 2) {
+               d_printf("Usage: 'net rpc group rename group newname'\n");
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       /* Get sam policy handle */
+       
+       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+                                 &connect_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               return result;
+       
+       /* Get domain policy handle */
+       
+       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+                                     MAXIMUM_ALLOWED_ACCESS,
+                                     domain_sid, &domain_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               return result;
+
+       result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000,
+                                      1, argv, &num_rids, &rids, &rid_types);
+
+       if (num_rids != 1) {
+               d_printf("Couldn't find group %s\n", argv[0]);
+               return result;
+       }
+
+       if (rid_types[0] != SID_NAME_DOM_GRP) {
+               d_printf("Can only rename domain groups\n");
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
+                                    MAXIMUM_ALLOWED_ACCESS,
+                                    rids[0], &group_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               return result;
+
+       ZERO_STRUCT(ctr);
+
+       ctr.switch_value1 = 2;
+       init_samr_group_info2(&ctr.group.info2, argv[1]);
+
+       result = cli_samr_set_groupinfo(cli, mem_ctx, &group_pol, &ctr);
+
+       if (!NT_STATUS_IS_OK(result))
+               return result;
+
+       return NT_STATUS_NO_SUCH_GROUP;
+}
+
+static int rpc_group_rename(int argc, const char **argv)
+{
+       if (argc != 2) {
+               return rpc_group_usage(argc, argv);
+       }
+
+       return run_rpc_command(NULL, PI_SAMR, 0,
+                              rpc_group_rename_internals,
+                              argc, argv);
+}
+
 /** 
  * 'net rpc group' entrypoint.
  * @param argc  Standard main() style argc
@@ -2219,6 +2302,7 @@ int net_rpc_group(int argc, const char **argv)
                {"delmem", rpc_group_delmem},
                {"list", rpc_group_list},
                {"members", rpc_group_members},
+               {"rename", rpc_group_rename},
                {NULL, NULL}
        };
        
index f2fb7dcaaf3000b92a10dd6f72d35c9bb6dfa0d4..39dcd9993d070979b07b7dce2d984a2b1eb31ff2 100644 (file)
@@ -369,6 +369,7 @@ NTSTATUS contact_winbind_auth_crap(const char *username,
                nt_status = NT_STATUS_UNSUCCESSFUL;
                if (error_string)
                        *error_string = smb_xstrdup("Reading winbind reply failed!");
+               free_response(&response);
                return nt_status;
        }
        
@@ -376,6 +377,7 @@ NTSTATUS contact_winbind_auth_crap(const char *username,
        if (!NT_STATUS_IS_OK(nt_status)) {
                if (error_string) 
                        *error_string = smb_xstrdup(response.data.auth.error_string);
+               free_response(&response);
                return nt_status;
        }
 
@@ -390,10 +392,12 @@ NTSTATUS contact_winbind_auth_crap(const char *username,
 
        if (flags & WBFLAG_PAM_UNIX_NAME) {
                if (pull_utf8_allocate(unix_name, (char *)response.extra_data) == -1) {
+                       free_response(&response);
                        return NT_STATUS_NO_MEMORY;
                }
        }
 
+       free_response(&response);
        return nt_status;
 }
                                   
@@ -810,32 +814,34 @@ static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode,
        pstring     reply_argument;
 
        if (strlen(buf) < 2) {
+               DEBUG(1, ("SPENGO query [%s] invalid", buf));
+               x_fprintf(x_stdout, "BH\n");
+               return;
+       }
 
-               if (ntlmssp_state != NULL) {
-                       DEBUG(1, ("Request for initial SPNEGO request where "
-                                 "we already have a state\n"));
-                       x_fprintf(x_stdout, "BH\n");
-                       return;
-               }
-
-               DEBUG(1, ("NTLMSSP query [%s] invalid", buf));
+       if (strncmp(buf, "YR", 2) == 0) {
+               if (ntlmssp_state)
+                       ntlmssp_end(&ntlmssp_state);
+       } else if (strncmp(buf, "KK", 2) == 0) {
+               
+       } else {
+               DEBUG(1, ("SPENGO query [%s] invalid", buf));
                x_fprintf(x_stdout, "BH\n");
                return;
        }
 
-       if ( (strlen(buf) == 2) && (strcmp(buf, "YR") == 0) ) {
+       if ( (strlen(buf) == 2)) {
 
-               /* Initial request, get the negTokenInit offering
+               /* no client data, get the negTokenInit offering
                    mechanisms */
 
                offer_gss_spnego_mechs();
                return;
        }
 
-       /* All subsequent requests are "KK" (Knock, Knock ;)) and have
-          a blob. This might be negTokenInit or negTokenTarg */
+       /* All subsequent requests have a blob. This might be negTokenInit or negTokenTarg */
 
-       if ( (strlen(buf) <= 3) || (strncmp(buf, "KK", 2) != 0) ) {
+       if (strlen(buf) <= 3) {
                DEBUG(1, ("GSS-SPNEGO query [%s] invalid\n", buf));
                x_fprintf(x_stdout, "BH\n");
                return;
@@ -1147,7 +1153,7 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
 {
        char *principal;
        DATA_BLOB tkt, to_server;
-       DATA_BLOB session_key_krb5;
+       DATA_BLOB session_key_krb5 = data_blob(NULL, 0);
        SPNEGO_DATA reply;
        char *reply_base64;
        int retval;
@@ -1192,14 +1198,14 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
                if ((retval = kerberos_kinit_password(user, opt_password, 
                                                      0, NULL))) {
                        DEBUG(10, ("Requesting TGT failed: %s\n", error_message(retval)));
-                       x_fprintf(x_stdout, "NA\n");
-                       return True;
+                       return False;
                }
 
                retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5);
 
                if (retval) {
                        DEBUG(10, ("Kinit suceeded, but getting a ticket failed: %s\n", error_message(retval)));
+                       return False;
                }
        }
 
@@ -1588,9 +1594,13 @@ static void manage_squid_request(enum stdio_helper_mode helper_mode, stdio_helpe
 
        /* this is not a typo - x_fgets doesn't work too well under squid */
        if (fgets(buf, sizeof(buf)-1, stdin) == NULL) {
-               DEBUG(1, ("fgets() failed! dying..... errno=%d (%s)\n", ferror(stdin),
-                         strerror(ferror(stdin))));
-               exit(1);    /* BIIG buffer */
+               if (ferror(stdin)) {
+                       DEBUG(1, ("fgets() failed! dying..... errno=%d (%s)\n", ferror(stdin),
+                                 strerror(ferror(stdin))));
+                       
+                       exit(1);    /* BIIG buffer */
+               }
+               exit(0);
        }
     
        c=memchr(buf,'\n',sizeof(buf)-1);
index 5a70d1688421c72402129b3f616f2fb0eff3c28d..cb82ad831eb6e713c0428edbeed28d5560ff7622 100644 (file)
@@ -624,11 +624,6 @@ static int cacl_set(struct cli_state *cli, char *filename,
                                                old->dacl->ace[k] = old->dacl->ace[k+1];
                                        }
                                        old->dacl->num_aces--;
-                                       if (old->dacl->num_aces == 0) {
-                                               SAFE_FREE(old->dacl->ace);
-                                               SAFE_FREE(old->dacl);
-                                               old->off_dacl = 0;
-                                       }
                                        found = True;
                                        break;
                                }