~ubuntu-branches/ubuntu/saucy/sssd/saucy

« back to all changes in this revision

Viewing changes to src/providers/ipa/ipa_init.c

  • Committer: Stéphane Graber
  • Date: 2011-06-15 16:23:14 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: stgraber@ubuntu.com-20110615162314-rbhoppnpaxfqo5q7
Merge 1.5.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    SSSD
 
3
 
 
4
    IPA Provider Initialization functions
 
5
 
 
6
    Authors:
 
7
        Simo Sorce <ssorce@redhat.com>
 
8
 
 
9
    Copyright (C) 2009 Red Hat
 
10
 
 
11
    This program is free software; you can redistribute it and/or modify
 
12
    it under the terms of the GNU General Public License as published by
 
13
    the Free Software Foundation; either version 3 of the License, or
 
14
    (at your option) any later version.
 
15
 
 
16
    This program is distributed in the hope that it will be useful,
 
17
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
    GNU General Public License for more details.
 
20
 
 
21
    You should have received a copy of the GNU General Public License
 
22
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
23
*/
 
24
 
 
25
#include <sys/types.h>
 
26
#include <unistd.h>
 
27
#include <sys/stat.h>
 
28
#include <fcntl.h>
 
29
 
 
30
#include "providers/child_common.h"
 
31
#include "providers/ipa/ipa_common.h"
 
32
#include "providers/krb5/krb5_auth.h"
 
33
#include "providers/ipa/ipa_auth.h"
 
34
#include "providers/ipa/ipa_access.h"
 
35
#include "providers/ipa/ipa_dyndns.h"
 
36
 
 
37
struct ipa_options *ipa_options = NULL;
 
38
 
 
39
/* Id Handler */
 
40
struct bet_ops ipa_id_ops = {
 
41
    .handler = sdap_account_info_handler,
 
42
    .finalize = NULL,
 
43
    .check_online = sdap_check_online
 
44
};
 
45
 
 
46
struct bet_ops ipa_auth_ops = {
 
47
    .handler = ipa_auth,
 
48
    .finalize = NULL,
 
49
};
 
50
 
 
51
struct bet_ops ipa_chpass_ops = {
 
52
    .handler = ipa_auth,
 
53
    .finalize = NULL,
 
54
};
 
55
 
 
56
struct bet_ops ipa_access_ops = {
 
57
    .handler = ipa_access_handler,
 
58
    .finalize = NULL
 
59
};
 
60
 
 
61
int common_ipa_init(struct be_ctx *bectx)
 
62
{
 
63
    const char *ipa_servers;
 
64
    int ret;
 
65
 
 
66
    ret = ipa_get_options(bectx, bectx->cdb,
 
67
                          bectx->conf_path,
 
68
                          bectx->domain, &ipa_options);
 
69
    if (ret != EOK) {
 
70
        return ret;
 
71
    }
 
72
 
 
73
    ipa_servers = dp_opt_get_string(ipa_options->basic, IPA_SERVER);
 
74
    if (!ipa_servers) {
 
75
        DEBUG(1, ("Missing ipa_server option - using service discovery!\n"));
 
76
    }
 
77
 
 
78
    ret = ipa_service_init(ipa_options, bectx, ipa_servers, ipa_options,
 
79
                           &ipa_options->service);
 
80
    if (ret != EOK) {
 
81
        DEBUG(0, ("Failed to init IPA failover service!\n"));
 
82
        return ret;
 
83
    }
 
84
 
 
85
    return EOK;
 
86
}
 
87
 
 
88
int sssm_ipa_id_init(struct be_ctx *bectx,
 
89
                     struct bet_ops **ops,
 
90
                     void **pvt_data)
 
