r23580: Merge bug fix for 4720 and Jeremy's winbindd_dual.c changes (still testing...
authorGerald Carter <jerry@samba.org>
Fri, 22 Jun 2007 04:09:38 +0000 (04:09 +0000)
committerGerald Carter <jerry@samba.org>
Fri, 22 Jun 2007 04:09:38 +0000 (04:09 +0000)
WHATSNEW.txt
source/client/client.c
source/nsswitch/winbindd_dual.c

index 5868036878807f2d50a092eadc397e64344ab5e6..30f17c156e653156211f006fe7fb91f5d7155549 100644 (file)
@@ -55,6 +55,11 @@ o   Guenther Deschner <gd@samba.org>
     * Add more netlogon GetDcName() client calls.
 
 
+o   SATOH Fumiyasu <fumiyas@osstech.co.jp>
+    * BUG 4720: Fix smbclient connections to share names containing 
+      multibyte characters.
+
+
 o   Steve Langasek <vorlon@debian.org>
     * Allow SIGTERM to cause nmbd to exit on awaiting an interface 
       to come up.
index f0ee12aa793bff7f4321e3041d772f0dcf9b959b..727e8db1f11e5ef5b6cd7440a31f0d0706834eb9 100644 (file)
@@ -3915,14 +3915,6 @@ static int do_message_op(void)
                /* if the service has not yet been specified lets see if it is available in the popt stack */
                if (!service_opt && poptPeekArg(pc)) {
                        pstrcpy(service, poptGetArg(pc));
-                       /* Convert any '/' characters in the service name to '\' characters */
-                       string_replace(service, '/','\\');
-
-                       if (count_chars(service,'\\') < 3) {
-                               d_printf("\n%s: Not enough '\\' characters in service\n",service);
-                               poptPrintUsage(pc, stderr, 0);
-                               exit(1);
-                       }
                        service_opt = True;
                }
 
@@ -4010,14 +4002,6 @@ static int do_message_op(void)
        /* if the service has not yet been specified lets see if it is available in the popt stack */
        if (!service_opt && poptPeekArg(pc)) {
                pstrcpy(service, poptGetArg(pc));
-               /* Convert any '/' characters in the service name to '\' characters */
-               string_replace(service, '/','\\');
-
-               if (count_chars(service,'\\') < 3) {
-                       d_printf("\n%s: Not enough '\\' characters in service\n",service);
-                       poptPrintUsage(pc, stderr, 0);
-                       exit(1);
-               }
                service_opt = True;
        }
 
@@ -4056,6 +4040,16 @@ static int do_message_op(void)
        }
        
        load_interfaces();
+
+       if (service_opt) {
+               /* Convert any '/' characters in the service name to '\' characters */
+               string_replace(service, '/','\\');
+               if (count_chars(service,'\\') < 3) {
+                       d_printf("\n%s: Not enough '\\' characters in service\n",service);
+                       poptPrintUsage(pc, stderr, 0);
+                       exit(1);
+               }
+       }
        
        if ( strlen(new_workgroup) != 0 )
                set_global_myworkgroup( new_workgroup );
index 169ea5e6882b2ca3202c1908acad55d59551f61b..ffbedfa9bf204655d21ee460cc56befdf46258b4 100644 (file)
@@ -97,6 +97,8 @@ struct winbindd_async_request {
        struct winbindd_response *response;
        void (*continuation)(void *private_data, BOOL success);
        struct timed_event *reply_timeout_event;
+       pid_t child_pid; /* pid of the child we're waiting on. Used to detect
+                           a restart of the child (child->pid != child_pid). */
        void *private_data;
 };
 
@@ -174,36 +176,51 @@ static void async_request_timeout_handler(struct event_context *ctx,
        struct winbindd_async_request *state =
                talloc_get_type_abort(private_data, struct winbindd_async_request);
 
-       /* Deal with the reply - set to error. */
+       DEBUG(0,("async_request_timeout_handler: child pid %u is not responding. "
+               "Closing connection to it.\n",
+               state->child_pid ));
 
+       /* Deal with the reply - set to error. */
        async_reply_recv(private_data, False);
+}
 
-       DEBUG(0,("async_request_timeout_handler: child pid %u is not responding. "
-               "Closing connection to it.\n",
-               state->child->pid ));
+/**************************************************************
+ Common function called on both async send and recv fail.
+ Cleans up the child and schedules the next request.
+**************************************************************/
 
