00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00033 #include "ld_con.h"
00034 #include "ld_uri.h"
00035
00036 #include "../../mem/mem.h"
00037 #include "../../dprint.h"
00038 #include "../../ut.h"
00039
00040 #include <ldap.h>
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #include <sasl/sasl.h>
00044
00051 static void ld_con_free(db_con_t* con, struct ld_con* payload)
00052 {
00053 struct ld_uri* luri;
00054 int ret;
00055 if (!payload) return;
00056
00057 luri = DB_GET_PAYLOAD(con->uri);
00058
00059
00060
00061
00062 if (db_pool_remove((db_pool_entry_t*)payload) == 0) return;
00063
00064 db_pool_entry_free(&payload->gen);
00065 if (payload->con) {
00066 ret = ldap_unbind_ext_s(payload->con, NULL, NULL);
00067 if (ret != LDAP_SUCCESS) {
00068 ERR("ldap: Error while unbinding from %s: %s\n",
00069 luri->uri, ldap_err2string(ret));
00070 }
00071 }
00072 pkg_free(payload);
00073 }
00074
00075
00076 int ld_con(db_con_t* con)
00077 {
00078 struct ld_con* lcon;
00079 struct ld_uri* luri;
00080
00081 luri = DB_GET_PAYLOAD(con->uri);
00082
00083
00084
00085
00086 lcon = (struct ld_con*)db_pool_get(con->uri);
00087 if (lcon) {
00088 DBG("ldap: Connection to %s found in connection pool\n",
00089 luri->uri);
00090 goto found;
00091 }
00092
00093 lcon = (struct ld_con*)pkg_malloc(sizeof(struct ld_con));
00094 if (!lcon) {
00095 ERR("ldap: No memory left\n");
00096 goto error;
00097 }
00098 memset(lcon, '\0', sizeof(struct ld_con));
00099 if (db_pool_entry_init(&lcon->gen, ld_con_free, con->uri) < 0) goto error;
00100
00101 DBG("ldap: Preparing new connection to %s\n", luri->uri);
00102
00103
00104 db_pool_put((struct db_pool_entry*)lcon);
00105 DBG("ldap: Connection stored in connection pool\n");
00106
00107 found:
00108
00109
00110
00111 DB_SET_PAYLOAD(con, lcon);
00112 con->connect = ld_con_connect;
00113 con->disconnect = ld_con_disconnect;
00114 return 0;
00115
00116 error:
00117 if (lcon) {
00118 db_pool_entry_free(&lcon->gen);
00119 pkg_free(lcon);
00120 }
00121 return -1;
00122 }
00123
00124
00125 int lutil_sasl_interact(
00126 LDAP *ld,
00127 unsigned flags,
00128 void *defaults,
00129 void *in )
00130 {
00131 sasl_interact_t *interact = in;
00132 const char *dflt = interact->defresult;
00133
00134
00135 if (ld == NULL)
00136 return LDAP_PARAM_ERROR;
00137
00138 while (interact->id != SASL_CB_LIST_END) {
00139 switch( interact->id ) {
00140
00141 case SASL_CB_AUTHNAME:
00142 if (defaults)
00143 dflt = ((struct ld_uri*)defaults)->username;
00144 break;
00145
00146 case SASL_CB_PASS:
00147 if (defaults)
00148 dflt = ((struct ld_uri*)defaults)->password;
00149 break;
00150
00151 case SASL_CB_GETREALM:
00152
00153 case SASL_CB_USER:
00154
00155 case SASL_CB_NOECHOPROMPT:
00156
00157 case SASL_CB_ECHOPROMPT:
00158 break;
00159 }
00160
00161 interact->result = (dflt && *dflt) ? dflt : "";
00162 interact->len = strlen(interact->result);
00163
00164 interact++;
00165 }
00166
00167 return LDAP_SUCCESS;
00168 }
00169
00170
00171 int ld_con_connect(db_con_t* con)
00172 {
00173 struct ld_con* lcon;
00174 struct ld_uri* luri;
00175 int ret, version = 3;
00176 char* err_str = NULL;
00177
00178 lcon = DB_GET_PAYLOAD(con);
00179 luri = DB_GET_PAYLOAD(con->uri);
00180
00181
00182 if (lcon->flags & LD_CONNECTED) return 0;
00183
00184 DBG("ldap: Connecting to %s\n", luri->uri);
00185
00186 if (lcon->con) {
00187 ret = ldap_unbind_ext_s(lcon->con, NULL, NULL);
00188 if (ret != LDAP_SUCCESS) {
00189 ERR("ldap: Error while unbinding from %s: %s\n",
00190 luri->uri, ldap_err2string(ret));
00191 }
00192 }
00193
00194
00195
00196 if (luri->tls) {
00197 if (setenv("LDAPTLS_CACERT", luri->ca_list, 1)) {
00198 ERR("ldap: Can't set environment variable 'LDAPTLS_CACERT'\n");
00199 goto error;
00200 }
00201 if (setenv("LDAPTLS_REQCERT", luri->req_cert, 1)) {
00202 ERR("ldap: Can't set environment variable 'LDAPTLS_REQCERT'\n");
00203 goto error;
00204 }
00205 }
00206
00207 ret = ldap_initialize(&lcon->con, luri->uri);
00208 if (lcon->con == NULL) {
00209 ERR("ldap: Error while initializing new LDAP connection to %s\n",
00210 luri->uri);
00211 goto error;
00212 }
00213
00214 ret = ldap_set_option(lcon->con, LDAP_OPT_PROTOCOL_VERSION, &version);
00215 if (ret != LDAP_OPT_SUCCESS) {
00216 ERR("ldap: Error while setting protocol version 3: %s\n",
00217 ldap_err2string(ret));
00218 goto error;
00219 }
00220
00221 if (luri->tls) {
00222 ret = ldap_start_tls_s(lcon->con, NULL, NULL);
00223 if (ret != LDAP_SUCCESS) {
00224
00225 #ifdef OPENLDAP23
00226 ldap_get_option(lcon->con, LDAP_OPT_ERROR_STRING, &err_str);
00227 #elif OPENLDAP24
00228 ldap_get_option(lcon->con, LDAP_OPT_DIAGNOSTIC_MESSAGE, &err_str);
00229 #endif
00230 ERR("ldap: Error while starting TLS: %s\n", ldap_err2string(ret));
00231 if (err_str) {
00232 ERR("ldap: %s\n", err_str);
00233 ldap_memfree(err_str);
00234 }
00235 goto error;
00236 }
00237 }
00238
00239 switch (luri->authmech) {
00240 case LDAP_AUTHMECH_NONE:
00241 ret = ldap_simple_bind_s(lcon->con, NULL, NULL);
00242 break;
00243 case LDAP_AUTHMECH_SIMPLE:
00244 ret = ldap_simple_bind_s(lcon->con, luri->username, luri->password);
00245 break;
00246 case LDAP_AUTHMECH_DIGESTMD5:
00247 ret = ldap_sasl_interactive_bind_s( lcon->con, NULL,
00248 LDAP_MECHANISM_STR_DIGESTMD5, NULL, NULL,
00249 0, lutil_sasl_interact, luri );
00250 break;
00251 case LDAP_AUTHMECH_EXTERNAL:
00252 default:
00253 ret = !LDAP_SUCCESS;
00254 break;
00255 }
00256
00257 if (ret != LDAP_SUCCESS) {
00258 ERR("ldap: Bind to %s failed: %s\n",
00259 luri->uri, ldap_err2string(ret));
00260 goto error;
00261 }
00262
00263 DBG("ldap: Successfully bound to %s\n", luri->uri);
00264 lcon->flags |= LD_CONNECTED;
00265 return 0;
00266
00267 error:
00268 if (lcon->con) {
00269 ret = ldap_unbind_ext_s(lcon->con, NULL, NULL);
00270 if (ret) {
00271 ERR("ldap: Error while unbinding from %s: %s\n",
00272 luri->uri, ldap_err2string(ret));
00273 }
00274 }
00275 lcon->con = NULL;
00276 return -1;
00277 }
00278
00279
00280 void ld_con_disconnect(db_con_t* con)
00281 {
00282 struct ld_con* lcon;
00283 struct ld_uri* luri;
00284 int ret;
00285
00286 lcon = DB_GET_PAYLOAD(con);
00287 luri = DB_GET_PAYLOAD(con->uri);
00288
00289 if ((lcon->flags & LD_CONNECTED) == 0) return;
00290
00291 DBG("ldap: Unbinding from %s\n", luri->uri);
00292
00293 if (lcon->con) {
00294 ret = ldap_unbind_ext_s(lcon->con, NULL, NULL);
00295 if (ret) {
00296 ERR("ldap: Error while unbinding from %s: %s\n",
00297 luri->uri, ldap_err2string(ret));
00298 }
00299 }
00300
00301 lcon->con = NULL;
00302 lcon->flags &= ~LD_CONNECTED;
00303 }
00304
00305