summaryrefslogtreecommitdiffstats
path: root/src/providers/data_provider/dp_private.h
blob: 2e71a373fdc8886fccb23bfb8283dc5bc341b1b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/*
    Authors:
        Pavel Březina <pbrezina@redhat.com>

    Copyright (C) 2016 Red Hat

    This program is free software; you can redistribute it and/or modify
    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/>.
*/

#ifndef _DP_PRIVATE_H_
#define _DP_PRIVATE_H_

#include <tevent.h>
#include <dhash.h>
#include "sbus/sssd_dbus.h"
#include "providers/data_provider/dp.h"
#include "util/util.h"

#define DP_REQ_DEBUG(level, name, fmt, ...) \
    DEBUG(level, "DP Request [%s]: " fmt "\n", (name ?: "Unknown"), ##__VA_ARGS__)

enum dp_clients {
    DPC_NSS,
    DPC_PAM,
    DPC_IFP,
    DPC_PAC,
    DPC_SUDO,
    DPC_HOST,
    DPC_AUTOFS,

    DP_CLIENT_SENTINEL
};

struct dp_req;
struct dp_client;

struct dp_module {
    bool initialized;
    const char *name;
    void *module_data;
    void *libhandle;
};

struct dp_target {
    const char *name;
    const char *module_name;
    bool explicitly_configured;

    bool initialized;
    enum dp_targets target;
    struct dp_module *module;
    struct dp_method *methods;
};

struct dp_method {
    dp_req_send_fn send_fn;
    dp_req_recv_fn recv_fn;
    void *method_data;
    const char *method_dtype;
    const char *request_dtype;
    const char *output_dtype;
    uint32_t output_size;
};

struct data_provider {
    uid_t uid;
    gid_t gid;
    struct be_ctx *be_ctx;
    struct tevent_context *ev;
    struct sbus_connection *srv_conn;
    struct dp_client *clients[DP_CLIENT_SENTINEL];
    bool terminating;

    struct {
        /* Numeric identificator that will be assigned to next request. */
        uint32_t index;

        /* List of all ongoing requests. */
        uint32_t num_active;
        struct dp_req *active;

        /* Table containing list of sbus_requests where DP sends reply when
         * a request is finished. Value of this table is pair
         * <tevent_req, list of sbus_request>
         */
        hash_table_t *reply_table;
    } requests;

    struct dp_module **modules;
    struct dp_target **targets;
};

errno_t dp_find_method(struct data_provider *provider,
                       enum dp_targets target,
                       enum dp_methods method,
                       struct dp_method **_execute);

struct dp_module *dp_load_module(TALLOC_CTX *mem_ctx,
                                 struct be_ctx *be_ctx,
                                 struct data_provider *provider,
                                 struct dp_module **modules,
                                 const char *name);

errno_t dp_init_modules(TALLOC_CTX *mem_ctx, struct dp_module ***_modules);

const char *dp_target_to_string(enum dp_targets target);

bool dp_target_initialized(struct dp_target **targets, enum dp_targets type);

errno_t dp_init_targets(TALLOC_CTX *mem_ctx,
                        struct be_ctx *be_ctx,
                        struct data_provider *provider,
                        struct dp_module **modules);

/* Reply callbacks. */

typedef void (*dp_req_post_fn)(const char *req_name,
                               struct data_provider *provider,
                               void *post_data,
                               void *reply_data);

typedef void (*dp_req_reply_fn)(const char *req_name,
                                struct sbus_request *sbus_req,
                                void *data);

void dp_req_reply_default(const char *req_name,
                          struct sbus_request *sbus_req,
                          void *data);

/* Data provider request table. */

struct dp_sbus_req_item;

struct dp_table_value {
    hash_table_t *table;
    const char *key;

    struct tevent_req *req;
    struct dp_sbus_req_item *list;
};

struct dp_sbus_req_item {
    struct dp_table_value *parent;
    struct sbus_request *sbus_req;

    struct dp_sbus_req_item *prev;
    struct dp_sbus_req_item *next;
};

char *dp_req_table_key(TALLOC_CTX *mem_ctx,
                       enum dp_targets target,
                       enum dp_methods method,
                       uint32_t dp_flags,
                       const char *custom_part);

errno_t dp_req_table_init(TALLOC_CTX *mem_ctx, hash_table_t **_table);

struct dp_table_value *dp_req_table_lookup(hash_table_t *table,
                                           const char *key);

errno_t dp_req_table_add(hash_table_t *table,
                         const char *key,
                         struct tevent_req *req,
                         struct sbus_request *sbus_req);

void dp_req_table_del(hash_table_t *table,
                      const char *key);

void dp_req_table_del_and_free(hash_table_t *table,
                               const char *key);

bool dp_req_table_has_key(hash_table_t *table,
                          const char *key);

/* Data provider request. */

void dp_terminate_active_requests(struct data_provider *provider);

void dp_req_reply_error(struct sbus_request *sbus_req,
                        const char *req_name,
                        errno_t ret);

void _dp_req_with_reply(struct dp_client *dp_cli,
                        const char *domain,
                        const char *request_name,
                        const char *custom_key,
                        struct sbus_request *sbus_req,
                        enum dp_targets target,
                        enum dp_methods method,
                        uint32_t dp_flags,
                        void *request_data,
                        dp_req_post_fn postprocess_fn,
                        void *postprocess_data,
                        dp_req_reply_fn reply_fn,
                        const char *output_dtype);

/**
 * If @domain is NULL, be_ctx->domain is used.
 * If req_key is NULL, address of sbus_req is used.
 *
 * If @pp_fn (post process function) is set it is call on a successful
 * DP request before reply is sent.
 */
#define dp_req_with_reply_pp(dp_cli, domain, req_name, req_key, sbus_req,     \
                             target, method, dp_flags, req_data, pp_fn,       \
                             pp_data, pp_dtype, reply_fn, output_dtype)       \
    do {                                                                      \
        /* Check postprocess function parameter types. */                     \
        void (*__pp_fn)(const char *, struct data_provider *,                 \
            pp_dtype *, output_dtype *) = (pp_fn);                            \
        pp_dtype *__pp_data = (pp_data);                                      \
                                                                              \
        /* Check reply function parameter types. */                           \
        void (*__reply_fn)(const char *, struct sbus_request *,               \
            output_dtype *) = (reply_fn);                                     \
                                                                              \
        _dp_req_with_reply(dp_cli, domain, req_name, req_key, sbus_req,       \
                           target, method, dp_flags, req_data,                \
                           (dp_req_post_fn)__pp_fn, __pp_data,                \
                           (dp_req_reply_fn)__reply_fn, #output_dtype);       \
    } while(0)

#define dp_req_with_reply(dp_cli, domain, req_name, req_key, sbus_req, target,\
                          method, dp_flags, req_data, reply_fn,               \
                          output_dtype)                                       \
    dp_req_with_reply_pp(dp_cli, domain, req_name, req_key, sbus_req, target, \
                         method, dp_flags, req_data, NULL, NULL, void,        \
                         reply_fn, output_dtype)

/* Client shared functions. */

errno_t dp_client_init(struct sbus_connection *conn, void *data);
struct data_provider *dp_client_provider(struct dp_client *dp_cli);
struct be_ctx *dp_client_be(struct dp_client *dp_cli);
struct sbus_connection *dp_client_conn(struct dp_client *dp_cli);

#endif /* _DP_PRIVATE_H_ */