-       /* Send kill signal to child. */
-       kill(state->child->pid, SIGTERM);
+static void async_request_fail(struct winbindd_async_request *state)
+{
+       DLIST_REMOVE(state->child->requests, state);
 
-       /* 
-        * Close the socket to the child.
-        */
+       TALLOC_FREE(state->reply_timeout_event);
+
+       SMB_ASSERT(state->child_pid != (pid_t)0);
+
+       /* If not already reaped, send kill signal to child. */
+       if (state->child->pid == state->child_pid) {
+               kill(state->child_pid, SIGTERM);
+
+               /* 
+                * Close the socket to the child.
+                */
+               winbind_child_died(state->child_pid);
+       }
 
-       winbind_child_died(state->child->pid);
+       state->response->length = sizeof(struct winbindd_response);
+       state->response->result = WINBINDD_ERROR;
+       state->continuation(state->private_data, False);
 }
 
 static void async_request_sent(void *private_data_data, BOOL success)
 {
-       uint32_t timeout = 30;
        struct winbindd_async_request *state =
                talloc_get_type_abort(private_data_data, struct winbindd_async_request);
 
        if (!success) {
-               DEBUG(5, ("Could not send async request\n"));
-
-               state->response->length = sizeof(struct winbindd_response);
-               state->response->result = WINBINDD_ERROR;
-               state->continuation(state->private_data, False);
+               DEBUG(5, ("Could not send async request to child pid %u\n",
+                       (unsigned int)state->child_pid ));
+               async_request_fail(state);
                return;
        }
 
@@ -215,25 +232,14 @@ static void async_request_sent(void *private_data_data, BOOL success)
                         async_reply_recv, state);
 
        /* 
-        * Normal timeouts are 30s, but auth requests may take a long
-        * time to timeout.
-        */
-
-       if (state->request->cmd == WINBINDD_PAM_AUTH ||
-                       state->request->cmd == WINBINDD_PAM_AUTH_CRAP ) {
-
-               timeout = 300;
-       }
-
-       /* 
-        * Set up a timeout of 30 seconds for the response.
+        * Set up a timeout of 300 seconds for the response.
         * If we don't get it close the child socket and
         * report failure.
         */
 
        state->reply_timeout_event = event_add_timed(winbind_event_context(),
                                                        NULL,
-                                                       timeval_current_ofs(timeout,0),
+                                                       timeval_current_ofs(300,0),
                                                        "async_request_timeout",
                                                        async_request_timeout_handler,
                                                        state);
@@ -248,27 +254,23 @@ static void async_reply_recv(void *private_data, BOOL success)
                talloc_get_type_abort(private_data, struct winbindd_async_request);
        struct winbindd_child *child = state->child;
 
-       if (state->reply_timeout_event) {
-               TALLOC_FREE(state->reply_timeout_event);
-       }
+       TALLOC_FREE(state->reply_timeout_event);
 
        state->response->length = sizeof(struct winbindd_response);
 
        if (!success) {
-               DEBUG(5, ("Could not receive async reply\n"));
+               DEBUG(5, ("Could not receive async reply from child pid %u\n",
+                       (unsigned int)state->child_pid ));
 
-               cache_cleanup_response(child->pid);
-               DLIST_REMOVE(child->requests, state);
-
-               state->response->result = WINBINDD_ERROR;
-               state->continuation(state->private_data, False);
+               cache_cleanup_response(state->child_pid);
+               async_request_fail(state);
                return;
        }
 
-       SMB_ASSERT(cache_retrieve_response(child->pid,
+       SMB_ASSERT(cache_retrieve_response(state->child_pid,
                                           state->response));
 
-       cache_cleanup_response(child->pid);
+       cache_cleanup_response(state->child_pid);
        
        DLIST_REMOVE(child->requests, state);
 
@@ -303,6 +305,9 @@ static void schedule_async_request(struct winbindd_child *child)
                return;
        }
 
+       /* Now we know who we're sending to - remember the pid. */
+       request->child_pid = child->pid;
+
        setup_async_write(&child->event, request->request,
                          sizeof(*request->request),
                          async_main_request_sent, request);
@@ -517,7 +522,7 @@ void winbind_child_died(pid_t pid)
        }
 
        if (child == NULL) {
-               DEBUG(0, ("Unknown child %d died!\n", pid));
+               DEBUG(5, ("Already reaped child %u died\n", (unsigned int)pid));
                return;
        }
 
@@ -713,9 +718,7 @@ static void account_lockout_policy_handler(struct event_context *ctx,
 
        DEBUG(10,("account_lockout_policy_handler called\n"));
 
-       if (child->lockout_policy_event) {
-               TALLOC_FREE(child->lockout_policy_event);
-       }
+       TALLOC_FREE(child->lockout_policy_event);
 
        methods = child->domain->methods;
 
@@ -962,9 +965,7 @@ static BOOL fork_domain_child(struct winbindd_child *child)
 
        for (domain = domain_list(); domain; domain = domain->next) {
                if (domain != child->domain) {
-                       if (domain->check_online_event) {
-                               TALLOC_FREE(domain->check_online_event);
-                       }
+                       TALLOC_FREE(domain->check_online_event);
                }
        }