91
{
 
92
    struct sdap_id_ctx *ctx;
 
93
    struct stat stat_buf;
 
94
    errno_t err;
 
95
    int ret;
 
96
 
 
97
    if (!ipa_options) {
 
98
        ret = common_ipa_init(bectx);
 
99
        if (ret != EOK) {
 
100
            return ret;
 
101
        }
 
102
    }
 
103
 
 
104
    if (ipa_options->id_ctx) {
 
105
        /* already initialized */
 
106
        *ops = &ipa_id_ops;
 
107
        *pvt_data = ipa_options->id_ctx;
 
108
        return EOK;
 
109
    }
 
110
 
 
111
    ctx = talloc_zero(ipa_options, struct sdap_id_ctx);
 
112
    if (!ctx) {
 
113
        return ENOMEM;
 
114
    }
 
115
    ctx->be = bectx;
 
116
    ctx->service = ipa_options->service->sdap;
 
117
    ipa_options->id_ctx = ctx;
 
118
 
 
119
    ret = ipa_get_id_options(ipa_options, bectx->cdb,
 
120
                             bectx->conf_path,
 
121
                             &ctx->opts);
 
122
    if (ret != EOK) {
 
123
        goto done;
 
124
    }
 
125
 
 
126
    if(dp_opt_get_bool(ipa_options->basic, IPA_DYNDNS_UPDATE)) {
 
127
        /* Perform automatic DNS updates when the
 
128
         * IP address changes.
 
129
         * Register a callback for successful LDAP
 
130
         * reconnections. This is the easiest way to
 
131
         * identify that we have gone online.
 
132
         */
 
133
 
 
134
        /* Ensure that nsupdate exists */
 
135
        errno = 0;
 
136
        ret = stat(NSUPDATE_PATH, &stat_buf);
 
137
        if (ret == -1) {
 
138
            err = errno;
 
139
            if (err == ENOENT) {
 
140
                DEBUG(0, ("%s does not exist. Dynamic DNS updates disabled\n",
 
141
                          NSUPDATE_PATH));
 
142
            }
 
143
            else {
 
144
                DEBUG(0, ("Could not set up dynamic DNS updates: [%d][%s]\n",
 
145
                          err, strerror(err)));
 
146
            }
 
147
        }
 
148
        else {
 
149
            /* nsupdate is available. Dynamic updates
 
150
             * are supported
 
151
             */
 
152
            ret = be_add_online_cb(ctx, ctx->be,
 
153
                                   ipa_dyndns_update,
 
154
                                   ipa_options, NULL);
 
155
            if (ret != EOK) {
 
156
                DEBUG(1,("Failure setting up automatic DNS update\n"));
 
157
                /* We will continue without DNS updating */
 
158
            }
 
159
        }
 
160
    }
 
161
 
 
162
 
 
163
 
 
164
    ret = setup_tls_config(ctx->opts->basic);
 
165
    if (ret != EOK) {
 
166
        DEBUG(1, ("setup_tls_config failed [%d][%s].\n",
 
167
                  ret, strerror(ret)));
 
168
        goto done;
 
169
    }
 
170
 
 
171
    ret = sdap_id_conn_cache_create(ctx, ctx, &ctx->conn_cache);
 
172
    if (ret != EOK) {
 
173
        goto done;
 
174
    }
 
175
 
 
176
    ret = sdap_id_setup_tasks(ctx);
 
177
    if (ret != EOK) {
 
178
        goto done;
 
179
    }
 
180
 
 
181
    ret = setup_child(ctx);
 
182
    if (ret != EOK) {
 
183
        DEBUG(1, ("setup_child failed [%d][%s].\n",
 
184
                  ret, strerror(ret)));
 
185
        goto done;
 
186
    }
 
187
 
 
188
    *ops = &ipa_id_ops;
 
189
    *pvt_data = ctx;
 
190
    ret = EOK;
 
191
 
 
192
done:
 
193
    if (ret != EOK) {
 
194
        talloc_zfree(ipa_options->id_ctx);
 
195
    }
 
196
    return ret;
 
197
}
 
198
 
 
199
int sssm_ipa_auth_init(struct be_ctx *bectx,
 
200
                       struct bet_ops **ops,
 
201
                       void **pvt_data)
 
