auth.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <ctype.h>
  44. #include <string.h>
  45. #include <prinit.h> // for PR_Init
  46. #include <prpriv.h> // for PR_Exit
  47. #include <ldaputil/certmap.h>
  48. #include <ldaputil/init.h>
  49. #include <ldaputil/ldapdb.h>
  50. #include <ldaputil/ldapauth.h>
  51. #include <ldaputil/dbconf.h>
  52. #include <ldaputil/ldaputil.h>
  53. #include <ldap.h>
  54. static const char* dllname = "plugin.so";
  55. char *global_issuer_dn = "o=Fedora Project, c=US";
  56. #define NSPR_INIT(Program) (PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 8))
  57. static int ldapu_certinfo_save_test (const char *fname, const char *old_fname)
  58. {
  59. int rv;
  60. /* Read the original certmap config file first */
  61. rv = ldaputil_init(old_fname, dllname, NULL, NULL, NULL);
  62. if (rv != LDAPU_SUCCESS) {
  63. fprintf(stderr, "ldapu_certinfo_save_test failed. Reason: %s\n",
  64. ldapu_err2string(rv));
  65. return rv;
  66. }
  67. rv = ldapu_certinfo_save(fname, old_fname, "certmap.tmp");
  68. if (rv != LDAPU_SUCCESS) {
  69. fprintf(stderr, "ldapu_certinfo_save_test failed. Reason: %s\n",
  70. ldapu_err2string(rv));
  71. }
  72. return rv;
  73. }
  74. static int ldapu_certinfo_delete_test (const char *fname, const char *old_fname)
  75. {
  76. int rv;
  77. /* Read the original certmap config file first */
  78. rv = ldaputil_init(old_fname, dllname, NULL, NULL, NULL);
  79. if (rv != LDAPU_SUCCESS) {
  80. fprintf(stderr, "ldapu_certinfo_delete_test failed. Reason: %s\n",
  81. ldapu_err2string(rv));
  82. return rv;
  83. }
  84. /* rv = ldapu_certinfo_delete("o=Ace Industry, c=US"); */
  85. rv = ldapu_certinfo_delete("o=Fedora Project, c=US");
  86. if (rv != LDAPU_SUCCESS) {
  87. fprintf(stderr, "ldapu_certinfo_delete failed. Reason: %s\n",
  88. ldapu_err2string(rv));
  89. return rv;
  90. }
  91. rv = ldapu_certinfo_save(fname, old_fname, "certmap.tmp");
  92. if (rv != LDAPU_SUCCESS) {
  93. fprintf(stderr, "ldapu_certinfo_delete_test failed. Reason: %s\n",
  94. ldapu_err2string(rv));
  95. }
  96. return rv;
  97. }
  98. static int ldapu_certinfo_new_test (const char *fname, const char *old_fname)
  99. {
  100. int rv;
  101. LDAPUPropValList_t *propval_list;
  102. LDAPUPropVal_t *propval;
  103. /* Read the original certmap config file first */
  104. rv = ldaputil_init(old_fname, dllname, NULL, NULL, NULL);
  105. if (rv != LDAPU_SUCCESS) {
  106. fprintf(stderr, "ldapu_certinfo_new_test failed. Reason: %s\n",
  107. ldapu_err2string(rv));
  108. return rv;
  109. }
  110. /* Setup propval_list */
  111. rv = ldapu_list_alloc(&propval_list);
  112. if (rv != LDAPU_SUCCESS) return rv;
  113. rv = ldapu_propval_alloc("prop1", "val1", &propval);
  114. if (rv != LDAPU_SUCCESS) return rv;
  115. rv = ldapu_list_add_info(propval_list, propval);
  116. if (rv != LDAPU_SUCCESS) return rv;
  117. rv = ldapu_propval_alloc("prop2", "val2", &propval);
  118. if (rv != LDAPU_SUCCESS) return rv;
  119. rv = ldapu_list_add_info(propval_list, propval);
  120. if (rv != LDAPU_SUCCESS) return rv;
  121. rv = ldapu_propval_alloc("prop3", 0, &propval);
  122. if (rv != LDAPU_SUCCESS) return rv;
  123. rv = ldapu_list_add_info(propval_list, propval);
  124. if (rv != LDAPU_SUCCESS) return rv;
  125. rv = ldapu_certinfo_modify("newmap", "o=Mcom Communications, c=US",
  126. propval_list);
  127. ldapu_propval_list_free(propval_list);
  128. if (rv != LDAPU_SUCCESS) {
  129. fprintf(stderr, "ldapu_certinfo_delete failed. Reason: %s\n",
  130. ldapu_err2string(rv));
  131. return rv;
  132. }
  133. rv = ldapu_certinfo_save(fname, old_fname, "certmap.tmp");
  134. if (rv != LDAPU_SUCCESS) {
  135. fprintf(stderr, "ldapu_certinfo_new_test failed. Reason: %s\n",
  136. ldapu_err2string(rv));
  137. }
  138. return rv;
  139. }
  140. static int get_dbnames_test (const char *mapfile)
  141. {
  142. char **names;
  143. int cnt;
  144. int rv;
  145. int i;
  146. rv = dbconf_get_dbnames(mapfile, &names, &cnt);
  147. if (rv != LDAPU_SUCCESS) {
  148. fprintf(stderr, "get_dbnames_test failed. Reason: %s\n",
  149. ldapu_err2string(rv));
  150. }
  151. else {
  152. for(i = 0; i < cnt; i++) {
  153. fprintf(stderr, "\tdbname[%d] = \"%s\"\n",
  154. i, names[i]);
  155. }
  156. }
  157. dbconf_free_dbnames(names);
  158. return rv;
  159. }
  160. static int case_ignore_strcmp (const char *s1, const char *s2)
  161. {
  162. int ls1, ls2; /* tolower values of chars in s1 & s2 resp. */
  163. if (!s1) return !s2 ? 0 : 0-tolower(*s2);
  164. else if (!s2) return tolower(*s1);
  165. while(*s1 && *s2 && (ls1 = tolower(*s1)) == (ls2 = tolower(*s2))) { s1++; s2++; }
  166. if (!*s1)
  167. return *s2 ? 0-tolower(*s2) : 0;
  168. else if (!*s2)
  169. return tolower(*s1);
  170. else
  171. return ls1 - ls2;
  172. }
  173. #define STRCASECMP3(s1, s2, rv) \
  174. { \
  175. int i = case_ignore_strcmp(s1, s2); \
  176. fprintf(stderr, "strcasecmp(\"%s\", \"%s\")\t=\t%d\t%s\tExpected: %d\n", \
  177. s1 ? s1 : "<NULL>", s2 ? s2 : "<NULL>", \
  178. i, i == rv ? "SUCCESS" : "FAILED", rv); \
  179. }
  180. #ifndef XP_WIN32
  181. #define STRCASECMP(s1, s2) STRCASECMP3(s1, s2, strcasecmp(s1, s2))
  182. #else
  183. #define STRCASECMP(s1, s2) STRCASECMP3(s1, s2, case_ignore_strcmp(s1, s2))
  184. #endif
  185. static void strcasecmp_test ()
  186. {
  187. STRCASECMP3(0, "aBcD", 0-tolower('a'));
  188. STRCASECMP3(0, 0, 0);
  189. STRCASECMP3("aBcD", 0, tolower('a'));
  190. STRCASECMP("AbCd", "aBcD");
  191. STRCASECMP("AbCd", "abcd");
  192. STRCASECMP("ABCD", "ABCD");
  193. STRCASECMP("abcd", "abcd");
  194. STRCASECMP("AbCd", "aBcD3");
  195. STRCASECMP("AbCd", "abcd3");
  196. STRCASECMP("ABCD", "ABCD3");
  197. STRCASECMP("abcd", "abcd3");
  198. STRCASECMP("AbCd1", "aBcD");
  199. STRCASECMP("AbCd2", "abcd");
  200. STRCASECMP("ABCDX", "ABCD");
  201. STRCASECMP("abcdY", "abcd");
  202. STRCASECMP("AbCd5", "aBcD1");
  203. STRCASECMP("AbCd5", "abcd1");
  204. STRCASECMP("ABCD5", "ABCD1");
  205. STRCASECMP("abcd5", "abcd1");
  206. STRCASECMP("AbCd2", "aBcDp");
  207. STRCASECMP("AbCd2", "abcdQ");
  208. STRCASECMP("ABCD2", "ABCDr");
  209. STRCASECMP("abcd2", "abcdS");
  210. }
  211. static int certmap_tests (const char *config_file) { return 0; }
  212. static int read_config_test (const char *config_file, const char *dbname,
  213. const char *url,
  214. const char *binddn, const char *bindpw)
  215. {
  216. int rv;
  217. DBConfDBInfo_t *db_info;
  218. char *dn;
  219. char *pw;
  220. rv = dbconf_read_default_dbinfo(config_file, &db_info);
  221. if (rv != LDAPU_SUCCESS) {
  222. fprintf(stderr, "config_test failed: %s\n",
  223. ldapu_err2string(rv));
  224. return LDAPU_FAILED;
  225. }
  226. if (strcmp(db_info->dbname, dbname) ||
  227. strcmp(db_info->url, url)) {
  228. fprintf(stderr, "config_test failed: %s\n",
  229. "first line in config file is wrong");
  230. return LDAPU_FAILED;
  231. }
  232. if ((ldapu_dbinfo_attrval(db_info, "binddn", &dn) != LDAPU_SUCCESS) ||
  233. (ldapu_dbinfo_attrval(db_info, "bindpw", &pw) != LDAPU_SUCCESS))
  234. {
  235. fprintf(stderr, "config_test failed: %s\n",
  236. "properties are missing");
  237. return LDAPU_FAILED;
  238. }
  239. if (strcmp(dn, binddn) ||
  240. strcmp(pw, bindpw)) {
  241. fprintf(stderr, "config_test failed: %s\n",
  242. "property values are wrong");
  243. return LDAPU_FAILED;
  244. }
  245. fprintf(stderr, "binddn from config file: \"%s\"\n", dn);
  246. fprintf(stderr, "bindpw from config file: \"%s\"\n", pw);
  247. /* cleanup */
  248. dbconf_free_dbinfo(db_info);
  249. free(dn);
  250. free(pw);
  251. return LDAPU_SUCCESS;
  252. }
  253. static int config_test (const char *binddn, const char *bindpw)
  254. {
  255. char *config_file = "config_out.conf";
  256. FILE *fp = fopen(config_file, "w");
  257. const char *dbname = "default";
  258. const char *url = "file:/foobar/path";
  259. int rv;
  260. if (!fp) return LDAPU_FAILED;
  261. dbconf_output_db_directive(fp, dbname, url);
  262. dbconf_output_propval(fp, dbname, "binddn", binddn, 0);
  263. dbconf_output_propval(fp, dbname, "bindpw", bindpw, 1);
  264. fclose(fp);
  265. fprintf(stderr, "Config file written: %s\n", config_file);
  266. rv = read_config_test(config_file, dbname, url, binddn, bindpw);
  267. return rv;
  268. }
  269. static int
  270. compare_groupid(const void *arg, const char *group, const int len)
  271. {
  272. auto const char* groupid = (const char*)arg;
  273. auto int err = LDAPU_FAILED;
  274. if (len == strlen (groupid) && !strncasecmp (groupid, group, len)) {
  275. err = LDAPU_SUCCESS;
  276. }
  277. return err;
  278. }
  279. static int
  280. compare_group(LDAP* directory, LDAPMessage* entry, void* set)
  281. {
  282. auto int err = LDAPU_FAILED;
  283. auto char** vals = ldap_get_values (directory, entry, "CN");
  284. if (vals) {
  285. auto char** val;
  286. for (val = vals; *val; ++val) {
  287. if (!strcasecmp (*val, (char*)set)) {
  288. err = LDAPU_SUCCESS;
  289. break;
  290. }
  291. }
  292. ldap_value_free (vals);
  293. }
  294. return err;
  295. }
  296. int perform_test (int argc, char *argv[])
  297. {
  298. int test_type;
  299. int retval = LDAPU_SUCCESS;
  300. DBConfDBInfo_t *db_info;
  301. LDAPDatabase_t *ldb;
  302. LDAP *ld;
  303. char *dbmap_file = "dblist.conf";
  304. char *binddn = 0;
  305. char *bindpw = 0;
  306. char *basedn;
  307. int retry = 1;
  308. int rv;
  309. fprintf(stderr, "\nStart of test: ./auth %s \"%s\" \"%s\"\n",
  310. argv[1], argv[2], argv[3]);
  311. rv = dbconf_read_default_dbinfo(dbmap_file, &db_info);
  312. if (rv != LDAPU_SUCCESS) {
  313. fprintf(stderr, "Error reading dbmap file \"%s\". Reason: %s\n",
  314. dbmap_file, ldapu_err2string(rv));
  315. return rv;
  316. }
  317. ldapu_dbinfo_attrval (db_info, LDAPU_ATTR_BINDDN, &binddn);
  318. ldapu_dbinfo_attrval (db_info, LDAPU_ATTR_BINDPW, &bindpw);
  319. rv = ldapu_url_parse (db_info->url, binddn, bindpw, &ldb);
  320. free(binddn);
  321. free(bindpw);
  322. if (rv != LDAPU_SUCCESS) {
  323. fprintf(stderr, "Error parsing ldap url \"%s\". Reason: %s\n",
  324. db_info->url, ldapu_err2string(rv));
  325. return rv;
  326. }
  327. basedn = ldb->basedn;
  328. test_type = atoi(argv[1]);
  329. retry = 1;
  330. while(retry) {
  331. retry = 0;
  332. rv = ldapu_ldap_init_and_bind (ldb);
  333. if (rv != LDAPU_SUCCESS) {
  334. fprintf(stderr, "Error initializing connection to LDAP. Reason: %s\n",
  335. ldapu_err2string(rv));
  336. return rv;
  337. }
  338. ld = ldb->ld;
  339. switch(test_type) {
  340. case 1:
  341. fprintf(stderr, "\nuserdn:\t\t\"%s\"\ngroupdn:\t\"%s\"\n",
  342. argv[2], argv[3]);
  343. retval = ldapu_auth_userdn_groupdn(ld, argv[2], argv[3], basedn);
  344. break;
  345. case 2:
  346. fprintf(stderr, "\nuid:\t\t\"%s\"\ngroupdn:\t\"%s\"\n", argv[2], argv[3]);
  347. retval = ldapu_auth_uid_groupdn(ld, argv[2], argv[3], basedn);
  348. break;
  349. case 3:
  350. fprintf(stderr, "\nuid:\t\t\"%s\"\ngroupid:\t\"%s\"\n", argv[2], argv[3]);
  351. retval = ldapu_auth_uid_groupid(ld, argv[2], argv[3], basedn);
  352. break;
  353. case 4:
  354. fprintf(stderr, "\nuserdn:\t\t\"%s\"\ngroupid:\t\"%s\"\n", argv[2], argv[3]);
  355. retval = ldapu_auth_userdn_groupid(ld, argv[2], argv[3], basedn);
  356. break;
  357. case 5:
  358. fprintf(stderr, "\nuserdn:\t\t\"%s\"\nattrFilter:\t\"%s\"\n", argv[2], argv[3]);
  359. retval = ldapu_auth_userdn_attrfilter(ld, argv[2], argv[3]);
  360. break;
  361. case 6:
  362. fprintf(stderr, "\nuid:\t\t\"%s\"\nattrFilter:\t\"%s\"\n", argv[2], argv[3]);
  363. retval = ldapu_auth_uid_attrfilter(ld, argv[2], argv[3], basedn);
  364. break;
  365. case 7:
  366. fprintf(stderr, "\nuserdn:\t\t\"%s\"\npassword:\t\"%s\"\n", argv[2], argv[3]);
  367. retval = ldapu_auth_userdn_password(ld, argv[2], argv[3]);
  368. break;
  369. case 8:
  370. fprintf(stderr, "\nuid:\t\t\"%s\"\npassword:\t\"%s\"\n", argv[2], argv[3]);
  371. retval = ldapu_auth_uid_password(ld, argv[2], argv[3], basedn);
  372. break;
  373. case 9: {
  374. /* plugin test */
  375. LDAPMessage *entry = 0;
  376. LDAPMessage *res = 0;
  377. fprintf(stderr, "Cert Map issuer DN: \"%s\"\n", argv[2]);
  378. fprintf(stderr, "Cert Map subject DN: \"%s\"\n", argv[3]);
  379. retval = ldaputil_init("certmap.conf", dllname, NULL, NULL, NULL);
  380. if (retval != LDAPU_SUCCESS) {
  381. fprintf(stderr, "Cert Map info test failed. Reason: %s\n",
  382. ldapu_err2string(retval));
  383. break;
  384. }
  385. if (*(argv[2]))
  386. global_issuer_dn = argv[2];
  387. else
  388. global_issuer_dn = 0;
  389. retval = ldapu_cert_to_ldap_entry(argv[3], ld, ldb->basedn, &res);
  390. if (retval == LDAPU_SUCCESS) {
  391. char *dn;
  392. entry = ldap_first_entry(ld, res);
  393. dn = ldap_get_dn(ld, entry);
  394. fprintf(stderr, "Matched entry to cert: \"%s\"\n", dn);
  395. ldap_memfree(dn);
  396. }
  397. else if (retval == LDAPU_FAILED) {
  398. /* Not an error but couldn't map the cert */
  399. }
  400. else {
  401. fprintf(stderr, "Cert Map info test failed. Reason: %s\n",
  402. ldapu_err2string(retval));
  403. break;
  404. }
  405. /* TEMPORARY -- when & how to free the entry */
  406. if (res) ldap_msgfree(res);
  407. break;
  408. } /* case 9 */
  409. case 10:
  410. if ((retval = config_test(argv[2], argv[3])) == LDAPU_SUCCESS) {
  411. fprintf(stderr, "Config file test succeeded\n");
  412. }
  413. else {
  414. fprintf(stderr, "Config file test failed\n");
  415. }
  416. break;
  417. case 11:
  418. retval = get_dbnames_test(argv[2]);
  419. break;
  420. case 12:
  421. retval = ldapu_certinfo_save_test(argv[2], argv[3]);
  422. break;
  423. case 13:
  424. retval = ldapu_certinfo_delete_test(argv[2], argv[3]);
  425. break;
  426. case 14:
  427. retval = ldapu_certinfo_new_test(argv[2], argv[3]);
  428. break;
  429. case 15:
  430. fprintf(stderr, "\nuserdn:\t\t\"%s\"\ngroupid:\t\"%s\"\n", argv[2], argv[3]);
  431. {
  432. auto LDAPU_DNList_t* userDNs = ldapu_DNList_alloc();
  433. ldapu_DNList_add(userDNs, argv[2]);
  434. retval = ldapu_auth_usercert_groups(ld, basedn, userDNs, NULL,
  435. argv[3], compare_group, 30, NULL);
  436. ldapu_DNList_free(userDNs);
  437. }
  438. break;
  439. case 16:
  440. fprintf(stderr, "\nuserCert:\t\"%s\"\ngroupid:\t\"%s\"\n", argv[2], argv[3]);
  441. retval = ldapu_auth_usercert_groupids(ld, NULL/*userDN*/, argv[2], argv[3],
  442. compare_groupid, basedn, NULL/*group_out*/);
  443. break;
  444. } /* switch */
  445. if (retval == LDAP_SERVER_DOWN) {
  446. /* retry */
  447. retry = 1;
  448. ldb->ld = 0;
  449. }
  450. else if (retval == LDAPU_SUCCESS) {
  451. fprintf(stderr, "Authentication succeeded.\n");
  452. }
  453. else {
  454. fprintf(stderr, "Authentication failed.\n");
  455. }
  456. }
  457. /* cleanup */
  458. // ldapu_free_LDAPDatabase_t(ldb);
  459. // dbconf_free_dbinfo(db_info);
  460. // ldaputil_exit();
  461. return retval;
  462. }
  463. int main (int argc, char *argv[])
  464. {
  465. int rv;
  466. NSPR_INIT("auth");
  467. if (argc != 4) {
  468. fprintf(stderr, "argc = %d\n", argc);
  469. fprintf(stderr, "usage: %s test_type user_dn group_dn\n", argv[0]);
  470. fprintf(stderr, "\t%s 1 <userdn> <groupdn>\n", argv[0]);
  471. fprintf(stderr, "\t%s 2 <uid> <groupdn>\n", argv[0]);
  472. fprintf(stderr, "\t%s 3 <uid> <groupid>\n", argv[0]);
  473. fprintf(stderr, "\t%s 4 <userdn> <groupid>\n", argv[0]);
  474. fprintf(stderr, "\t%s 5 <userdn> <attrFilter>\n", argv[0]);
  475. fprintf(stderr, "\t%s 6 <uid> <attrFilter>\n", argv[0]);
  476. fprintf(stderr, "\t%s 7 <userdn> <password>\n", argv[0]);
  477. fprintf(stderr, "\t%s 8 <uid> <password>\n", argv[0]);
  478. fprintf(stderr, "\t%s 9 <certmap.conf> <subjectDN>\n", argv[0]);
  479. fprintf(stderr, "\t%s 10 <binddn> <bindpw>\n", argv[0]);
  480. fprintf(stderr, "\t%s 11 <dbmap> <ignore>\n", argv[0]);
  481. fprintf(stderr, "\t%s 12 <newconfig> <oldconfig> ... to test save\n", argv[0]);
  482. fprintf(stderr, "\t%s 13 <newconfig> <oldconfig> ... to test delete\n", argv[0]);
  483. fprintf(stderr, "\t%s 14 <newconfig> <oldconfig> ... to test add\n", argv[0]);
  484. fprintf(stderr, "\t%s 15 <userdn> <groupid>\n", argv[0]);
  485. fprintf(stderr, "\t%s 16 <userCertDescription> <groupid>\n", argv[0]);
  486. exit(LDAP_PARAM_ERROR);
  487. }
  488. rv = perform_test(argc, argv);
  489. /* PR_Exit(); */
  490. return rv;
  491. }