proxy_auth.c revision 71829db25d6a0beb63066d912702ac1b7787dbe2
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose Stephen Gallagher <sgallagh@redhat.com>
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose Copyright (C) 2010 Red Hat
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose This program is free software; you can redistribute it and/or modify
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose it under the terms of the GNU General Public License as published by
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose the Free Software Foundation; either version 3 of the License, or
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose (at your option) any later version.
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose This program is distributed in the hope that it will be useful,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose but WITHOUT ANY WARRANTY; without even the implied warranty of
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose GNU General Public License for more details.
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose You should have received a copy of the GNU General Public License
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose along with this program. If not, see <http://www.gnu.org/licenses/>.
81165faf5d951aca69f410713730c26ff048ec44Sumit Bosestatic struct tevent_req *proxy_child_send(TALLOC_CTX *mem_ctx,
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bosestatic void proxy_child_done(struct tevent_req *child_req);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose pd = talloc_get_type(req->req_data, struct pam_data);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose ctx = talloc_get_type(req->be_ctx->bet_info[BET_AUTH].pvt_bet_data,
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce ctx = talloc_get_type(req->be_ctx->bet_info[BET_CHPASS].pvt_bet_data,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny ctx = talloc_get_type(req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny proxy_reply(req, DP_ERR_OK, EINVAL, "Unsupported PAM task");
418e6ccd116eced7ccc75aca999a4c37c67289baJakub Hrozek client_ctx = talloc(req, struct proxy_client_ctx);
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce /* Queue the request and spawn a child if there
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose * is an available slot.
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce /* Could not queue request
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose * Return an error
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose proxy_reply(req, DP_ERR_FATAL, EINVAL, "Could not queue request\n");
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose tevent_req_set_callback(child_req, proxy_child_done, client_ctx);
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bosestatic int proxy_child_destructor(TALLOC_CTX *ctx)
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose DEBUG(8, ("Removing proxy child id [%d]\n", child_ctx->id));
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose hret = hash_delete(child_ctx->auth_ctx->request_table, &key);
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek DEBUG(1, ("Hash error [%d][%s]\n", hret, hash_error_string(hret)));
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek /* Nothing we can do about this, so just continue */
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bosestatic struct tevent_req *proxy_child_init_send(TALLOC_CTX *mem_ctx,
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bosestatic void proxy_child_init_done(struct tevent_req *subreq);
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bosestatic struct tevent_req *proxy_child_send(TALLOC_CTX *mem_ctx,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov req = tevent_req_create(mem_ctx, &state, struct proxy_child_ctx);
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek DEBUG(1, ("Could not send PAM request to child\n"));
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek state->pd = talloc_get_type(be_req->req_data, struct pam_data);
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek /* Find an available key */
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* Handle overflow, zero is a reserved value
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose * Also handle the unlikely case where the next ID
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose * is still awaiting being run
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* We've looped through all possible integers! */
096a9678919fae460342469989b97fd47d812823Sumit Bose DEBUG(0, ("Serious error: queue is too long!\n"));
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose DEBUG(1, ("Could not add request to the queue\n"));
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (auth_ctx->running < auth_ctx->max_children) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* There's an available slot; start a child
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose * to handle the request
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose subreq = proxy_child_init_send(auth_ctx, state, auth_ctx);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose tevent_req_set_callback(subreq, proxy_child_init_done, req);
096a9678919fae460342469989b97fd47d812823Sumit Bose /* If there was no available slot, it will be queued
096a9678919fae460342469989b97fd47d812823Sumit Bose * until a slot is available
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose DEBUG(8, ("All available child slots are full, queuing request\n"));
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* If the init request has died, forcibly kill the child */
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bosestatic void pc_init_sig_handler(struct tevent_context *ev,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashovstatic void pc_init_timeout(struct tevent_context *ev,
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bosestatic struct tevent_req *proxy_child_init_send(TALLOC_CTX *mem_ctx,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov req = tevent_req_create(mem_ctx, &state, struct pc_init_ctx);
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose "%s/proxy_child -d %#.4x --debug-timestamps=%d "
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose "--debug-microseconds=%d%s --domain %s --id %d",
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose SSSD_LIBEXEC_PATH, debug_level, debug_timestamps,
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose debug_microseconds, (debug_to_file ? " --debug-to-files" : ""),
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose DEBUG(7, ("Starting proxy child with args [%s]\n", state->command));
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(1, ("fork failed [%d][%s].\n", ret, strerror(ret)));
096a9678919fae460342469989b97fd47d812823Sumit Bose DEBUG(0, ("Could not start proxy child [%s]: [%d][%s].\n",
096a9678919fae460342469989b97fd47d812823Sumit Bose else { /* parent */
096a9678919fae460342469989b97fd47d812823Sumit Bose /* Make sure to kill the child process if we abort */
096a9678919fae460342469989b97fd47d812823Sumit Bose talloc_set_destructor((TALLOC_CTX *)state, pc_init_destructor);
096a9678919fae460342469989b97fd47d812823Sumit Bose state->sige = tevent_add_signal(auth_ctx->be->ev, req,
096a9678919fae460342469989b97fd47d812823Sumit Bose /* Save the init request to the child context.
096a9678919fae460342469989b97fd47d812823Sumit Bose * This is technically a layering violation,
096a9678919fae460342469989b97fd47d812823Sumit Bose * but it's the only sane way to be able to
096a9678919fae460342469989b97fd47d812823Sumit Bose * identify which client is which when it
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose * connects to the backend in
096a9678919fae460342469989b97fd47d812823Sumit Bose * client_registration()
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* Wait six seconds for the child to connect
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose * This is because the connection handler will add
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose * its own five-second timeout, and we don't want to
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose * be faster here.
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose state->timeout = tevent_add_timer(auth_ctx->be->ev, req,
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* processing will continue once the connection is received
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek * in proxy_client_init()
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozekstatic void pc_init_sig_handler(struct tevent_context *ev,
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek DEBUG(0, ("SIGCHLD handler called with invalid child count\n"));
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose init_ctx = tevent_req_data(req, struct pc_init_ctx);
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(7, ("Waiting for child [%d].\n", init_ctx->pid));
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose ret = waitpid(init_ctx->pid, &child_status, WNOHANG);
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek DEBUG(1, ("waitpid failed [%d][%s].\n", ret, strerror(ret)));
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose } else if (ret == 0) {
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(1, ("waitpid did not find a child with changed status.\n"));
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(4, ("child [%d] exited with status [%d].\n", ret,
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(4, ("child [%d] was terminate by signal [%d].\n", ret,
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(1, ("child [%d] was stopped by signal [%d].\n", ret,
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(1, ("child [%d] was resumed by delivery of SIGCONT.\n",
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(1, ("Child is still running, no new child is started.\n"));
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bosestatic void pc_init_timeout(struct tevent_context *ev,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek DEBUG(2, ("Client timed out before Identification!\n"));
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekstatic errno_t proxy_child_init_recv(struct tevent_req *req,
09d7c105839bfc7447ea0f766413ed86675ca075Sumit Bose state = tevent_req_data(req, struct pc_init_ctx);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose /* Unset the destructor since we initialized successfully.
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce * We don't want to kill the child now that it's properly
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce talloc_set_destructor((TALLOC_CTX *)state, NULL);
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorcestatic void proxy_child_sig_handler(struct tevent_context *ev,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashovstatic struct tevent_req *proxy_pam_conv_send(TALLOC_CTX *mem_ctx,
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorcestatic void proxy_pam_conv_done(struct tevent_req *subreq);
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorcestatic void proxy_child_init_done(struct tevent_req *subreq) {
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce tevent_req_callback_data(subreq, struct tevent_req);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov tevent_req_data(req, struct proxy_child_ctx);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose ret = proxy_child_init_recv(subreq, &child_ctx->pid, &child_ctx->conn);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(6, ("Proxy child init failed [%d]\n", ret));
09d7c105839bfc7447ea0f766413ed86675ca075Sumit Bose /* An initialized child is available, awaiting the PAM command */
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose subreq = proxy_pam_conv_send(req, child_ctx->auth_ctx,
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek tevent_req_set_callback(subreq, proxy_pam_conv_done, req);
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek /* Add a signal handler for the child under the auth_ctx,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek * that way if the child exits after completion of the
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek * request, it will still be handled.
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek sig_ctx = talloc_zero(child_ctx->auth_ctx, struct proxy_child_sig_ctx);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek sige = tevent_add_signal(child_ctx->auth_ctx->be->ev,
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce /* Steal the signal context onto the signal event
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce * so that when the signal is freed, the context
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek * will go with it.
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekstatic void remove_sige(struct tevent_context *ev,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekstatic void run_proxy_child_queue(struct tevent_context *ev,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekstatic void proxy_child_sig_handler(struct tevent_context *ev,
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce DEBUG(0, ("SIGCHLD handler called with invalid child count\n"));
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce sig_ctx = talloc_get_type(pvt, struct proxy_child_sig_ctx);
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek DEBUG(7, ("Waiting for child [%d].\n", sig_ctx->pid));
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce ret = waitpid(sig_ctx->pid, &child_status, WNOHANG);
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce DEBUG(1, ("waitpid failed [%d][%s].\n", ret, strerror(ret)));
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce } else if (ret == 0) {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce DEBUG(1, ("waitpid did not found a child with changed status.\n"));
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce DEBUG(4, ("child [%d] exited with status [%d].\n", ret,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(4, ("child [%d] was terminated by signal [%d].\n", ret,
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce DEBUG(1, ("child [%d] was stopped by signal [%d].\n", ret,
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce DEBUG(1, ("child [%d] was resumed by delivery of SIGCONT.\n",
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce DEBUG(1, ("Child is still running, no new child is started.\n"));
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek tevent_schedule_immediate(imm, ev, run_proxy_child_queue,
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce /* schedule another immediate timer to delete the sigchld handler */
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce tevent_schedule_immediate(imm2, ev, remove_sige, sige);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorcestatic void remove_sige(struct tevent_context *ev,
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorcestatic void proxy_pam_conv_reply(DBusPendingCall *pending, void *ptr);
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorcestatic struct tevent_req *proxy_pam_conv_send(TALLOC_CTX *mem_ctx,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose req = tevent_req_create(mem_ctx, &state, struct proxy_conv_ctx);
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek DEBUG(1, ("dbus_message_new_method_call failed.\n"));
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny DEBUG(4, ("Sending request with the following data:\n"));
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce ret = sbus_conn_send(state->conn, msg, state->auth_ctx->timeout_ms,
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorcestatic void proxy_pam_conv_reply(DBusPendingCall *pending, void *ptr)
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose state = tevent_req_data(req, struct proxy_conv_ctx);
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce DEBUG(0, ("Severe error. A reply callback was called but no reply was"
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "received and no timeout occurred\n"));
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov ret = dp_unpack_pam_response(reply, state->pd, &dbus_error);
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce /* Kill the child */
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose /* Conversation is finished */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashovstatic errno_t proxy_pam_conv_recv(struct tevent_req *req)
81165faf5d951aca69f410713730c26ff048ec44Sumit Bosestatic void proxy_pam_conv_done(struct tevent_req *subreq)
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek req = tevent_req_callback_data(subreq, struct tevent_req);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(6, ("Proxy PAM conversation failed [%d]\n", ret));
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zelenystatic int proxy_child_recv(struct tevent_req *req,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny ctx = tevent_req_data(req, struct proxy_child_ctx);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bosestatic void proxy_child_done(struct tevent_req *req)
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose tevent_req_callback_data(req, struct proxy_client_ctx);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose /* Start the next auth in the queue, if any */
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose imm = tevent_create_immediate(client_ctx->be_req->be_ctx->ev);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose /* We'll still finish the current request, but we're
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose * likely to have problems if there are queued events
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov * if we've gotten into this state.
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose * Hopefully this is impossible, since freeing req
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose * above should guarantee that we have enough memory
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose * to create this immediate event.
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek /* Pam child failed */
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek proxy_reply(client_ctx->be_req, DP_ERR_FATAL, ret,
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek "PAM child failed");
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek /* Check if we need to save the cached credentials */
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek if ((pd->cmd == SSS_PAM_AUTHENTICATE || pd->cmd == SSS_PAM_CHAUTHTOK) &&
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek client_ctx->be_req->be_ctx->domain->cache_credentials) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose /* password caching failures are not fatal errors */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose talloc_set_destructor((TALLOC_CTX *)password, password_destructor);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose ret = sysdb_cache_password(client_ctx->be_req->be_ctx->sysdb,
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose /* password caching failures are not fatal errors */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose /* so we just log it any return */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose DEBUG(2, ("Failed to cache password (%d)[%s]!?\n",
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose proxy_reply(client_ctx->be_req, DP_ERR_OK, EOK, NULL);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bosestatic void run_proxy_child_queue(struct tevent_context *ev,
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose auth_ctx = talloc_get_type(pvt, struct proxy_auth_ctx);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose /* Launch next queued request */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose iter = new_hash_iter_context(auth_ctx->request_table);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose req = talloc_get_type(entry->value.ptr, struct tevent_req);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose state = tevent_req_data(req, struct proxy_child_ctx);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose /* Nothing pending on the queue */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose if (auth_ctx->running < auth_ctx->max_children) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose /* There's an available slot; start a child
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose * to handle the request
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose subreq = proxy_child_init_send(auth_ctx, state, auth_ctx);