202
{
 
203
    struct ipa_auth_ctx *ipa_auth_ctx;
 
204
    struct krb5_ctx *krb5_auth_ctx;
 
205
    struct sdap_auth_ctx *sdap_auth_ctx;
 
206
    FILE *debug_filep;
 
207
    unsigned v;
 
208
    int ret;
 
209
 
 
210
    if (!ipa_options) {
 
211
        ret = common_ipa_init(bectx);
 
212
        if (ret != EOK) {
 
213
            return ret;
 
214
        }
 
215
    }
 
216
 
 
217
    if (ipa_options->auth_ctx) {
 
218
        /* already initialized */
 
219
        *ops = &ipa_auth_ops;
 
220
        *pvt_data = ipa_options->auth_ctx;
 
221
        return EOK;
 
222
    }
 
223
 
 
224
    ipa_auth_ctx = talloc_zero(ipa_options, struct ipa_auth_ctx);
 
225
    if (!ipa_auth_ctx) {
 
226
        return ENOMEM;
 
227
    }
 
228
    ipa_options->auth_ctx = ipa_auth_ctx;
 
229
 
 
230
    ret = dp_copy_options(ipa_auth_ctx, ipa_options->basic,
 
231
                          IPA_OPTS_BASIC, &ipa_auth_ctx->ipa_options);
 
232
    if (ret != EOK) {
 
233
        DEBUG(1, ("dp_copy_options failed.\n"));
 
234
        goto done;
 
235
    }
 
236
 
 
237
    krb5_auth_ctx = talloc_zero(ipa_auth_ctx, struct krb5_ctx);
 
238
    if (!krb5_auth_ctx) {
 
239
        ret = ENOMEM;
 
240
        goto done;
 
241
    }
 
242
    krb5_auth_ctx->service = ipa_options->service->krb5_service;
 
243
    ipa_options->auth_ctx->krb5_auth_ctx = krb5_auth_ctx;
 
244
 
 
245
    ret = ipa_get_auth_options(ipa_options, bectx->cdb, bectx->conf_path,
 
246
                               &krb5_auth_ctx->opts);
 
247
    if (ret != EOK) {
 
248
        goto done;
 
249
    }
 
250
 
 
251
    sdap_auth_ctx = talloc_zero(ipa_auth_ctx, struct sdap_auth_ctx);
 
252
    if (!sdap_auth_ctx) {
 
253
        ret = ENOMEM;
 
254
        goto done;
 
255
    }
 
256
    sdap_auth_ctx->be =  bectx;
 
257
    sdap_auth_ctx->service = ipa_options->service->sdap;
 
258
    ipa_options->auth_ctx->sdap_auth_ctx = sdap_auth_ctx;
 
259
 
 
260
    ret = ipa_get_id_options(ipa_options, bectx->cdb, bectx->conf_path,
 
261
                             &sdap_auth_ctx->opts);
 
262
    if (ret != EOK) {
 
263
        goto done;
 
264
    }
 
265
 
 
266
    ret = setup_tls_config(sdap_auth_ctx->opts->basic);
 
267
    if (ret != EOK) {
 
268
        DEBUG(1, ("setup_tls_config failed [%d][%s].\n",
 
269
                  ret, strerror(ret)));
 
270
        goto done;
 
271
    }
 
272
 
 
273
    if (dp_opt_get_bool(krb5_auth_ctx->opts, KRB5_STORE_PASSWORD_IF_OFFLINE)) {
 
274
        ret = init_delayed_online_authentication(krb5_auth_ctx, bectx,
 
275
                                                 bectx->ev);
 
276
        if (ret != EOK) {
 
277
            DEBUG(1, ("init_delayed_online_authentication failed.\n"));
 
278
            goto done;
 
279
        }
 
280
    }
 
281
 
 
282
    ret = check_and_export_options(krb5_auth_ctx->opts, bectx->domain,
 
283
                                   krb5_auth_ctx);
 
284
    if (ret != EOK) {
 
285
        DEBUG(1, ("check_and_export_opts failed.\n"));
 
286
        goto done;
 
287
    }
 
288
 
 
289
    ret = krb5_install_offline_callback(bectx, krb5_auth_ctx);
 
290
    if (ret != EOK) {
 
291
        DEBUG(1, ("krb5_install_offline_callback failed.\n"));
 
292
        goto done;
 
293
    }
 
294
 
 
295
    ret = krb5_install_sigterm_handler(bectx->ev, krb5_auth_ctx);
 
296
    if (ret != EOK) {
 
297
        DEBUG(1, ("krb5_install_sigterm_handler failed.\n"));
 
298
        goto done;
 
299
    }
 
300
 
 
301
    if (debug_to_file != 0) {
 
302
        ret = open_debug_file_ex("krb5_child", &debug_filep);
 
303
        if (ret != EOK) {
 
304
            DEBUG(0, ("Error setting up logging (%d) [%s]\n",
 
305
                    ret, strerror(ret)));
 
306
            goto done;
 
307
        }
 
308
 
 
309
        krb5_auth_ctx->child_debug_fd = fileno(debug_filep);
 
310
        if (krb5_auth_ctx->child_debug_fd == -1) {
 
311
            DEBUG(0, ("fileno failed [%d][%s]\n", errno, strerror(errno)));
 
312
            ret = errno;
 
313
            goto done;
 
314
        }
 
315
 
 
316
        v = fcntl(krb5_auth_ctx->child_debug_fd, F_GETFD, 0);
 
317
        fcntl(krb5_auth_ctx->child_debug_fd, F_SETFD, v & ~FD_CLOEXEC);
 
318
    }
 
319
 
 
320
    *ops = &ipa_auth_ops;
 
321
    *pvt_data = ipa_auth_ctx;
 
322
    ret = EOK;
 
323
 
 
324
done:
 
325
    if (ret != EOK) {
 
326
        talloc_zfree(ipa_options->auth_ctx);
 
327
    }
 
328
    return ret;
 
329
}
 
