/*
SSSD
Authors:
Stephen Gallagher <sgallagh@redhat.com>
Copyright (C) 2010 Red Hat
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "providers/proxy/proxy_iface_generated.h"
struct pc_init_ctx;
{
int hret;
if (!(hret == HASH_SUCCESS ||
hret == HASH_ERROR_KEY_NOT_FOUND)) {
/* Nothing we can do about this, so just continue */
}
return 0;
}
struct proxy_child_ctx *child_ctx,
struct proxy_auth_ctx *auth_ctx);
struct proxy_auth_ctx *auth_ctx,
{
int hret;
return NULL;
}
/* Find an available key */
/* Handle overflow, zero is a reserved value
* Also handle the unlikely case where the next ID
* is still awaiting being run
*/
/* We've looped through all possible integers! */
return NULL;
}
}
if (hret != HASH_SUCCESS) {
return NULL;
}
/* There's an available slot; start a child
* to handle the request
*/
if (!subreq) {
return NULL;
}
}
else {
/* If there was no available slot, it will be queued
* until a slot is available
*/
"All available child slots are full, queuing request\n");
}
return req;
}
{
/* If the init request has died, forcibly kill the child */
return 0;
}
struct tevent_timer *te,
struct proxy_child_ctx *child_ctx,
struct proxy_auth_ctx *auth_ctx)
{
char **proxy_child_args;
return NULL;
}
"%s/proxy_child -d %#.4x --debug-timestamps=%d "
"--debug-microseconds=%d%s --domain %s --id %d",
return NULL;
}
if (pid < 0) {
return NULL;
}
if (pid == 0) { /* child */
"Could not start proxy child [%s]: [%d][%s].\n",
_exit(1);
}
else { /* parent */
/* Make sure to kill the child process if we abort */
SIGCHLD, 0,
return NULL;
}
/* Save the init request to the child context.
* This is technically a layering violation,
* but it's the only sane way to be able to
* identify which client is which when it
* connects to the backend in
* client_registration()
*/
/* Wait six seconds for the child to connect
* This is because the connection handler will add
* its own five-second timeout, and we don't want to
* be faster here.
*/
/* processing will continue once the connection is received
* in proxy_client_init()
*/
return req;
}
}
{
int ret;
int child_status;
if (count <= 0) {
"SIGCHLD handler called with invalid child count\n");
return;
}
errno = 0;
if (ret == -1) {
} else if (ret == 0) {
"waitpid did not find a child with changed status.\n");
} else {
if (WIFEXITED(child_status)) {
"child [%d] exited with status [%d].\n", ret,
} else if (WIFSIGNALED(child_status)) {
"child [%d] was terminate by signal [%d].\n", ret,
} else {
if (WIFSTOPPED(child_status)) {
"child [%d] was stopped by signal [%d].\n", ret,
}
if (WIFCONTINUED(child_status) == true) {
"child [%d] was resumed by delivery of SIGCONT.\n",
ret);
}
"Child is still running, no new child is started.\n");
return;
}
}
}
struct tevent_timer *te,
{
}
struct sbus_connection **conn)
{
/* Unset the destructor since we initialized successfully.
* We don't want to kill the child now that it's properly
* set up.
*/
return EOK;
}
struct proxy_child_sig_ctx {
};
struct proxy_auth_ctx *auth_ctx,
struct sbus_connection *conn,
int ret;
return;
}
/* An initialized child is available, awaiting the PAM command */
if (!subreq) {
return;
}
/* Add a signal handler for the child under the auth_ctx,
* that way if the child exits after completion of the
* request, it will still be handled.
*/
return;
}
SIGCHLD, 0,
sig_ctx);
return;
}
/* Steal the signal context onto the signal event
* so that when the signal is freed, the context
* will go with it.
*/
}
struct tevent_immediate *imm,
void *pvt);
struct tevent_immediate *imm,
void *pvt);
{
int ret;
int child_status;
if (count <= 0) {
"SIGCHLD handler called with invalid child count\n");
return;
}
errno = 0;
if (ret == -1) {
} else if (ret == 0) {
"waitpid did not found a child with changed status.\n");
} else {
if (WIFEXITED(child_status)) {
"child [%d] exited with status [%d].\n", ret,
} else if (WIFSIGNALED(child_status) == true) {
"child [%d] was terminated by signal [%d].\n", ret,
} else {
if (WIFSTOPPED(child_status)) {
"child [%d] was stopped by signal [%d].\n", ret,
}
if (WIFCONTINUED(child_status) == true) {
"child [%d] was resumed by delivery of SIGCONT.\n",
ret);
}
"Child is still running, no new child is started.\n");
return;
}
return;
}
/* schedule another immediate timer to delete the sigchld handler */
return;
}
}
return;
}
struct tevent_immediate *imm,
void *pvt)
{
}
struct proxy_conv_ctx {
};
struct proxy_auth_ctx *auth_ctx,
struct sbus_connection *conn,
{
bool dp_ret;
return NULL;
}
return NULL;
}
if (!dp_ret) {
return NULL;
}
return NULL;
}
return req;
}
{
int type;
int ret;
"Severe error. A reply callback was called but no reply was"
"received and no timeout occurred\n");
}
switch (type) {
if (!ret) {
return;
}
break;
case DBUS_MESSAGE_TYPE_ERROR:
break;
default:
}
/* Kill the child */
/* Conversation is finished */
}
{
return EOK;
}
{
int ret;
return;
}
}
{
return EOK;
}
struct tevent_immediate *imm,
void *pvt)
{
/* Launch next queued request */
break;
}
}
if (!entry) {
/* Nothing pending on the queue */
return;
}
/* There's an available slot; start a child
* to handle the request
*/
if (!subreq) {
return;
}
}
}
struct proxy_pam_handler_state {
};
struct tevent_req *
struct proxy_auth_ctx *proxy_auth_ctx,
struct dp_req_params *params)
{
return NULL;
}
case SSS_PAM_AUTHENTICATE:
case SSS_PAM_CHAUTHTOK:
case SSS_PAM_CHAUTHTOK_PRELIM:
case SSS_PAM_ACCT_MGMT:
/* Queue the request and spawn a child if there is an available slot. */
goto immediately;
}
break;
case SSS_PAM_SETCRED:
case SSS_PAM_OPEN_SESSION:
case SSS_PAM_CLOSE_SESSION:
goto immediately;
default:
goto immediately;
}
return req;
/* TODO For backward compatibility we always return EOK to DP now. */
return req;
}
{
const char *password;
goto done;
}
/* Start the next auth in the queue, if any */
/* We'll still finish the current request, but we're
* likely to have problems if there are queued events
* if we've gotten into this state.
* Hopefully this is impossible, since freeing req
* above should guarantee that we have enough memory
* to create this immediate event.
*/
} else {
}
/* Check if we need to save the cached credentials */
if (ret) {
/* password caching failures are not fatal errors */
goto done;
}
/* password caching failures are not fatal errors */
/* so we just log it any return */
}
}
done:
/* TODO For backward compatibility we always return EOK to DP now. */
}
struct tevent_req *req,
{
return EOK;
}