Merge branch 'v3-3-test' of git://git.samba.org/samba into 3-3
[samba.git] / source / libsmb / libsmb_server.c
index 64eb1ea58418c32e47a7fd0dd0216c1402f4f3b0..6880f5c3426eed4156c9f10e67ebd3b180b2cd3f 100644 (file)
@@ -101,15 +101,29 @@ SMBC_call_auth_fn(TALLOC_CTX *ctx,
        fstring workgroup;
        fstring username;
        fstring password;
+        smbc_get_auth_data_with_context_fn auth_with_context_fn;
         
        strlcpy(workgroup, *pp_workgroup, sizeof(workgroup));
        strlcpy(username, *pp_username, sizeof(username));
        strlcpy(password, *pp_password, sizeof(password));
         
-        smbc_getFunctionAuthData(context)(server, share,
-                                          workgroup, sizeof(workgroup),
-                                          username, sizeof(username),
-                                          password, sizeof(password));
+        /* See if there's an authentication with context function provided */
+        auth_with_context_fn = smbc_getFunctionAuthDataWithContext(context);
+        if (auth_with_context_fn)
+        {
+            (* auth_with_context_fn)(context,
+                                     server, share,
+                                     workgroup, sizeof(workgroup),
+                                     username, sizeof(username),
+                                     password, sizeof(password));
+        }
+        else
+        {
+            smbc_getFunctionAuthData(context)(server, share,
+                                              workgroup, sizeof(workgroup),
+                                              username, sizeof(username),
+                                              password, sizeof(password));
+        }
         
        TALLOC_FREE(*pp_workgroup);
        TALLOC_FREE(*pp_username);
@@ -144,6 +158,10 @@ SMBC_find_server(TALLOC_CTX *ctx,
         SMBCSRV *srv;
         int auth_called = 0;
         
+        if (!pp_workgroup || !pp_username || !pp_password) {
+                return NULL;
+        }
+                
 check_server_cache:
         
        srv = smbc_getFunctionGetCachedServer(context)(context,
@@ -156,10 +174,6 @@ check_server_cache:
                SMBC_call_auth_fn(ctx, context, server, share,
                                   pp_workgroup, pp_username, pp_password);
                 
-               if (!pp_workgroup || !pp_username || !pp_password) {
-                       return NULL;
-               }
-                
                /*
                  * However, smbc_auth_fn may have picked up info relating to
                  * an existing connection, so try for an existing connection
@@ -224,6 +238,7 @@ SMBC_server(TALLOC_CTX *ctx,
             char **pp_password)
 {
        SMBCSRV *srv=NULL;
+       char *workgroup = NULL;
        struct cli_state *c;
        struct nmb_name called, calling;
        const char *server_n = server;
@@ -231,10 +246,12 @@ SMBC_server(TALLOC_CTX *ctx,
        int tried_reverse = 0;
         int port_try_first;
         int port_try_next;
+        int is_ipc = (share != NULL && strcmp(share, "IPC$") == 0);
+       uint32 fs_attrs = 0;
         const char *username_used;
        NTSTATUS status;
         
-       zero_addr(&ss);
+       zero_sockaddr(&ss);
        ZERO_STRUCT(c);
         
        if (server[0] == 0) {
@@ -296,6 +313,38 @@ SMBC_server(TALLOC_CTX *ctx,
                                 srv = NULL;
                         }
                         
+                        /* Determine if this share supports case sensitivity */
+                        if (is_ipc) {
+                                DEBUG(4,
+                                      ("IPC$ so ignore case sensitivity\n"));
+                        } else if (!cli_get_fs_attr_info(c, &fs_attrs)) {
+                                DEBUG(4, ("Could not retrieve "
+                                          "case sensitivity flag: %s.\n",
+                                          cli_errstr(c)));
+
+                                /*
+                                 * We can't determine the case sensitivity of
+                                 * the share. We have no choice but to use the
+                                 * user-specified case sensitivity setting.
+                                 */
+                                if (smbc_getOptionCaseSensitive(context)) {
+                                        cli_set_case_sensitive(c, True);
+                                } else {
+                                        cli_set_case_sensitive(c, False);
+                                }
+                        } else {
+                                DEBUG(4,
+                                      ("Case sensitive: %s\n",
+                                       (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
+                                        ? "True"
+                                        : "False")));
+                                cli_set_case_sensitive(
+                                        c,
+                                        (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
+                                         ? True
+                                         : False));
+                        }
+
                         /*
                          * Regenerate the dev value since it's based on both
                          * server and share
@@ -311,7 +360,7 @@ SMBC_server(TALLOC_CTX *ctx,
         if (srv) {
                 
                 /* ... then we're done here.  Give 'em what they came for. */
-                return srv;
+                goto done;
         }
         
         /* If we're not asked to connect when a connection doesn't exist... */
@@ -334,14 +383,14 @@ SMBC_server(TALLOC_CTX *ctx,
         
 again:
         
-       zero_addr(&ss);
+       zero_sockaddr(&ss);
         
        /* have to open a new connection */
        if ((c = cli_initialise()) == NULL) {
                errno = ENOMEM;
                return NULL;
        }
-        
+
         if (smbc_getOptionUseKerberos(context)) {
                c->use_kerberos = True;
        }
@@ -356,7 +405,7 @@ again:
          * Force use of port 139 for first try if share is $IPC, empty, or
          * null, so browse lists can work
          */
-        if (share == NULL || *share == '\0' || strcmp(share, "IPC$") == 0) {
+        if (share == NULL || *share == '\0' || is_ipc) {
                 port_try_first = 139;
                 port_try_next = 445;
         } else {
@@ -460,6 +509,34 @@ again:
         
        DEBUG(4,(" tconx ok\n"));
         
+        /* Determine if this share supports case sensitivity */
+       if (is_ipc) {
+                DEBUG(4, ("IPC$ so ignore case sensitivity\n"));
+        } else if (!cli_get_fs_attr_info(c, &fs_attrs)) {
+                DEBUG(4, ("Could not retrieve case sensitivity flag: %s.\n",
+                          cli_errstr(c)));
+
+                /*
+                 * We can't determine the case sensitivity of the share. We
+                 * have no choice but to use the user-specified case
+                 * sensitivity setting.
+                 */
+                if (smbc_getOptionCaseSensitive(context)) {
+                        cli_set_case_sensitive(c, True);
+                } else {
+                        cli_set_case_sensitive(c, False);
+                }
+       } else {
+                DEBUG(4, ("Case sensitive: %s\n",
+                          (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
+                           ? "True"
+                           : "False")));
+                cli_set_case_sensitive(c,
+                                       (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
+                                        ? True
+                                        : False));
+        }
+
        if (context->internal->smb_encryption_level) {
                /* Attempt UNIX smb encryption. */
                if (!NT_STATUS_IS_OK(cli_force_encryption(c,
@@ -522,6 +599,22 @@ again:
                  server, share, srv));
         
        DLIST_ADD(context->internal->servers, srv);
+done:
+       if (!pp_workgroup || !*pp_workgroup || !**pp_workgroup) {
+               workgroup = talloc_strdup(ctx, smbc_getWorkgroup(context));
+       } else {
+               workgroup = *pp_workgroup;
+       }
+       if(!workgroup) {
+               return NULL;
+       }
+       
+       /* set the credentials to make DFS work */
+       smbc_set_credentials_with_fallback(context,
+                                          workgroup,
+                                          *pp_username,
+                                          *pp_password);
+       
        return srv;
         
 failed:
@@ -581,7 +674,7 @@ SMBC_attr_server(TALLOC_CTX *ctx,
                         flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
                 }
                 
-                zero_addr(&ss);
+                zero_sockaddr(&ss);
                 nt_status = cli_full_connection(&ipc_cli,
                                                global_myname(), server,
                                                &ss, 0, "IPC$", "?????",
@@ -632,10 +725,9 @@ SMBC_attr_server(TALLOC_CTX *ctx,
                 ZERO_STRUCTP(ipc_srv);
                 ipc_srv->cli = ipc_cli;
                 
-                pipe_hnd = cli_rpc_pipe_open_noauth(ipc_srv->cli,
-                                                    PI_LSARPC,
-                                                    &nt_status);
-                if (!pipe_hnd) {
+                nt_status = cli_rpc_pipe_open_noauth(
+                       ipc_srv->cli, &ndr_table_lsarpc.syntax_id, &pipe_hnd);
+                if (!NT_STATUS_IS_OK(nt_status)) {
                         DEBUG(1, ("cli_nt_session_open fail!\n"));
                         errno = ENOTSUP;
                         cli_shutdown(ipc_srv->cli);