The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
state.c
Go to the documentation of this file.
1 /*
2  * This program is is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or (at
5  * your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: 9f91571b54eac96b575d5c003896badaaa882337 $
19  * @file lib/ldap/start_tls.c
20  * @brief Start TLS asynchronously
21  *
22  * @copyright 2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23  */
24 RCSID("$Id: 9f91571b54eac96b575d5c003896badaaa882337 $")
25 
27 
28 #include <freeradius-devel/ldap/base.h>
29 
30 #define STATE_TRANSITION(_new) \
31 do { \
32  DEBUG4("Changed state %s -> %s", \
33  fr_table_str_by_value(fr_ldap_connection_states, c->state, "<INVALID>"), \
34  fr_table_str_by_value(fr_ldap_connection_states, _new, "<INVALID>")); \
35  c->state = _new; \
36 } while (0)
37 
38 /** Move between LDAP connection states
39  *
40  * Bringing up an LDAP connection is quite complex, as we need to do multiple operations
41  * before we can install the main mux/demux functions which do the work of sending
42  * requests to the directory and processing the responses.
43  *
44  * This function moves the connection through different states, setting different I/O
45  * handlers.
46  *
47  * If any of the states
48  */
50 {
51 again:
52  switch (c->state) {
53  /*
54  * Start by negotiating TLS, or binding
55  */
56  case FR_LDAP_STATE_INIT:
57  if (c->config->start_tls) {
58  if (fr_ldap_start_tls_async(c, NULL, NULL) < 0) {
60  goto again;
61  }
63  break;
64  }
66 
67  /*
68  * If we're successful in negotiating TLS,
69  * bind to the server as the credentials
70  * will now be protected.
71  */
74 
75  /*
76  * SASL uses a different (and more complex) codepath
77  */
78 #ifdef WITH_SASL
79  if (c->config->admin_sasl.mech) {
86  NULL, NULL) < 0) {
88  goto again;
89  }
90  break;
91  }
92 #endif
93 
94  /*
95  * Normal binds are just a simple request/response pair
96  */
97  if (fr_ldap_bind_async(c,
100  NULL, NULL) < 0) {
102  goto again;
103  }
104  break;
105 
106  /*
107  * After binding install the mux (write) and
108  * demux (read) I/O functions.
109  */
110  case FR_LDAP_STATE_BIND:
113  break;
114 
115  /*
116  * Something went wrong
117  */
118  case FR_LDAP_STATE_RUN: /* There's no next state for run, so this an error */
119  case FR_LDAP_STATE_ERROR:
122  /*
123  * The old connection has been freed, so specifically return the INIT state
124  */
125  return FR_LDAP_STATE_INIT;
126  }
127 
128  return c->state;
129 }
130 
131 /** Signal that there's been an error on the connection
132  *
133  */
135 {
138 }
139 
#define USES_APPLE_DEPRECATED_API
Definition: build.h:431
#define RCSID(id)
Definition: build.h:444
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition: build.h:320
@ FR_CONNECTION_FAILED
Connection is being reconnected because it failed.
Definition: connection.h:84
char const * mech
SASL mech(s) to try.
Definition: base.h:129
char const * proxy
Identity to proxy.
Definition: base.h:130
char const * admin_password
Password used in administrative bind.
Definition: base.h:229
fr_ldap_state_t state
LDAP connection state machine.
Definition: base.h:345
char const * admin_identity
Identity we bind as when we need to query the LDAP directory.
Definition: base.h:227
int fr_ldap_bind_async(fr_ldap_connection_t *c, char const *bind_dn, char const *password, LDAPControl **serverctrls, LDAPControl **clientctrls)
Install I/O handlers for the bind operation.
Definition: bind.c:185
fr_connection_t * conn
Connection state handle.
Definition: base.h:343
fr_ldap_state_t
LDAP connection handle states.
Definition: base.h:166
@ FR_LDAP_STATE_ERROR
Connection is in an error state.
Definition: base.h:171
@ FR_LDAP_STATE_BIND
Connection is being bound.
Definition: base.h:169
@ FR_LDAP_STATE_START_TLS
TLS is being negotiated.
Definition: base.h:168
@ FR_LDAP_STATE_RUN
Connection is muxing/demuxing requests.
Definition: base.h:170
@ FR_LDAP_STATE_INIT
Connection uninitialised.
Definition: base.h:167
fr_ldap_config_t const * config
rlm_ldap connection configuration.
Definition: base.h:342
bool start_tls
Send the Start TLS message to the LDAP directory to start encrypted communications using the standard...
Definition: base.h:256
char const * realm
Kerberos realm.
Definition: base.h:131
fr_ldap_sasl_t admin_sasl
SASL parameters used when binding as the admin.
Definition: base.h:231
int fr_ldap_start_tls_async(fr_ldap_connection_t *c, LDAPControl **serverctrls, LDAPControl **clientctrls)
Install I/O handlers for Start TLS negotiation.
Definition: start_tls.c:222
Tracks the state of a libldap connection handle.
Definition: base.h:330
void fr_ldap_state_error(fr_ldap_connection_t *c)
Signal that there's been an error on the connection.
Definition: state.c:134
fr_ldap_state_t fr_ldap_state_next(fr_ldap_connection_t *c)
Move between LDAP connection states.
Definition: state.c:49
#define STATE_TRANSITION(_new)
Definition: state.c:30
int fr_ldap_sasl_bind_async(fr_ldap_connection_t *c, char const *mechs, char const *identity, char const *password, char const *proxy, char const *realm, LDAPControl **serverctrls, LDAPControl **clientctrls)
Install I/O handlers for the bind operation.
Definition: sasl.c:308
void fr_connection_signal_connected(fr_connection_t *conn)
Asynchronously signal that the connection is open.
Definition: connection.c:1136
void fr_connection_signal_reconnect(fr_connection_t *conn, fr_connection_reason_t reason)
Asynchronously signal the connection should be reconnected.
Definition: connection.c:1166