proxy_auth.c revision 71829db25d6a0beb63066d912702ac1b7787dbe2
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose/*
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose SSSD
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose proxy_auth.c
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose Authors:
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose Stephen Gallagher <sgallagh@redhat.com>
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose Copyright (C) 2010 Red Hat
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
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
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
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 Bose*/
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose#include "providers/proxy/proxy.h"
09d7c105839bfc7447ea0f766413ed86675ca075Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bosestruct proxy_client_ctx {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct be_req *be_req;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose struct proxy_auth_ctx *auth_ctx;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose};
204cfc89a076fd32bf34f2abb3f809304aaa88abSimo Sorce
81165faf5d951aca69f410713730c26ff048ec44Sumit Bosestatic struct tevent_req *proxy_child_send(TALLOC_CTX *mem_ctx,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct proxy_auth_ctx *ctx,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny struct be_req *be_req);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bosestatic void proxy_child_done(struct tevent_req *child_req);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zelenyvoid proxy_pam_handler(struct be_req *req)
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose{
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct pam_data *pd;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose struct proxy_auth_ctx *ctx;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose struct tevent_req *child_req = NULL;
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose struct proxy_client_ctx *client_ctx;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose pd = talloc_get_type(req->req_data, struct pam_data);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose switch (pd->cmd) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose case SSS_PAM_AUTHENTICATE:
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose ctx = talloc_get_type(req->be_ctx->bet_info[BET_AUTH].pvt_bet_data,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct proxy_auth_ctx);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose break;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose case SSS_PAM_CHAUTHTOK:
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce case SSS_PAM_CHAUTHTOK_PRELIM:
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce ctx = talloc_get_type(req->be_ctx->bet_info[BET_CHPASS].pvt_bet_data,
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce struct proxy_auth_ctx);
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose break;
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce case SSS_PAM_ACCT_MGMT:
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny ctx = talloc_get_type(req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny struct proxy_auth_ctx);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny break;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose case SSS_PAM_SETCRED:
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny case SSS_PAM_OPEN_SESSION:
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny case SSS_PAM_CLOSE_SESSION:
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny pd->pam_status = PAM_SUCCESS;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny proxy_reply(req, DP_ERR_OK, EOK, NULL);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny return;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny default:
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny DEBUG(1, ("Unsupported PAM task.\n"));
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose pd->pam_status = PAM_MODULE_UNKNOWN;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny proxy_reply(req, DP_ERR_OK, EINVAL, "Unsupported PAM task");
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny return;
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce }
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce
418e6ccd116eced7ccc75aca999a4c37c67289baJakub Hrozek client_ctx = talloc(req, struct proxy_client_ctx);
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce if (client_ctx == NULL) {
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce proxy_reply(req, DP_ERR_FATAL, ENOMEM, NULL);
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce return;
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose client_ctx->auth_ctx = ctx;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce client_ctx->be_req = req;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce
3b533d57a737e2de1b3e85b073b14d3bfb49dafcSimo Sorce /* Queue the request and spawn a child if there
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose * is an available slot.
5063dcc5ab685dce325b13b9c1e93cee2a673e60Sumit Bose */
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose child_req = proxy_child_send(req, ctx, req);
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce if (child_req == NULL) {
87ed72b47859e673b636c85f35b85f1546c7ed3dSimo Sorce /* Could not queue request
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose * Return an error
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose */
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose proxy_reply(req, DP_ERR_FATAL, EINVAL, "Could not queue request\n");
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose return;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose }
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose tevent_req_set_callback(child_req, proxy_child_done, client_ctx);
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose return;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose}
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bosestruct pc_init_ctx;
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bosestatic int proxy_child_destructor(TALLOC_CTX *ctx)
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose{
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose struct proxy_child_ctx *child_ctx =
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose talloc_get_type(ctx, struct proxy_child_ctx);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov hash_key_t key;
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose int hret;
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose DEBUG(8, ("Removing proxy child id [%d]\n", child_ctx->id));
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose key.type = HASH_KEY_ULONG;
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose key.ul = child_ctx->id;
b1829e54acbc8a010aca7f14b9ffa9625f8c102cSumit Bose hret = hash_delete(child_ctx->auth_ctx->request_table, &key);
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek if (!(hret == HASH_SUCCESS ||
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek hret == HASH_ERROR_KEY_NOT_FOUND)) {
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 */
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek }
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek return 0;
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek}
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bosestatic struct tevent_req *proxy_child_init_send(TALLOC_CTX *mem_ctx,
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bose struct proxy_child_ctx *child_ctx,
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bose struct proxy_auth_ctx *auth_ctx);
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bosestatic void proxy_child_init_done(struct tevent_req *subreq);
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bosestatic struct tevent_req *proxy_child_send(TALLOC_CTX *mem_ctx,
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bose struct proxy_auth_ctx *auth_ctx,
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bose struct be_req *be_req)
4fa184e2c60b377fd71e0115a618bd68dc73627dSumit Bose{
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek struct tevent_req *req;
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek struct tevent_req *subreq;
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek struct proxy_child_ctx *state;
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek int hret;
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek hash_key_t key;
c3243e3212f91b69ef9990e2cb4c9339bf2f7888Jakub Hrozek hash_value_t value;
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek uint32_t first;
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov req = tevent_req_create(mem_ctx, &state, struct proxy_child_ctx);
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek if (req == NULL) {
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek DEBUG(1, ("Could not send PAM request to child\n"));
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek return NULL;
06424c5ac5ffb871476208155762bb5b73e0b665Jakub Hrozek }
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek state->be_req = be_req;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov state->auth_ctx = auth_ctx;
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek state->pd = talloc_get_type(be_req->req_data, struct pam_data);
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek /* Find an available key */
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek key.type = HASH_KEY_ULONG;
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek key.ul = auth_ctx->next_id;
d2a8b08561e6700bdd4feb988becae4e8f5368ddJakub Hrozek
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose first = auth_ctx->next_id;
096a9678919fae460342469989b97fd47d812823Sumit Bose while (auth_ctx->next_id == 0 ||
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose hash_has_key(auth_ctx->request_table, &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 */
096a9678919fae460342469989b97fd47d812823Sumit Bose auth_ctx->next_id++;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose key.ul = auth_ctx->next_id;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose if (auth_ctx->next_id == first) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* We've looped through all possible integers! */
096a9678919fae460342469989b97fd47d812823Sumit Bose DEBUG(0, ("Serious error: queue is too long!\n"));
096a9678919fae460342469989b97fd47d812823Sumit Bose talloc_zfree(req);
096a9678919fae460342469989b97fd47d812823Sumit Bose return NULL;
096a9678919fae460342469989b97fd47d812823Sumit Bose }
096a9678919fae460342469989b97fd47d812823Sumit Bose }
096a9678919fae460342469989b97fd47d812823Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose state->id = auth_ctx->next_id;
096a9678919fae460342469989b97fd47d812823Sumit Bose auth_ctx->next_id++;
096a9678919fae460342469989b97fd47d812823Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose value.type = HASH_VALUE_PTR;
096a9678919fae460342469989b97fd47d812823Sumit Bose value.ptr = req;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose DEBUG(8, ("Queueing request [%d]\n", key.ul));
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose hret = hash_enter(auth_ctx->request_table,
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose &key, &value);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov if (hret != HASH_SUCCESS) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose DEBUG(1, ("Could not add request to the queue\n"));
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose talloc_zfree(req);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose return NULL;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose }
096a9678919fae460342469989b97fd47d812823Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose talloc_set_destructor((TALLOC_CTX *) state,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov proxy_child_destructor);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
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 */
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov auth_ctx->running++;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose subreq = proxy_child_init_send(auth_ctx, state, auth_ctx);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (!subreq) {
096a9678919fae460342469989b97fd47d812823Sumit Bose DEBUG(1, ("Could not fork child process\n"));
096a9678919fae460342469989b97fd47d812823Sumit Bose auth_ctx->running--;
096a9678919fae460342469989b97fd47d812823Sumit Bose talloc_zfree(req);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov return NULL;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose tevent_req_set_callback(subreq, proxy_child_init_done, req);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose state->running = true;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose else {
096a9678919fae460342469989b97fd47d812823Sumit Bose /* If there was no available slot, it will be queued
096a9678919fae460342469989b97fd47d812823Sumit Bose * until a slot is available
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov */
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose DEBUG(8, ("All available child slots are full, queuing request\n"));
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose }
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose return req;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose}
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bosestatic int pc_init_destructor (TALLOC_CTX *ctx)
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose{
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose struct pc_init_ctx *init_ctx =
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose talloc_get_type(ctx, struct pc_init_ctx);
096a9678919fae460342469989b97fd47d812823Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* If the init request has died, forcibly kill the child */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov kill(init_ctx->pid, SIGKILL);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose return 0;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose}
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bosestatic void pc_init_sig_handler(struct tevent_context *ev,
096a9678919fae460342469989b97fd47d812823Sumit Bose struct tevent_signal *sige, int signum,
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose int count, void *__siginfo, void *pvt);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashovstatic void pc_init_timeout(struct tevent_context *ev,
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose struct tevent_timer *te,
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose struct timeval t, void *ptr);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bosestatic struct tevent_req *proxy_child_init_send(TALLOC_CTX *mem_ctx,
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose struct proxy_child_ctx *child_ctx,
096a9678919fae460342469989b97fd47d812823Sumit Bose struct proxy_auth_ctx *auth_ctx)
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose{
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov struct tevent_req *req;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose struct pc_init_ctx *state;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose char **proxy_child_args;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose struct timeval tv;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose errno_t ret;
096a9678919fae460342469989b97fd47d812823Sumit Bose pid_t pid;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov req = tevent_req_create(mem_ctx, &state, struct pc_init_ctx);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (req == NULL) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose DEBUG(1, ("Could not create tevent_req\n"));
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose return NULL;
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose }
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose state->child_ctx = child_ctx;
096a9678919fae460342469989b97fd47d812823Sumit Bose
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov state->command = talloc_asprintf(req,
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 auth_ctx->be->domain->name,
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose child_ctx->id);
096a9678919fae460342469989b97fd47d812823Sumit Bose if (state->command == NULL) {
096a9678919fae460342469989b97fd47d812823Sumit Bose DEBUG(1, ("talloc_asprintf failed.\n"));
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose return NULL;
096a9678919fae460342469989b97fd47d812823Sumit Bose }
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose DEBUG(7, ("Starting proxy child with args [%s]\n", state->command));
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose pid = fork();
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose if (pid < 0) {
096a9678919fae460342469989b97fd47d812823Sumit Bose ret = errno;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(1, ("fork failed [%d][%s].\n", ret, strerror(ret)));
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose talloc_zfree(req);
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose return NULL;
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose }
096a9678919fae460342469989b97fd47d812823Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose if (pid == 0) { /* child */
096a9678919fae460342469989b97fd47d812823Sumit Bose proxy_child_args = parse_args(state->command);
096a9678919fae460342469989b97fd47d812823Sumit Bose execvp(proxy_child_args[0], proxy_child_args);
096a9678919fae460342469989b97fd47d812823Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose ret = errno;
096a9678919fae460342469989b97fd47d812823Sumit Bose DEBUG(0, ("Could not start proxy child [%s]: [%d][%s].\n",
096a9678919fae460342469989b97fd47d812823Sumit Bose state->command, ret, strerror(ret)));
096a9678919fae460342469989b97fd47d812823Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose _exit(1);
096a9678919fae460342469989b97fd47d812823Sumit Bose }
096a9678919fae460342469989b97fd47d812823Sumit Bose
096a9678919fae460342469989b97fd47d812823Sumit Bose else { /* parent */
096a9678919fae460342469989b97fd47d812823Sumit Bose state->pid = pid;
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
096a9678919fae460342469989b97fd47d812823Sumit Bose state->sige = tevent_add_signal(auth_ctx->be->ev, req,
096a9678919fae460342469989b97fd47d812823Sumit Bose SIGCHLD, SA_SIGINFO,
096a9678919fae460342469989b97fd47d812823Sumit Bose pc_init_sig_handler, req);
096a9678919fae460342469989b97fd47d812823Sumit Bose if (state->sige == NULL) {
096a9678919fae460342469989b97fd47d812823Sumit Bose DEBUG(1, ("tevent_add_signal failed.\n"));
096a9678919fae460342469989b97fd47d812823Sumit Bose talloc_zfree(req);
096a9678919fae460342469989b97fd47d812823Sumit Bose return NULL;
096a9678919fae460342469989b97fd47d812823Sumit Bose }
096a9678919fae460342469989b97fd47d812823Sumit Bose
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 */
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose child_ctx->init_req = req;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
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 */
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose tv = tevent_timeval_current_ofs(6, 0);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose state->timeout = tevent_add_timer(auth_ctx->be->ev, req,
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose tv, pc_init_timeout, req);
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose /* processing will continue once the connection is received
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek * in proxy_client_init()
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek */
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek return req;
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek }
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek}
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozekstatic void pc_init_sig_handler(struct tevent_context *ev,
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek struct tevent_signal *sige, int signum,
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek int count, void *__siginfo, void *pvt)
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov{
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek int ret;
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek int child_status;
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek struct tevent_req *req;
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek struct pc_init_ctx *init_ctx;
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek if (count <= 0) {
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek DEBUG(0, ("SIGCHLD handler called with invalid child count\n"));
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose return;
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose }
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose req = talloc_get_type(pvt, struct tevent_req);
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose init_ctx = tevent_req_data(req, struct pc_init_ctx);
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(7, ("Waiting for child [%d].\n", init_ctx->pid));
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose errno = 0;
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose ret = waitpid(init_ctx->pid, &child_status, WNOHANG);
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose if (ret == -1) {
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek ret = errno;
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 } else {
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek if (WIFEXITED(child_status)) {
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(4, ("child [%d] exited with status [%d].\n", ret,
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose WEXITSTATUS(child_status)));
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose tevent_req_error(req, EIO);
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose } else if (WIFSIGNALED(child_status)) {
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(4, ("child [%d] was terminate by signal [%d].\n", ret,
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose WTERMSIG(child_status)));
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose tevent_req_error(req, EIO);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov } else {
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose if (WIFSTOPPED(child_status)) {
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(1, ("child [%d] was stopped by signal [%d].\n", ret,
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose WSTOPSIG(child_status)));
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose }
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek if (WIFCONTINUED(child_status)) {
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(1, ("child [%d] was resumed by delivery of SIGCONT.\n",
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose ret));
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose }
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(1, ("Child is still running, no new child is started.\n"));
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose return;
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose }
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose }
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose}
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bosestatic void pc_init_timeout(struct tevent_context *ev,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek struct tevent_timer *te,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek struct timeval t, void *ptr)
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek{
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek struct tevent_req *req;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek DEBUG(2, ("Client timed out before Identification!\n"));
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek req = talloc_get_type(ptr, struct tevent_req);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek tevent_req_error(req, ETIMEDOUT);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek}
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekstatic errno_t proxy_child_init_recv(struct tevent_req *req,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek pid_t *pid,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek struct sbus_connection **conn)
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek{
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek struct pc_init_ctx *state;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek TEVENT_REQ_RETURN_ON_ERROR(req);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
09d7c105839bfc7447ea0f766413ed86675ca075Sumit Bose state = tevent_req_data(req, struct pc_init_ctx);
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek
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 * set up.
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce */
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce talloc_set_destructor((TALLOC_CTX *)state, NULL);
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose *pid = state->pid;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose *conn = state->conn;
09d7c105839bfc7447ea0f766413ed86675ca075Sumit Bose
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek return EOK;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek}
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozekstruct proxy_child_sig_ctx {
5627532b81802c2654ced8edac07f420bd677930Jakub Hrozek struct proxy_auth_ctx *auth_ctx;
5627532b81802c2654ced8edac07f420bd677930Jakub Hrozek pid_t pid;
5627532b81802c2654ced8edac07f420bd677930Jakub Hrozek};
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorcestatic void proxy_child_sig_handler(struct tevent_context *ev,
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce struct tevent_signal *sige, int signum,
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce int count, void *__siginfo, void *pvt);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashovstatic struct tevent_req *proxy_pam_conv_send(TALLOC_CTX *mem_ctx,
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce struct proxy_auth_ctx *auth_ctx,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct sbus_connection *conn,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct pam_data *pd,
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce pid_t pid);
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorcestatic void proxy_pam_conv_done(struct tevent_req *subreq);
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorcestatic void proxy_child_init_done(struct tevent_req *subreq) {
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce int ret;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce struct tevent_signal *sige;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct tevent_req *req =
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce tevent_req_callback_data(subreq, struct tevent_req);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce struct proxy_child_ctx *child_ctx =
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov tevent_req_data(req, struct proxy_child_ctx);
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce struct proxy_child_sig_ctx *sig_ctx;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose ret = proxy_child_init_recv(subreq, &child_ctx->pid, &child_ctx->conn);
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce talloc_zfree(subreq);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce if (ret != EOK) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(6, ("Proxy child init failed [%d]\n", ret));
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce tevent_req_error(req, ret);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce return;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
fdda4b659fa3be3027df91a2b053835186ec2c59Sumit Bose
09d7c105839bfc7447ea0f766413ed86675ca075Sumit Bose /* An initialized child is available, awaiting the PAM command */
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose subreq = proxy_pam_conv_send(req, child_ctx->auth_ctx,
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose child_ctx->conn, child_ctx->pd,
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose child_ctx->pid);
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose if (!subreq) {
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose DEBUG(1,("Could not start PAM conversation\n"));
c5711b0279ea85d69fe3c77dfb194360c346e1d7Sumit Bose tevent_req_error(req, EIO);
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek return;
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek }
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek tevent_req_set_callback(subreq, proxy_pam_conv_done, req);
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek
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 */
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek sig_ctx = talloc_zero(child_ctx->auth_ctx, struct proxy_child_sig_ctx);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek if(sig_ctx == NULL) {
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek DEBUG(1, ("tevent_add_signal failed.\n"));
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek tevent_req_error(req, ENOMEM);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek return;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek }
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek sig_ctx->auth_ctx = child_ctx->auth_ctx;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek sig_ctx->pid = child_ctx->pid;
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek sige = tevent_add_signal(child_ctx->auth_ctx->be->ev,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek child_ctx->auth_ctx,
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce SIGCHLD, SA_SIGINFO,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov proxy_child_sig_handler,
0fcdef99980260d2da308c2c26861492ab983e3dJakub Hrozek sig_ctx);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce if (sige == NULL) {
204cfc89a076fd32bf34f2abb3f809304aaa88abSimo Sorce DEBUG(1, ("tevent_add_signal failed.\n"));
0fcdef99980260d2da308c2c26861492ab983e3dJakub Hrozek tevent_req_error(req, ENOMEM);
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce return;
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce }
0fcdef99980260d2da308c2c26861492ab983e3dJakub Hrozek
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 Hrozek */
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek talloc_steal(sige, sig_ctx);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek}
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekstatic void remove_sige(struct tevent_context *ev,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek struct tevent_immediate *imm,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek void *pvt);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekstatic void run_proxy_child_queue(struct tevent_context *ev,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek struct tevent_immediate *imm,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek void *pvt);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekstatic void proxy_child_sig_handler(struct tevent_context *ev,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek struct tevent_signal *sige, int signum,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek int count, void *__siginfo, void *pvt)
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek{
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek int ret;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek int child_status;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce struct proxy_child_sig_ctx *sig_ctx;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce struct tevent_immediate *imm;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce struct tevent_immediate *imm2;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek if (count <= 0) {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce DEBUG(0, ("SIGCHLD handler called with invalid child count\n"));
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce return;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
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
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce errno = 0;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce ret = waitpid(sig_ctx->pid, &child_status, WNOHANG);
95e94691178297f2b8225a83d43ae388cab04b45Simo Sorce
31dd31b00ad759f256282ef0f7054e60672161ceJakub Hrozek if (ret == -1) {
4f118e3e6a25762f40a43e6dbefb09f44adbef32Simo Sorce ret = errno;
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 } else {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce if (WIFEXITED(child_status)) {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce DEBUG(4, ("child [%d] exited with status [%d].\n", ret,
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce WEXITSTATUS(child_status)));
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov } else if (WIFSIGNALED(child_status)) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(4, ("child [%d] was terminated by signal [%d].\n", ret,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose WTERMSIG(child_status)));
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce } else {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce if (WIFSTOPPED(child_status)) {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce DEBUG(1, ("child [%d] was stopped by signal [%d].\n", ret,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose WSTOPSIG(child_status)));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce if (WIFCONTINUED(child_status)) {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce DEBUG(1, ("child [%d] was resumed by delivery of SIGCONT.\n",
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce ret));
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce }
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce DEBUG(1, ("Child is still running, no new child is started.\n"));
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce return;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
418e6ccd116eced7ccc75aca999a4c37c67289baJakub Hrozek
418e6ccd116eced7ccc75aca999a4c37c67289baJakub Hrozek imm = tevent_create_immediate(ev);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek if (imm == NULL) {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce DEBUG(1, ("tevent_create_immediate failed.\n"));
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce return;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek }
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek tevent_schedule_immediate(imm, ev, run_proxy_child_queue,
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce sig_ctx->auth_ctx);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce /* schedule another immediate timer to delete the sigchld handler */
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce imm2 = tevent_create_immediate(ev);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce if (imm == NULL) {
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce DEBUG(1, ("tevent_create_immediate failed.\n"));
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce return;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce tevent_schedule_immediate(imm2, ev, remove_sige, sige);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce }
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce return;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce}
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorcestatic void remove_sige(struct tevent_context *ev,
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce struct tevent_immediate *imm,
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce void *pvt)
9b7762729da24a901388ea53da29448f23e0f77bJakub Hrozek{
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek talloc_free(pvt);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek}
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
81165faf5d951aca69f410713730c26ff048ec44Sumit Bosestruct proxy_conv_ctx {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct proxy_auth_ctx *auth_ctx;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct sbus_connection *conn;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct pam_data *pd;
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce pid_t pid;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce};
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 struct proxy_auth_ctx *auth_ctx,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct sbus_connection *conn,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct pam_data *pd,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose pid_t pid)
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose{
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose errno_t ret;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose bool dp_ret;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DBusMessage *msg;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct tevent_req *req;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct proxy_conv_ctx *state;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose req = tevent_req_create(mem_ctx, &state, struct proxy_conv_ctx);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (req == NULL) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose return NULL;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose state->auth_ctx = auth_ctx;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose state->conn = conn;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose state->pd = pd;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose state->pid = pid;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek msg = dbus_message_new_method_call(NULL,
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek DP_PATH,
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek DP_INTERFACE,
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek DP_METHOD_PAMHANDLER);
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek if (msg == NULL) {
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek DEBUG(1, ("dbus_message_new_method_call failed.\n"));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose talloc_zfree(req);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny return NULL;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose }
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny DEBUG(4, ("Sending request with the following data:\n"));
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce DEBUG_PAM_DATA(4, pd);
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce dp_ret = dp_pack_pam_request(msg, pd);
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce if (!dp_ret) {
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce DEBUG(1, ("Failed to build message\n"));
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce dbus_message_unref(msg);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek talloc_zfree(req);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek return NULL;
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce }
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce ret = sbus_conn_send(state->conn, msg, state->auth_ctx->timeout_ms,
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce proxy_pam_conv_reply, req, NULL);
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce if (ret != EOK) {
5e60c73cb91d1659755fb5ea829837db68d46163Sumit Bose dbus_message_unref(msg);
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce talloc_zfree(req);
5ea449b18d2597f2581627de80bcaf2bc70b0fd3Simo Sorce return NULL;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce dbus_message_unref(msg);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose return req;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce}
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorcestatic void proxy_pam_conv_reply(DBusPendingCall *pending, void *ptr)
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose{
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct tevent_req *req;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce struct proxy_conv_ctx *state;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce DBusError dbus_error;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DBusMessage *reply;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce int type;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose int ret;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce DEBUG(8, ("Handling pam conversation reply\n"));
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce req = talloc_get_type(ptr, struct tevent_req);
20ccfd63a17dc15dd24e6543424d86913d511c4bSumit Bose state = tevent_req_data(req, struct proxy_conv_ctx);
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce dbus_error_init(&dbus_error);
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce reply = dbus_pending_call_steal_reply(pending);
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce dbus_pending_call_unref(pending);
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek if (reply == NULL) {
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce DEBUG(0, ("Severe error. A reply callback was called but no reply was"
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "received and no timeout occurred\n"));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose state->pd->pam_status = PAM_SYSTEM_ERR;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce tevent_req_error(req, EIO);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce type = dbus_message_get_type(reply);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose switch (type) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov case DBUS_MESSAGE_TYPE_METHOD_RETURN:
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov ret = dp_unpack_pam_response(reply, state->pd, &dbus_error);
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce if (!ret) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(0, ("Failed to parse reply.\n"));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose state->pd->pam_status = PAM_SYSTEM_ERR;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce dbus_message_unref(reply);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose tevent_req_error(req, EIO);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose return;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose }
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce DEBUG(4, ("received: [%d][%s]\n",
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce state->pd->pam_status,
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce state->pd->domain));
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce break;
4c20fe34346919cf676c3e1b54b7701069e2aac6Simo Sorce case DBUS_MESSAGE_TYPE_ERROR:
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose DEBUG(0, ("Reply error [%s].\n",
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose dbus_message_get_error_name(reply)));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose state->pd->pam_status = PAM_SYSTEM_ERR;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose break;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose default:
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(0, ("Default... what now?.\n"));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose state->pd->pam_status = PAM_SYSTEM_ERR;
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce }
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce dbus_message_unref(reply);
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce /* Kill the child */
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose kill(state->pid, SIGKILL);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose /* Conversation is finished */
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose tevent_req_done(req);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose}
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashovstatic errno_t proxy_pam_conv_recv(struct tevent_req *req)
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose{
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose TEVENT_REQ_RETURN_ON_ERROR(req);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov return EOK;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose}
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bosestatic void proxy_pam_conv_done(struct tevent_req *subreq)
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose{
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct tevent_req *req;
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek int ret;
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek req = tevent_req_callback_data(subreq, struct tevent_req);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose ret = proxy_pam_conv_recv(subreq);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose talloc_zfree(subreq);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (ret != EOK) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(6, ("Proxy PAM conversation failed [%d]\n", ret));
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose tevent_req_error(req, ret);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose return;
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose tevent_req_done(req);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny}
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zelenystatic int proxy_child_recv(struct tevent_req *req,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose TALLOC_CTX *mem_ctx,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct pam_data **pd)
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose{
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny struct proxy_child_ctx *ctx;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny TEVENT_REQ_RETURN_ON_ERROR(req);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny ctx = tevent_req_data(req, struct proxy_child_ctx);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny *pd = talloc_steal(mem_ctx, ctx->pd);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny return EOK;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose}
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bosestatic void proxy_child_done(struct tevent_req *req)
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose{
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct proxy_client_ctx *client_ctx =
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose tevent_req_callback_data(req, struct proxy_client_ctx);
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce struct pam_data *pd = NULL;
21f19d573047e70ee8ec0119ec00c1ed1af9ec04Simo Sorce char *password;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose int ret;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose struct tevent_immediate *imm;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose ret = proxy_child_recv(req, client_ctx, &pd);
6a81cb8c3424dbe9f764af3738299cbbe5874a15Simo Sorce talloc_zfree(req);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose /* Start the next auth in the queue, if any */
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose client_ctx->auth_ctx->running--;
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose imm = tevent_create_immediate(client_ctx->be_req->be_ctx->ev);
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (imm == NULL) {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose DEBUG(1, ("tevent_create_immediate failed.\n"));
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.
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny */
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose } else {
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose tevent_schedule_immediate(imm,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose client_ctx->be_req->be_ctx->ev,
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose run_proxy_child_queue,
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek client_ctx->auth_ctx);
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek }
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek if (ret != EOK) {
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek /* Pam child failed */
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek proxy_reply(client_ctx->be_req, DP_ERR_FATAL, ret,
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek "PAM child failed");
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek return;
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek }
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek
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 pd->pam_status == PAM_SUCCESS &&
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek client_ctx->be_req->be_ctx->domain->cache_credentials) {
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek password = talloc_strndup(client_ctx->be_req,
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek (char *) pd->authtok,
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek pd->authtok_size);
ad9ca94d0c793c2e30e77f4cc385bf10e42e382fJakub Hrozek if (!password) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose /* password caching failures are not fatal errors */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose DEBUG(2, ("Failed to cache password\n"));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose goto done;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose talloc_set_destructor((TALLOC_CTX *)password, password_destructor);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose ret = sysdb_cache_password(client_ctx->be_req->be_ctx->sysdb,
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose pd->user, password);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose /* password caching failures are not fatal errors */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose /* so we just log it any return */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose if (ret != EOK) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose DEBUG(2, ("Failed to cache password (%d)[%s]!?\n",
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose ret, strerror(ret)));
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bosedone:
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose proxy_reply(client_ctx->be_req, DP_ERR_OK, EOK, NULL);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose}
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bosestatic void run_proxy_child_queue(struct tevent_context *ev,
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose struct tevent_immediate *imm,
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose void *pvt)
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose{
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose struct proxy_auth_ctx *auth_ctx;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose struct hash_iter_context_t *iter;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose struct hash_entry_t *entry;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose struct tevent_req *req;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose struct tevent_req *subreq;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose struct proxy_child_ctx *state;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose auth_ctx = talloc_get_type(pvt, struct proxy_auth_ctx);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose /* Launch next queued request */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose iter = new_hash_iter_context(auth_ctx->request_table);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose while ((entry = iter->next(iter)) != NULL) {
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 if (!state->running) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose break;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose free(iter);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose if (!entry) {
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose /* Nothing pending on the queue */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose return;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose }
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose
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 */
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose auth_ctx->running++;
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose subreq = proxy_child_init_send(auth_ctx, state, auth_ctx);
08ab0d4ede41a1749e0bc26f78a37a4d10c20db8Sumit Bose if (!subreq) {
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose DEBUG(1, ("Could not fork child process\n"));
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose auth_ctx->running--;
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose talloc_zfree(req);
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose return;
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose }
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose tevent_req_set_callback(subreq, proxy_child_init_done, req);
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose
a50b229c8ea1e22c9efa677760b94d8c48c3ec89Sumit Bose state->running = true;
44329653f423c632b027065a9c0ea0bf4199396aSumit Bose }
44329653f423c632b027065a9c0ea0bf4199396aSumit Bose}
44329653f423c632b027065a9c0ea0bf4199396aSumit Bose