330
 
 
331
int sssm_ipa_chpass_init(struct be_ctx *bectx,
 
332
                         struct bet_ops **ops,
 
333
                         void **pvt_data)
 
334
{
 
335
    int ret;
 
336
    ret = sssm_ipa_auth_init(bectx, ops, pvt_data);
 
337
    *ops = &ipa_chpass_ops;
 
338
    return ret;
 
339
}
 
340
 
 
341
int sssm_ipa_access_init(struct be_ctx *bectx,
 
342
                         struct bet_ops **ops,
 
343
                         void **pvt_data)
 
344
{
 
345
    int ret;
 
346
    struct ipa_access_ctx *ipa_access_ctx;
 
347
 
 
348
    ipa_access_ctx = talloc_zero(bectx, struct ipa_access_ctx);
 
349
    if (ipa_access_ctx == NULL) {
 
350
        DEBUG(1, ("talloc_zero failed.\n"));
 
351
        return ENOMEM;
 
352
    }
 
353
 
 
354
    ret = sssm_ipa_id_init(bectx, ops, (void **) &ipa_access_ctx->sdap_ctx);
 
355
    if (ret != EOK) {
 
356
        DEBUG(1, ("sssm_ipa_id_init failed.\n"));
 
357
        goto done;
 
358
    }
 
359
 
 
360
    ret = dp_copy_options(ipa_access_ctx, ipa_options->basic,
 
361
                          IPA_OPTS_BASIC, &ipa_access_ctx->ipa_options);
 
362
    if (ret != EOK) {
 
363
        DEBUG(1, ("dp_copy_options failed.\n"));
 
364
        goto done;
 
365
    }
 
366
 
 
367
    *ops = &ipa_access_ops;
 
368
    *pvt_data = ipa_access_ctx;
 
369
 
 
370
done:
 
371
    if (ret != EOK) {
 
372
        talloc_free(ipa_access_ctx);
 
373
    }
 
374
    return ret;
 
375
}