File: ipa_ldap.c

package info (click to toggle)
freeipa 4.12.4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 100,668 kB
  • sloc: python: 298,952; javascript: 71,606; ansic: 49,369; sh: 6,547; makefile: 2,553; xml: 343; sed: 16
file content (161 lines) | stat: -rw-r--r-- 5,211 bytes parent folder | download | duplicates (3)
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
/* Authors: Christian Heimes <cheimes@redhat.com>
 *          Simo Sorce <ssorce@redhat.com>
 *
 * Copyright (C) 2018  Red Hat
 * see file 'COPYING' for use and warranty information
 *
 * 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/>.
 */

#define _GNU_SOURCE

#include <stdio.h>

#include "ipa_ldap.h"


/** Print LDAP error message to stderr
 *
 * The help function prints custom error message, LDAP error string,
 * diagnostic message (if available) to stderr.
 *
 * @param ld      LDAP connection
 * @param errnum  error code from LDAP operation
 * @param msg     Additional custom error message (must include trailing
 *                new line)
 */
void ipa_ldap_error(LDAP *ld, int errnum, char *msg)
{
    const char *errstring;
    char *diagnostic = NULL;
    int ret = 0;
    int has_diagnostic = 0;

    /* print custom message msg first. All msg strings have trailing newline
     */
    fprintf(stderr, "%s", msg);

    /* Get human readable error string and diagnostic message */
    errstring = ldap_err2string(errnum);
    ret = ldap_get_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&diagnostic);
    has_diagnostic = ((ret == LDAP_SUCCESS) && diagnostic && *diagnostic);

    if (errstring && has_diagnostic) {
        fprintf(stderr, "    %s: %s\n", errstring, diagnostic);
    } else if (errstring) {
        fprintf(stderr, "    %s\n", errstring);
    } else if (has_diagnostic) {
        fprintf(stderr, "    %i: %s\n", errnum, diagnostic);
    }
    /* else no additional error message */
}

/** Initialize LDAP context
 *
 * Initializes an LDAP context for a given LDAP URI. LDAP protocol version
 * and SASL canonization are disabled.
 *
 */
int ipa_ldap_init(LDAP **ld, const char *ldap_uri)
{
    int ret = 0;
    int version = LDAP_VERSION3;
    ret = ldap_initialize(ld, ldap_uri);

    if (ret != LDAP_SUCCESS) {
        fprintf(
            stderr,
            _("Unable to initialize connection to ldap server %1$s: %2$s\n"),
            ldap_uri,
            ldap_err2string(ret)
        );
        return ret;
    }

    /* StartTLS and other features need LDAP protocol version 3 */
    ret = ldap_set_option(*ld, LDAP_OPT_PROTOCOL_VERSION, &version);
    if (ret != LDAP_SUCCESS) {
        ipa_ldap_error(*ld, ret, _("Unable to set LDAP_OPT_PROTOCOL_VERSION\n")
        );
    }

#ifdef LDAP_OPT_X_SASL_NOCANON
    /* Don't do DNS canonization */
    ret = ldap_set_option(*ld, LDAP_OPT_X_SASL_NOCANON, LDAP_OPT_ON);
    if (ret != LDAP_SUCCESS) {
        ipa_ldap_error(*ld, ret, _("Unable to set LDAP_OPT_X_SASL_NOCANON\n"));
        return ret;
    }
#endif

    return ret;
}

/** Configure TLS/SSL and perform StartTLS for ldap://
 *
 * The LDAP connection is configured for secure TLS.
 *
 */
int ipa_tls_ssl_init(LDAP *ld, const char *ldap_uri,
                     const char *ca_cert_file)
{
    int ret = LDAP_SUCCESS;
    int tls_demand = LDAP_OPT_X_TLS_DEMAND;
    int tlsv1_0 = LDAP_OPT_X_TLS_PROTOCOL_TLS1_0;
    int newctx = 0;  /* client context */

    if (strncmp(ldap_uri, SCHEMA_LDAPI, sizeof(SCHEMA_LDAPI) - 1) == 0) {
        /* Nothing to do for LDAPI */
        return ret;
    }

    ret = ldap_set_option(ld, LDAP_OPT_X_TLS_CACERTFILE, ca_cert_file);
    if (ret != LDAP_OPT_SUCCESS) {
        ipa_ldap_error(ld, ret,
                       _("Unable to set LDAP_OPT_X_TLS_CACERTFILE\n"));
        return ret;
    }
    /* Require a valid certificate */
    ret = ldap_set_option(ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &tls_demand);
    if (ret != LDAP_OPT_SUCCESS) {
        ipa_ldap_error(ld, ret,
                       _("Unable to set LDAP_OPT_X_TLS_REQUIRE_CERT\n"));
        return ret;
    }
    /* Disable SSLv2 and SSLv3 */
    ret = ldap_set_option(ld, LDAP_OPT_X_TLS_PROTOCOL_MIN, &tlsv1_0);
    if (ret != LDAP_OPT_SUCCESS) {
        ipa_ldap_error(ld, ret,
                       _("Unable to set LDAP_OPT_X_TLS_PROTOCOL_MIN\n"));
        return ret;
    }
    /* Apply TLS settings and create new client context */
    ret = ldap_set_option(ld, LDAP_OPT_X_TLS_NEWCTX, &newctx);
    if (ret != LDAP_OPT_SUCCESS) {
        ipa_ldap_error(ld, ret,
                       _("Unable to create new TLS context (OpenSSL failed "
                         "to initialize or to load certificates)\n"));
        return ret;
    }

    if (strncmp(ldap_uri, SCHEMA_LDAP, sizeof(SCHEMA_LDAP) - 1) == 0) {
        ret = ldap_start_tls_s(ld, NULL, NULL);
        if (ret != LDAP_SUCCESS) {
            ipa_ldap_error(ld, ret,
                           _("Unable to initialize STARTTLS session\n"));
            return ret;
        }
    }
    return ret;
}