2 * This program 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
5 * (at your option) any later version.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 * connection management : if an user has no connection, a new one is created
19 * and the binding is done with its dn and userPassword.
20 * then the connection is added in the local hashtable
21 * a monitor thread checks the connections which are older than 10s and
22 * deletes them. that mainly permits to make the authentication
23 * process (4 requests) with the same LDAP connection.
32 #include <v2l_config.h>
34 /* linked list of all currently active LDAP connections */
35 static xht global_conn_list
= NULL
;
37 /* unbind and free the connection owned by user */
38 static void v2l_free_conn (xht h
, const char *user
, void *val
);
39 /* add a connection to the hashtable */
40 static void v2l_add_conn (v2l_LdapConn
* ldap_conn
);
41 /* walker function used to unbind and free all the LDAP connections */
42 static void v2l_free_callback (xht h
, const char *key
, void *val
,
44 /* walker function used to unbind and free an expired connection */
45 static void v2l_free_expired (xht h
, const char *key
, void *val
,
47 /* periodic function which expunge expired functions */
48 static void v2l_check_func (void *arg
);
51 v2l_create_conn (char *host
, int port
, const char *binddn
,
52 const char *user
, const char *passwd
, int add_in_list
)
55 v2l_LdapConn
*ldap_conn
;
56 int version
; /* LDAP protocol version */
61 if ((ld
= ldap_init (host
, port
)) == NULL
)
63 log_error (ZONE
, "[v2l_create_conn] unable to init LDAP");
67 /* Set the LDAP protocol version supported by the client
68 * to 3. (By default, this is set to 2. SASL authentication
69 * is part of version 3 of the LDAP protocol.) */
70 version
= LDAP_VERSION3
;
71 ldap_set_option (ld
, LDAP_OPT_PROTOCOL_VERSION
, &version
);
73 /* Bind to the LDAP server. */
75 if ((rc
= ldap_simple_bind_s (ld
, binddn
, passwd
)) != LDAP_SUCCESS
)
78 "[v2l_create_conn] error : %s", ldap_err2string (rc
));
82 /* Add it in the main list */
84 ldap_conn
= pmalloc (p
, sizeof (v2l_LdapConn
));
89 pmalloc (ldap_conn
->p
, sizeof (char) * (strlen (binddn
) + 1));
90 strcpy (ldap_conn
->binddn
, binddn
);
92 tmp_str
= (char *) malloc (sizeof (char) * (strlen (binddn
) + 1));
93 strcpy (tmp_str
, binddn
);
94 ptr
= strtok (tmp_str
, ", ");
97 pmalloc (ldap_conn
->p
, sizeof (char) * (strlen (tmp_str
) + 1));
98 strcpy (ldap_conn
->entry
, tmp_str
);
101 pmalloc (ldap_conn
->p
, sizeof (char) * (strlen (user
) + 1));
102 strcpy (ldap_conn
->user
, user
);
104 ldap_conn
->creation_time
= time (NULL
);
105 ldap_conn
->exists
= 1;
107 if (add_in_list
== 1)
108 v2l_add_conn (ldap_conn
);
114 int v2l_ldap_wait_result(void *arg
)
116 v2l_LdapEvt
*evt_res
= (v2l_LdapEvt
*) arg
;
120 rc
= ldap_result (evt_res
->ld
, evt_res
->msgid
, 1, NULL
, &result
);
124 log_error(ZONE
, "[v2l_wait_result] result error %d",
125 ldap_err2string(rc
));
126 evt_res
->result
= NULL
;
131 if ((rc
== LDAP_RES_ADD
)
132 || (rc
== LDAP_RES_MODIFY
)
133 || (rc
== LDAP_RES_SEARCH_RESULT
)
134 || (rc
== LDAP_RES_SEARCH_ENTRY
)
135 || (rc
== LDAP_RES_DELETE
))
137 evt_res
->result
= result
;
142 return 0; /* still waiting */
146 v2l_get_conn (const char *user
)
148 return (v2l_LdapConn
*) xhash_get (global_conn_list
, user
);
151 /* get user password from LDAP */
152 /* caller must free the returned string */
153 char *v2l_ldap_get_passwd(v2l_Config
*self
, char *user
)
155 LDAPMessage
*e
; /* pointer to LDAP result */
156 v2l_LdapEvt
*evt_res
;
159 char *data
, *filter
, **vals
, *attrs
[2] = {"userPassword", NULL
};
161 /* to wait for the results */
162 evt_res
= (v2l_LdapEvt
*) malloc(sizeof(v2l_LdapEvt
));
166 log_error(ZONE
, "[v2l_ldap_get_passwd] unable to allocate memory");
170 filter
= (char *) malloc (sizeof(char)*
171 (strlen(self
->uniqattr
) + strlen(user
) + 2));
175 log_error(ZONE
, "[v2l_ldap_get_passwd] unable to allocate memory");
180 sprintf(filter
, "%s=%s", self
->uniqattr
, user
);
181 evt_res
->ld
= self
->master_conn
->ld
;
183 /* Search for the entry. */
184 evt_res
->rc
= ldap_search_ext(evt_res
->ld
, self
->suffix
,
185 LDAP_SCOPE_ONELEVEL
, filter
, attrs
, 0, NULL
, NULL
, NULL
,
186 LDAP_NO_LIMIT
, &(evt_res
->msgid
));
190 if (evt_res
->rc
!= LDAP_SUCCESS
)
193 "[v2l_ldap_get_passwd] search error : %s", ldap_err2string(rc
));
198 /* wait for the operation to be terminated, poll every second */
199 evt
= pth_event(PTH_EVENT_FUNC
, &v2l_ldap_wait_result
, (void *) evt_res
,
205 if (ldap_count_entries(evt_res
->ld
, evt_res
->result
) == 1)
207 e
= ldap_first_entry(evt_res
->ld
, evt_res
->result
);
208 vals
= ldap_get_values(evt_res
->ld
, e
, "userPassword");
212 log_debug(ZONE
, "[v2l_ldap_get_passwd] user has no password !");
213 data
= (char *) malloc(sizeof(char));
217 ldap_msgfree(evt_res
->result
);
225 /* build the result set */
226 data
= (char *) malloc(sizeof(char) * (strlen(vals
[0]) + 1));
230 strcpy(data
, vals
[0]);
233 ldap_value_free(vals
);
236 ldap_msgfree(evt_res
->result
);
239 /* log_debug(ZONE, "[v2l_ldap_get_passwd] user does not exist");
240 * log_warn(ZONE, "[v2l_ldap_get_passwd] more than one user found");
249 xhash_walk (global_conn_list
, v2l_free_callback
, NULL
);
250 xhash_free (global_conn_list
);
253 /***********************/
254 /* public api ends here */
257 v2l_free_callback (xht h
, const char *key
, void *val
, void *arg
)
259 v2l_free_conn (h
, key
, val
);
263 v2l_free_conn (xht h
, const char *user
, void *val
)
265 v2l_LdapConn
*temp_conn
= (v2l_LdapConn
*) val
;
267 log_debug (ZONE
, "[v2l_free_conn] freeing %s LDAP connection", user
);
270 ldap_unbind (temp_conn
->ld
);
271 pool_free (temp_conn
->p
);
275 v2l_free_expired (xht h
, const char *key
, void *val
, void *arg
)
277 v2l_LdapConn
*temp_conn
= (v2l_LdapConn
*) val
;
279 /* kill connections older than 10s */
280 if ((time (NULL
) - temp_conn
->creation_time
) > (time_t) 50)
282 v2l_free_conn (h
, key
, val
);
287 v2l_check_func (void *arg
)
290 "[v2l_check_func] monitor thread enters its main loop");
294 /* special case : when it is called and xdb_ldap is shutting down
295 * and that global_conn_list has already been deallocated
296 * added by BO, 2001/08/31
298 if (global_conn_list
!= NULL
)
300 xhash_walk (global_conn_list
, v2l_free_expired
, NULL
);
307 v2l_add_conn (v2l_LdapConn
* ldap_conn
)
311 if (global_conn_list
== NULL
)
314 log_debug (ZONE
, "[v2l_add_conn] no existing hashtable for conns");
316 global_conn_list
= xhash_new (509);
318 /* spawn the thread which deletes expired connections */
319 attr
= pth_attr_new ();
320 pth_attr_set (attr
, PTH_ATTR_JOINABLE
, FALSE
);
321 pth_spawn (attr
, (void *) v2l_check_func
, NULL
);
322 pth_attr_destroy (attr
);
325 xhash_put (global_conn_list
, ldap_conn
->user
, (void *) ldap_conn
);