scalab01.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217
  1. #ident "ldclt @(#)scalab01.c 1.8 01/05/03"
  2. /** BEGIN COPYRIGHT BLOCK
  3. * This Program is free software; you can redistribute it and/or modify it under
  4. * the terms of the GNU General Public License as published by the Free Software
  5. * Foundation; version 2 of the License.
  6. *
  7. * This Program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  10. *
  11. * You should have received a copy of the GNU General Public License along with
  12. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  13. * Place, Suite 330, Boston, MA 02111-1307 USA.
  14. *
  15. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  16. * right to link the code of this Program with code not covered under the GNU
  17. * General Public License ("Non-GPL Code") and to distribute linked combinations
  18. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  19. * permitted under this exception must only link to the code of this Program
  20. * through those well defined interfaces identified in the file named EXCEPTION
  21. * found in the source code files (the "Approved Interfaces"). The files of
  22. * Non-GPL Code may instantiate templates or use macros or inline functions from
  23. * the Approved Interfaces without causing the resulting work to be covered by
  24. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  25. * additions to the list of Approved Interfaces. You must obey the GNU General
  26. * Public License in all respects for all of the Program code and other code used
  27. * in conjunction with the Program except the Non-GPL Code covered by this
  28. * exception. If you modify this file, you may extend this exception to your
  29. * version of the file, but you are not obligated to do so. If you do not wish to
  30. * provide this exception without modification, you must delete this exception
  31. * statement from your version and license this file solely under the GPL without
  32. * exception.
  33. *
  34. *
  35. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  36. * Copyright (C) 2006 Red Hat, Inc.
  37. * All rights reserved.
  38. * END COPYRIGHT BLOCK **/
  39. #ifdef HAVE_CONFIG_H
  40. # include <config.h>
  41. #endif
  42. /*
  43. FILE : scalab01.c
  44. AUTHOR : Jean-Luc SCHWING
  45. VERSION : 1.0
  46. DATE : 08 January 2001
  47. DESCRIPTION :
  48. This file contains the implmentation of the specific
  49. scenario scalab01 of ldclt.
  50. I implement this set of functions in a separate file to
  51. reduce the interconnection(s) between the main ldclt
  52. and the add-ons, keeping in mind the possibility to use
  53. a dynamic load of plugins for a future release.
  54. LOCAL : None.
  55. HISTORY :
  56. ---------+--------------+------------------------------------------------------
  57. dd/mm/yy | Author | Comments
  58. ---------+--------------+------------------------------------------------------
  59. 08/01/01 | JL Schwing | Creation
  60. ---------+--------------+------------------------------------------------------
  61. 12/01/01 | JL Schwing | 1.2 : Second set of options for -e scalab01
  62. ---------+--------------+------------------------------------------------------
  63. 29/01/01 | B Kolics | 1.3 : readAttrValue() uses filter of requested attr
  64. ---------+--------------+------------------------------------------------------
  65. 01/02/01 | JL Schwing | 1.4 : Protect against multiple choice of same user.
  66. ---------+--------------+------------------------------------------------------
  67. 26/02/01 | JL Schwing | 1.5 : Port on non-solaris platforms...
  68. ---------+--------------+------------------------------------------------------
  69. 14/03/01 | JL Schwing | 1.6 : Lint cleanup.
  70. | Bug fix : forget to set ldap protocol version.
  71. ---------+--------------+------------------------------------------------------
  72. 26/04/01 | B Kolics | 1.7 : in case of lock failure, thread is not aborted
  73. ---------+--------------+------------------------------------------------------
  74. 03/05/01 | B Kolics | 1.8 : bug fix - forget to release more line.
  75. ---------+--------------+------------------------------------------------------
  76. */
  77. #include <stdio.h> /* printf(), etc... */
  78. #include <stdlib.h> /* malloc(), etc... */
  79. #include <string.h> /* strcpy(), etc... */
  80. #include <errno.h> /* perror(), etc... */
  81. #ifndef _WIN32
  82. #include <pthread.h> /* pthreads(), etc... */
  83. #endif
  84. #include <lber.h> /* ldap C-API BER declarations */
  85. #include <ldap.h> /* ldap C-API declarations */
  86. #if !defined(USE_OPENLDAP)
  87. #include <ldap_ssl.h> /* ldapssl_init(), etc... */
  88. #endif
  89. #include <prprf.h>
  90. #include "port.h" /* Portability definitions */
  91. #include "ldclt.h" /* This tool's include file */
  92. #include "utils.h" /* Utilities functions */
  93. #include "scalab01.h" /* Scalab01 specific definitions */
  94. /*
  95. * Private data structures.
  96. */
  97. scalab01_context s1ctx;
  98. /* ****************************************************************************
  99. FUNCTION : scalab01_init
  100. PURPOSE : Initiates the scalab01 scenario.
  101. INPUT : None.
  102. OUTPUT : None.
  103. RETURN : -1 if error, 0 else.
  104. DESCRIPTION :
  105. *****************************************************************************/
  106. int
  107. scalab01_init (void)
  108. {
  109. int ret; /* Return value */
  110. s1ctx.nbcnx = 0; /* No connection yet */
  111. s1ctx.list = NULL; /* No record yet */
  112. s1ctx.lockingMax = 0; /* No locking yet */
  113. /*
  114. * Initiates mutexes
  115. */
  116. if ((ret = ldclt_mutex_init (&(s1ctx.list_mutex))) != 0)
  117. {
  118. fprintf (stderr, "ldclt[%d]: %s\n", mctx.pid, strerror (ret));
  119. fprintf (stderr, "ldclt[%d]: Error: cannot initiate s1ctx.list_mutex\n", mctx.pid);
  120. fflush (stderr);
  121. return (-1);
  122. }
  123. if ((ret = ldclt_mutex_init (&(s1ctx.locking_mutex))) != 0)
  124. {
  125. fprintf (stderr, "ldclt[%d]: %s\n", mctx.pid, strerror (ret));
  126. fprintf (stderr, "ldclt[%d]: Error: cannot initiate s1ctx.locking_mutex\n", mctx.pid);
  127. fflush (stderr);
  128. return (-1);
  129. }
  130. if ((ret = ldclt_mutex_init (&(s1ctx.nbcnx_mutex))) != 0)
  131. {
  132. fprintf (stderr, "ldclt[%d]: %s\n", mctx.pid, strerror (ret));
  133. fprintf (stderr, "ldclt[%d]: Error: cannot initiate s1ctx.nbcnx_mutex\n", mctx.pid);
  134. fflush (stderr);
  135. return (-1);
  136. }
  137. /*
  138. * No error
  139. */
  140. return (0);
  141. }
  142. /* ****************************************************************************
  143. FUNCTION : scalab01Lock
  144. PURPOSE : Lock for single user trying to connect.
  145. INPUT : tttctx = thread context.
  146. OUTPUT : None.
  147. RETURN : -1 if error, 0 cannot lock, 1 if could lock.
  148. DESCRIPTION :
  149. *****************************************************************************/
  150. int
  151. scalab01Lock (
  152. thread_context *tttctx)
  153. {
  154. int i; /* For the loop */
  155. int ret; /* Return code */
  156. int res; /* Result of this function */
  157. /*
  158. * Get secure access to the common data structure.
  159. */
  160. if ((ret = ldclt_mutex_lock (&(s1ctx.locking_mutex))) != 0)
  161. {
  162. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_lock(), error=%d (%s)\n",
  163. mctx.pid, tttctx->thrdId, ret, strerror (ret));
  164. fflush (stderr);
  165. return (-1);
  166. }
  167. /*
  168. * Is it locked ?
  169. */
  170. res = 1;
  171. for (i=0 ; i<s1ctx.lockingMax ; i++)
  172. if ((s1ctx.locking[i] != NULL) &&
  173. (!strcmp (s1ctx.locking[i], tttctx->bufBindDN)))
  174. {
  175. res = 0;
  176. break;
  177. }
  178. if (res == 1)
  179. {
  180. for (i=0 ; (i<s1ctx.lockingMax) && (s1ctx.locking[i] != NULL) ; i++);
  181. if (i == s1ctx.lockingMax)
  182. {
  183. if (s1ctx.lockingMax == SCALAB01_MAX_LOCKING)
  184. res = 0;
  185. else
  186. s1ctx.lockingMax++;
  187. }
  188. if (res != 0)
  189. s1ctx.locking[i] = tttctx->bufBindDN;
  190. }
  191. /*
  192. * Free mutex
  193. */
  194. if ((ret = ldclt_mutex_unlock (&(s1ctx.locking_mutex))) != 0)
  195. {
  196. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_unlock(), error=%d (%s)\n",
  197. mctx.pid, tttctx->thrdId, ret, strerror (ret));
  198. fflush (stderr);
  199. return (-1);
  200. }
  201. return (res);
  202. }
  203. /* ****************************************************************************
  204. FUNCTION : scalab01Unlock
  205. PURPOSE : Unlock for single user trying to connect.
  206. INPUT : tttctx = thread context.
  207. OUTPUT : None.
  208. RETURN : -1 if error, 0 else.
  209. DESCRIPTION :
  210. *****************************************************************************/
  211. int
  212. scalab01Unlock (
  213. thread_context *tttctx)
  214. {
  215. int i; /* For the loop */
  216. int ret; /* Return code */
  217. /*
  218. * Get secure access to the common data structure.
  219. */
  220. if ((ret = ldclt_mutex_lock (&(s1ctx.locking_mutex))) != 0)
  221. {
  222. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_lock(), error=%d (%s)\n",
  223. mctx.pid, tttctx->thrdId, ret, strerror (ret));
  224. fflush (stderr);
  225. return (-1);
  226. }
  227. /*
  228. * Find the entry and unlock it.
  229. */
  230. for (i=0 ; i<s1ctx.lockingMax ; i++)
  231. if ((s1ctx.locking[i] != NULL) &&
  232. (!strcmp (s1ctx.locking[i], tttctx->bufBindDN)))
  233. {
  234. s1ctx.locking[i] = NULL;
  235. break;
  236. }
  237. /*
  238. * Free mutex
  239. */
  240. if ((ret = ldclt_mutex_unlock (&(s1ctx.locking_mutex))) != 0)
  241. {
  242. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_unlock(), error=%d (%s)\n",
  243. mctx.pid, tttctx->thrdId, ret, strerror (ret));
  244. fflush (stderr);
  245. return (-1);
  246. }
  247. return (0);
  248. }
  249. /* ****************************************************************************
  250. FUNCTION : scalab01_modemIncr
  251. PURPOSE : Increments the modem nb of cnx
  252. INPUT : ident = thread identifier
  253. OUTPUT : None.
  254. RETURN : -1 if error
  255. 0 if no modem available
  256. 1 if modem available
  257. DESCRIPTION :
  258. *****************************************************************************/
  259. int
  260. scalab01_modemIncr (
  261. char *ident)
  262. {
  263. int ret; /* Return value */
  264. int res; /* Result of this function */
  265. /*
  266. * Get secure access to the common data structure.
  267. */
  268. if ((ret = ldclt_mutex_lock (&(s1ctx.nbcnx_mutex))) != 0)
  269. {
  270. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_lock(), error=%d (%s)\n",
  271. mctx.pid, ident, ret, strerror (ret));
  272. fflush (stderr);
  273. return (-1);
  274. }
  275. if (s1ctx.nbcnx >= s1ctx.maxcnxnb)
  276. res = 0;
  277. else
  278. {
  279. res = 1;
  280. s1ctx.nbcnx++;
  281. }
  282. /*
  283. * Free mutex
  284. */
  285. if ((ret = ldclt_mutex_unlock (&(s1ctx.nbcnx_mutex))) != 0)
  286. {
  287. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_unlock(), error=%d (%s)\n",
  288. mctx.pid, ident, ret, strerror (ret));
  289. fflush (stderr);
  290. return (-1);
  291. }
  292. return (res);
  293. }
  294. /* ****************************************************************************
  295. FUNCTION : scalab01_modemDecr
  296. PURPOSE : Decrements the modem nb of cnx
  297. INPUT : ident = thread identifier
  298. OUTPUT : None.
  299. RETURN : -1 if error, 0 else.
  300. DESCRIPTION :
  301. *****************************************************************************/
  302. int
  303. scalab01_modemDecr (
  304. char *ident)
  305. {
  306. int ret; /* Return value */
  307. /*
  308. * Get secure access to the common data structure.
  309. */
  310. if ((ret = ldclt_mutex_lock (&(s1ctx.nbcnx_mutex))) != 0)
  311. {
  312. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_lock(), error=%d (%s)\n",
  313. mctx.pid, ident, ret, strerror (ret));
  314. fflush (stderr);
  315. return (-1);
  316. }
  317. s1ctx.nbcnx--;
  318. /*
  319. * Free mutex
  320. */
  321. if ((ret = ldclt_mutex_unlock (&(s1ctx.nbcnx_mutex))) != 0)
  322. {
  323. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_unlock(), error=%d (%s)\n",
  324. mctx.pid, ident, ret, strerror (ret));
  325. fflush (stderr);
  326. return (-1);
  327. }
  328. return (0);
  329. }
  330. /* ****************************************************************************
  331. FUNCTION : scalab01_addLogin
  332. PURPOSE : Add a new user login to the s1ctx structure.
  333. INPUT : tttctx = thread context.
  334. dn = user's dn.
  335. duration = duration of the connection.
  336. OUTPUT : None.
  337. RETURN : -1 if error, 0 else.
  338. DESCRIPTION :
  339. *****************************************************************************/
  340. int
  341. scalab01_addLogin (
  342. thread_context *tttctx,
  343. char *dn,
  344. int duration)
  345. {
  346. int ret; /* Return value */
  347. isp_user *new; /* New entry */
  348. isp_user *cur; /* Current entry */
  349. int rc = 0;
  350. /*
  351. * Create the new record.
  352. */
  353. new = (isp_user *) malloc (sizeof (isp_user));
  354. if (NULL == new) {
  355. fprintf (stderr, "ldclt[%d]: %s: cannot malloc(isp_user), error=%d (%s)\n",
  356. mctx.pid, tttctx->thrdId, errno, strerror (errno));
  357. fflush (stderr);
  358. return -1;
  359. }
  360. strcpy (new->dn, dn);
  361. new->cost = new->counter = duration;
  362. new->next = NULL;
  363. /*
  364. * Get secure access to the common data structure.
  365. * Note : it should be possible to reduce the "size" of this critical
  366. * section but I am not 100% certain this won't mess up all things.
  367. */
  368. if ((ret = ldclt_mutex_lock (&(s1ctx.list_mutex))) != 0)
  369. {
  370. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_lock(), error=%d (%s)\n",
  371. mctx.pid, tttctx->thrdId, ret, strerror (ret));
  372. fflush (stderr);
  373. rc = -1;
  374. goto error;
  375. }
  376. /*
  377. * Maybe this is the first entry of the list ?
  378. */
  379. if (s1ctx.list == NULL)
  380. s1ctx.list = new;
  381. else
  382. {
  383. /*
  384. * Check with the list's head
  385. */
  386. if (s1ctx.list->counter >= duration)
  387. {
  388. new->next = s1ctx.list;
  389. s1ctx.list = new;
  390. }
  391. else
  392. {
  393. cur = s1ctx.list;
  394. while (cur != NULL)
  395. {
  396. if (cur->next == NULL)
  397. {
  398. cur->next = new;
  399. cur = NULL; /* Exit loop */
  400. }
  401. else
  402. if (cur->next->counter >= duration)
  403. {
  404. new->next = cur->next;
  405. cur->next = new;
  406. cur = NULL; /* Exit loop */
  407. }
  408. else
  409. cur = cur->next;
  410. }
  411. }
  412. }
  413. goto done;
  414. error:
  415. if (new) free(new);
  416. done:
  417. /*
  418. * Free mutex
  419. */
  420. if ((ret = ldclt_mutex_unlock (&(s1ctx.list_mutex))) != 0)
  421. {
  422. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_unlock(), error=%d (%s)\n",
  423. mctx.pid, tttctx->thrdId, ret, strerror (ret));
  424. fflush (stderr);
  425. rc = -1;
  426. }
  427. return rc;
  428. }
  429. /* ****************************************************************************
  430. FUNCTION : scalab01_connectSuperuser
  431. PURPOSE : Purpose of the fct
  432. INPUT : None.
  433. OUTPUT : None.
  434. RETURN : -1 if error, 0 else.
  435. DESCRIPTION :
  436. *****************************************************************************/
  437. int
  438. scalab01_connectSuperuser (void)
  439. {
  440. int ret; /* Return value */
  441. int v2v3; /* LDAP version used */
  442. char bindDN [MAX_DN_LENGTH] = {0}; /* To bind */
  443. const char *mech = LDAP_SASL_SIMPLE;
  444. struct berval cred = {0, NULL};
  445. struct berval *servercredp = NULL;
  446. #if defined(USE_OPENLDAP)
  447. char *ldapurl = NULL;
  448. #endif
  449. #if defined(USE_OPENLDAP)
  450. ldapurl = PR_smprintf("ldap%s://%s:%d/",
  451. (mctx.mode & SSL) ? "s" : "",
  452. mctx.hostname, mctx.port);
  453. if ((ret = ldap_initialize(&s1ctx.ldapCtx, ldapurl))) {
  454. printf ("ldclt[%d]: ctrl: Cannot ldap_initialize (%s), errno=%d ldaperror=%d:%s\n",
  455. mctx.pid, ldapurl, errno, ret, my_ldap_err2string(ret));
  456. fflush (stdout);
  457. PR_smprintf_free(ldapurl);
  458. return (-1);
  459. }
  460. PR_smprintf_free(ldapurl);
  461. ldapurl = NULL;
  462. #else /* !USE_OPENLDAP */
  463. /*
  464. * Create the LDAP context
  465. */
  466. /*
  467. * SSL is enabled ?
  468. */
  469. if (mctx.mode & SSL)
  470. {
  471. /*
  472. * LDAP session initialization in SSL mode
  473. */
  474. s1ctx.ldapCtx = ldapssl_init(mctx.hostname, mctx.port, 1);
  475. if (mctx.mode & VERY_VERBOSE)
  476. printf ("ldclt[%d]: ctrl: ldapssl_init (%s, %d), ldapCtx=0x%p\n",
  477. mctx.pid, mctx.hostname, mctx.port, s1ctx.ldapCtx);
  478. if (s1ctx.ldapCtx == NULL)
  479. {
  480. printf ("ldclt[%d]: ctrl: Cannot ldapssl_init (%s, %d), errno=%d\n",
  481. mctx.pid, mctx.hostname, mctx.port, errno);
  482. fflush (stdout);
  483. return (-1);
  484. }
  485. /*
  486. * Client authentication is used ?
  487. */
  488. if (mctx.mode & CLTAUTH)
  489. {
  490. ret = ldapssl_enable_clientauth(s1ctx.ldapCtx, "", mctx.keydbpin, mctx.cltcertname);
  491. if (mctx.mode & VERY_VERBOSE)
  492. printf
  493. ("ldclt[%d]: ctrl: After ldapssl_enable_clientauth (ldapCtx=0x%p, %s, %s)",
  494. mctx.pid, s1ctx.ldapCtx, mctx.keydbpin, mctx.cltcertname);
  495. if (ret < 0)
  496. {
  497. printf
  498. ("ldclt[%d]: ctrl: Cannot ldapssl_enable_clientauth (ldapCtx=0x%p, %s, %s)",
  499. mctx.pid, s1ctx.ldapCtx, mctx.keydbpin, mctx.cltcertname);
  500. ldap_perror(s1ctx.ldapCtx, "ldapssl_enable_clientauth");
  501. fflush (stdout);
  502. return (-1);
  503. }
  504. }
  505. }
  506. else
  507. {
  508. /*
  509. * Connection initialization in normal, unencrypted mode
  510. */
  511. s1ctx.ldapCtx = ldap_init (mctx.hostname, mctx.port);
  512. if (mctx.mode & VERY_VERBOSE)
  513. printf ("ldclt[%d]: ctrl: After ldap_init (%s, %d), ldapCtx=0x%p\n",
  514. mctx.pid, mctx.hostname, mctx.port, s1ctx.ldapCtx);
  515. if (s1ctx.ldapCtx == NULL)
  516. {
  517. printf ("ldclt[%d]: ctrl: Cannot ldap_init (%s, %d), errno=%d\n",
  518. mctx.pid, mctx.hostname, mctx.port, errno);
  519. fflush (stdout);
  520. return (-1);
  521. }
  522. }
  523. #endif /* !USE_OPENLDAP */
  524. if (mctx.mode & CLTAUTH) {
  525. mech = "EXTERNAL";
  526. } else {
  527. strcpy (bindDN, SCALAB01_SUPER_USER_RDN);
  528. strcat (bindDN, ",");
  529. strcat (bindDN, mctx.baseDN);
  530. cred.bv_val = SCALAB01_SUPER_USER_PASSWORD;
  531. cred.bv_len = strlen(cred.bv_val);
  532. }
  533. /*
  534. * Set the LDAP version and other options...
  535. */
  536. if (mctx.mode & LDAP_V2)
  537. v2v3 = LDAP_VERSION2;
  538. else
  539. v2v3 = LDAP_VERSION3;
  540. ret = ldap_set_option (s1ctx.ldapCtx, LDAP_OPT_PROTOCOL_VERSION, &v2v3);
  541. if (ret < 0) /*JLS 14-03-01*/
  542. { /*JLS 14-03-01*/
  543. printf ("ldclt[%d]: ctrl: Cannot ldap_set_option(LDAP_OPT_PROTOCOL_VERSION)\n",
  544. mctx.pid);
  545. fflush (stdout); /*JLS 14-03-01*/
  546. return (-1); /*JLS 14-03-01*/
  547. } /*JLS 14-03-01*/
  548. if (mctx.mode & VERY_VERBOSE)
  549. printf ("ldclt[%d]: ctrl: Before bind mech %s (%s , %s)\n",
  550. mctx.pid, mech ? mech : "SIMPLE", bindDN, SCALAB01_SUPER_USER_PASSWORD);
  551. ret = ldap_sasl_bind_s (s1ctx.ldapCtx, bindDN, mech, &cred, NULL, NULL, &servercredp);
  552. ber_bvfree(servercredp);
  553. if (mctx.mode & VERY_VERBOSE)
  554. printf ("ldclt[%d]: ctrl: After bind mech %s (%s, %s)\n",
  555. mctx.pid, mech ? mech : "SIMPLE", bindDN, SCALAB01_SUPER_USER_PASSWORD);
  556. if (ret != LDAP_SUCCESS)
  557. {
  558. printf("ldclt[%d]: ctrl: Cannot bind mech %s (%s, %s), error=%d (%s)\n",
  559. mctx.pid, mech ? mech : "SIMPLE", bindDN, SCALAB01_SUPER_USER_PASSWORD,
  560. ret, my_ldap_err2string (ret));
  561. fflush (stdout);
  562. return (-1);
  563. }
  564. /*
  565. * Normal end...
  566. */
  567. return (0);
  568. }
  569. /* ****************************************************************************
  570. FUNCTION : readAttrValue
  571. PURPOSE : This function will ldap_search the given entry for the
  572. value of the given attribute.
  573. INPUT : ident = thread identifier
  574. ldapCtx = LDAP context
  575. dn = dn of the entry to process
  576. attname = attribute name
  577. OUTPUT : value = attribute value. This buffer must be
  578. initiated with enough memory.
  579. value[0] == '\0' if not find.
  580. RETURN : -1 if error, 0 else.
  581. DESCRIPTION :
  582. *****************************************************************************/
  583. int
  584. readAttrValue (
  585. LDAP *ldapCtx,
  586. char *ident,
  587. char *dn,
  588. char *attname,
  589. char *value)
  590. {
  591. int ret; /* Return value */
  592. char *attrs[2]; /* Attribute to retrieve */
  593. LDAPMessage *res; /* LDAP responses */
  594. LDAPMessage *cur; /* Current message */
  595. BerElement *ber; /* To decode the response */
  596. char *aname; /* Current attribute name */
  597. char *filter; /* Filter used for searching */
  598. /*
  599. * First, ldap_search() the entry.
  600. */
  601. attrs[0] = attname;
  602. attrs[1] = NULL;
  603. filter = (char *)malloc((4+strlen(attname))*sizeof(char));
  604. if (NULL == filter)
  605. {
  606. printf ("ldclt[%d]: %s: Out of memory\n", mctx.pid, ident);
  607. fflush (stdout);
  608. return (-1);
  609. }
  610. sprintf(filter, "(%s=*)", attname);
  611. ret = ldap_search_ext_s (ldapCtx, dn, LDAP_SCOPE_BASE,
  612. filter, attrs, 0, NULL, NULL, NULL, -1, &res);
  613. free(filter);
  614. if (ret != LDAP_SUCCESS)
  615. {
  616. printf ("ldclt[%d]: %s: Cannot ldap_search (%s in %s), error=%d (%s)\n",
  617. mctx.pid, ident, attname, dn, ret, my_ldap_err2string (ret));
  618. fflush (stdout);
  619. return (-1);
  620. }
  621. /*
  622. * Decode the response
  623. */
  624. value[0] = '\0'; /* Not find yet */
  625. cur = ldap_first_entry (ldapCtx, res);
  626. while ((!value[0]) && (cur != NULL))
  627. {
  628. aname = ldap_first_attribute (ldapCtx, cur, &ber);
  629. while ((!value[0]) && (aname != NULL))
  630. {
  631. /*
  632. * We expect this attribute to be single-valued.
  633. */
  634. if (!strcmp (aname, attname))
  635. {
  636. struct berval **vals;
  637. vals = ldap_get_values_len (ldapCtx, cur, aname);
  638. if (vals == NULL)
  639. {
  640. printf ("ldclt[%d]: %s: no value for %s in %s\n",
  641. mctx.pid, ident, dn, attname);
  642. fflush (stdout);
  643. return (-1);
  644. }
  645. strncpy (value, vals[0]->bv_val, vals[0]->bv_len);
  646. value[vals[0]->bv_len] = '\0';
  647. ldap_value_free_len (vals);
  648. }
  649. /*
  650. * Next attribute
  651. */
  652. ldap_memfree (aname);
  653. if (!value[0])
  654. aname = ldap_next_attribute (ldapCtx, cur, ber);
  655. }
  656. /*
  657. * Next entry - shouldn't happen in theory
  658. */
  659. if (ber != NULL)
  660. ber_free (ber, 0);
  661. cur = ldap_next_entry (ldapCtx, cur);
  662. }
  663. ldap_msgfree (res); /* Free the response */
  664. return (0);
  665. }
  666. /* ****************************************************************************
  667. FUNCTION : writeAttrValue
  668. PURPOSE : This function will ldap_modify the given entry to
  669. replace the value of the given attribute.
  670. INPUT : ident = thread identifier
  671. ldapCtx = LDAP context
  672. dn = dn of the entry to process
  673. attname = attribute name
  674. value = attribute value
  675. OUTPUT : None.
  676. RETURN : -1 if error, 0 else.
  677. DESCRIPTION :
  678. *****************************************************************************/
  679. int
  680. writeAttrValue (
  681. LDAP *ldapCtx,
  682. char *ident,
  683. char *dn,
  684. char *attname,
  685. char *value)
  686. {
  687. int ret; /* Return value */
  688. LDAPMod attribute; /* To build the attributes */
  689. LDAPMod *attrsmod[2]; /* Modify attributes */
  690. char *pvalues[2]; /* To build the values list */
  691. /*
  692. * Prepear the data to be written
  693. */
  694. pvalues[0] = value;
  695. pvalues[1] = NULL;
  696. attribute.mod_op = LDAP_MOD_REPLACE;
  697. attribute.mod_type = attname;
  698. attribute.mod_values = pvalues;
  699. attrsmod[0] = &attribute;
  700. attrsmod[1] = NULL;
  701. /*
  702. * Store the data in the directory.
  703. */
  704. ret = ldap_modify_ext_s (ldapCtx, dn, attrsmod, NULL, NULL);
  705. if (ret != LDAP_SUCCESS)
  706. {
  707. printf ("ldclt[%d]: %s: Cannot ldap_modify_ext_s (%s in %s), error=%d (%s)\n",
  708. mctx.pid, ident, attname, dn, ret, my_ldap_err2string (ret));
  709. fflush (stdout);
  710. return (-1);
  711. }
  712. return (0);
  713. }
  714. /* ****************************************************************************
  715. FUNCTION : scalab01_unlock
  716. PURPOSE : Unlock the user given in argument.
  717. INPUT : entry = entry to unlock.
  718. OUTPUT : None.
  719. RETURN : -1 if error, 0 else.
  720. DESCRIPTION :
  721. *****************************************************************************/
  722. int
  723. scalab01_unlock (
  724. isp_user *user)
  725. {
  726. int account; /* Accounting value */
  727. char buf[20]; /* To read/write attribute */
  728. /*
  729. * Increment accounting counters
  730. * First, read the current value.
  731. */
  732. if (readAttrValue (s1ctx.ldapCtx,"ctrl",user->dn,SCALAB01_ACC_ATTRIB,buf) < 0)
  733. {
  734. printf ("ldclt[%d]: ctrl: Cannot read accounting attribute of %s\n",
  735. mctx.pid, user->dn);
  736. fflush (stdout);
  737. return (-1);
  738. }
  739. /*
  740. * If this attribute has no value (doesn't exist) we assume it is 0.
  741. */
  742. if (buf[0] != '\0')
  743. account = atoi (buf);
  744. else
  745. {
  746. printf ("ldclt[%d]: ctrl: No accounting attribute for %s - assume it is 0\n",
  747. mctx.pid, user->dn);
  748. fflush (stdout);
  749. account = 0;
  750. }
  751. /*
  752. * Compute the new value and store it in the directory.
  753. */
  754. sprintf (buf, "%d", account + user->cost);
  755. if (writeAttrValue (s1ctx.ldapCtx,"ctrl",user->dn,SCALAB01_ACC_ATTRIB,buf) <0)
  756. {
  757. printf ("ldclt[%d]: ctrl: Cannot write accounting attribute of %s\n",
  758. mctx.pid, user->dn);
  759. fflush (stdout);
  760. return (-1);
  761. }
  762. /*
  763. * Unlock the user
  764. */
  765. if (writeAttrValue (s1ctx.ldapCtx, "ctrl", user->dn,
  766. SCALAB01_LOCK_ATTRIB, SCALAB01_VAL_UNLOCKED) < 0)
  767. {
  768. printf ("ldclt[%d]: ctrl: Cannot write lock (unlock) attribute of %s\n",
  769. mctx.pid, user->dn);
  770. fflush (stdout);
  771. return (-1);
  772. }
  773. if (mctx.mode & VERY_VERBOSE)
  774. printf ("ldclt[%d]: ctrl: entry %s unlocked\n",
  775. mctx.pid, user->dn);
  776. /*
  777. * Decrement modem pool usage...
  778. */
  779. if (scalab01_modemDecr ("ctrl") < 0)
  780. return (-1);
  781. /*
  782. * Normal end
  783. */
  784. return (0);
  785. }
  786. /* ****************************************************************************
  787. FUNCTION : scalab01_control
  788. PURPOSE : This function implements the control loop/thread of
  789. the scalab01 scenario. Its main target is to manage
  790. the counters of each "connection" and to unlock the
  791. entry when time is reached.
  792. INPUT : None.
  793. OUTPUT : None.
  794. RETURN : -1 if error, 0 else.
  795. DESCRIPTION :
  796. *****************************************************************************/
  797. void *
  798. scalab01_control (
  799. void *arg)
  800. {
  801. isp_user *cur; /* Current entry */
  802. isp_user *head; /* Head of entries to process */
  803. int ret; /* Return value */
  804. int nbTot; /* Total nb entries locked */
  805. int nbU; /* Number unlocked */
  806. /*
  807. * Initialization
  808. * Failure to connect is a critical error...
  809. */
  810. if (scalab01_connectSuperuser () < 0)
  811. ldcltExit (EXIT_NOBIND);
  812. /*
  813. * Main loop
  814. */
  815. while (1 /*CONSTCOND*/) /*JLS 14-03-01*/
  816. {
  817. ldclt_sleep (1); /* Poll the connections every second */
  818. nbTot = nbU = 0; /* No entries processed yet */
  819. /*
  820. * Get protected access to the entries
  821. */
  822. if ((ret = ldclt_mutex_lock (&(s1ctx.list_mutex))) != 0)
  823. {
  824. fprintf (stderr, "ldclt[%d]: ctrl: cannot mutex_lock(), error=%d (%s)\n",
  825. mctx.pid, ret, strerror (ret));
  826. fflush (stderr);
  827. ldcltExit (EXIT_OTHER);
  828. }
  829. /*
  830. * Decrement all counters
  831. */
  832. for (cur=s1ctx.list ; cur!=NULL ; cur=cur->next)
  833. {
  834. cur->counter--;
  835. nbTot++;
  836. }
  837. /*
  838. * Find the entries to process.
  839. */
  840. if ((s1ctx.list == NULL) || (s1ctx.list->counter > 0))
  841. head = NULL;
  842. else
  843. {
  844. head = cur = s1ctx.list;
  845. while ((cur != NULL) && (cur->counter == 0))
  846. cur = cur->next;
  847. s1ctx.list = cur;
  848. }
  849. /*
  850. * Release mutex
  851. */
  852. if ((ret = ldclt_mutex_unlock (&(s1ctx.list_mutex))) != 0)
  853. {
  854. fprintf (stderr, "ldclt[%d]: ctrl: cannot mutex_unlock(), error=%d (%s)\n",
  855. mctx.pid, ret, strerror (ret));
  856. fflush (stderr);
  857. ldcltExit (EXIT_OTHER);
  858. }
  859. /*
  860. * Now, we have "head" that points either to NULL or to a list of
  861. * entries to process.
  862. * Attention, this list of entries is not terminated by NULL, but
  863. * we must rather check the field head->next->counter" for the last
  864. * entry...
  865. *
  866. * NOTE : implements this section as a separate thread to keep the
  867. * general timer working...
  868. */
  869. while (head != NULL)
  870. {
  871. if (scalab01_unlock (head) < 0)
  872. {
  873. printf ("ldclt[%d]: ctrl: cannot unlock %s\n", mctx.pid, head->dn);
  874. ldcltExit (EXIT_OTHER);
  875. }
  876. nbU++; /* One more entry unlocked */
  877. /*
  878. * Next entry...
  879. */
  880. cur = head;
  881. if (head->next == NULL)
  882. head = NULL;
  883. else
  884. if (head->next->counter != 0)
  885. head = NULL;
  886. else
  887. head = head->next;
  888. free (cur);
  889. } /* while (head =! NULL) */
  890. /*
  891. * Print some stats...
  892. */
  893. if (mctx.mode & VERBOSE)
  894. printf ("ldclt[%d]: ctrl: nb entries unlocked / total : %3d / %5d\n",
  895. mctx.pid, nbU, nbTot);
  896. } /* Main loop */
  897. /*
  898. * End of thread
  899. */
  900. }
  901. /* ****************************************************************************
  902. FUNCTION : doScalab01
  903. PURPOSE : Implements the client part of the scalab01 scenario.
  904. INPUT : tttctx = this thread context
  905. OUTPUT : None.
  906. RETURN : -1 if error, 0 else.
  907. DESCRIPTION :
  908. *****************************************************************************/
  909. int
  910. doScalab01 (
  911. thread_context *tttctx)
  912. {
  913. char buf[32]; /* To read attributes value */
  914. int duration; /* Use a variable for trace purpose */
  915. int res; /* Result of cnx to modem pool */
  916. int doloop; /* To know if we should loop */
  917. /*
  918. * Simulate connection to the modem pool.
  919. */
  920. while ((res = scalab01_modemIncr(tttctx->thrdId)) != 1)
  921. switch (res)
  922. {
  923. case 0:
  924. ldclt_sleep (s1ctx.wait==0?SCALAB01_DEF_WAIT_TIME:rndlim(0,s1ctx.wait));
  925. break;
  926. case -1:
  927. return (-1);
  928. break;
  929. }
  930. /*
  931. * Connection to the server
  932. * The function connectToServer() will take care of the various connection/
  933. * disconnection, bind/unbind/close etc... requested by the user.
  934. * The cost is one more function call in this application, but the
  935. * resulting source code will be much more easiest to maintain.
  936. */
  937. if (connectToServer (tttctx) < 0)
  938. return (-1);
  939. if (!(tttctx->binded))
  940. return (0);
  941. /*
  942. * Check that no other thread is using the same identity...
  943. */
  944. doloop = 1;
  945. while (doloop)
  946. {
  947. switch (scalab01Lock (tttctx))
  948. {
  949. case 0:
  950. ldclt_sleep (1);
  951. break;
  952. case 1:
  953. doloop = 0;
  954. break;
  955. case -1:
  956. return (-1);
  957. break;
  958. }
  959. }
  960. /*
  961. * Ok, we are now binded. Great ;-)
  962. * The DN we used to bind is available in tttctx->bufBindDN
  963. * Read lock attribute
  964. */
  965. if (readAttrValue (tttctx->ldapCtx, tttctx->thrdId, tttctx->bufBindDN,
  966. SCALAB01_LOCK_ATTRIB, buf) < 0)
  967. {
  968. printf ("ldclt[%d]: %s: Cannot read lock attribute of %s\n",
  969. mctx.pid, tttctx->thrdId, tttctx->bufBindDN);
  970. fflush (stdout);
  971. (void) scalab01_modemDecr (tttctx->thrdId);
  972. return (-1);
  973. }
  974. if (mctx.mode & VERY_VERBOSE)
  975. printf ("ldclt[%d]: %s: entry %s lock read\n",
  976. mctx.pid, tttctx->thrdId, tttctx->bufBindDN);
  977. /*
  978. * If locked, then we cannot login now...
  979. */
  980. if (!strcmp (buf, SCALAB01_VAL_LOCKED))
  981. {
  982. if (scalab01_modemDecr (tttctx->thrdId) < 0)
  983. return (-1);
  984. return (0);
  985. }
  986. /*
  987. * If not locked :
  988. * - lock the user
  989. * - decide how many times will be connected
  990. * - add information to the list of connected
  991. */
  992. if (writeAttrValue (tttctx->ldapCtx, tttctx->thrdId, tttctx->bufBindDN,
  993. SCALAB01_LOCK_ATTRIB, SCALAB01_VAL_LOCKED) < 0)
  994. {
  995. printf ("ldclt[%d]: %s: Cannot write lock attribute of %s\n",
  996. mctx.pid, tttctx->thrdId, tttctx->bufBindDN);
  997. fflush (stdout);
  998. /*
  999. * It can still happen that two threads write this attribute at the same
  1000. * time, so there can be failure in one of the threads
  1001. * in this case just return
  1002. */
  1003. if (scalab01_modemDecr (tttctx->thrdId) < 0) /*JLS 03-05-01*/
  1004. return (-1); /*JLS 03-05-01*/
  1005. return (0); /*BK 26-04-01*/
  1006. }
  1007. if (mctx.mode & VERY_VERBOSE)
  1008. printf ("ldclt[%d]: %s: entry %s lock written\n",
  1009. mctx.pid, tttctx->thrdId, tttctx->bufBindDN);
  1010. if (scalab01Unlock (tttctx) < 0)
  1011. return (-1);
  1012. duration = rndlim (1, s1ctx.cnxduration);
  1013. if (scalab01_addLogin (tttctx, tttctx->bufBindDN, duration) < 0)
  1014. {
  1015. printf ("ldclt[%d]: %s: Cannot memorize new login of %s\n",
  1016. mctx.pid, tttctx->thrdId, tttctx->bufBindDN);
  1017. fflush (stdout);
  1018. return (-1);
  1019. }
  1020. if (mctx.mode & VERY_VERBOSE)
  1021. printf ("ldclt[%d]: %s: entry %s login added duration %6d\n",
  1022. mctx.pid, tttctx->thrdId, tttctx->bufBindDN, duration);
  1023. /*
  1024. * Memorize the operation
  1025. */
  1026. if (incrementNbOpers (tttctx) < 0)
  1027. return (-1);
  1028. /*
  1029. * Wait before next operation...
  1030. */
  1031. if (s1ctx.wait > 0)
  1032. ldclt_sleep (rndlim (0,s1ctx.wait));
  1033. /*
  1034. * Unbind
  1035. */
  1036. /*
  1037. TBC - this is done in the next loop... - cf connectToServer()
  1038. */
  1039. return (0);
  1040. }
  1041. /* End of file */