cfg_sspt.c 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661
  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 <stdarg.h>
  43. #include <stdlib.h>
  44. #include <assert.h>
  45. #include "ldap.h"
  46. #include "dsalib.h"
  47. #include "nspr.h"
  48. #include "plstr.h"
  49. #include <string.h>
  50. #define __CFG_SSPT_C
  51. #include "cfg_sspt.h"
  52. /*#define CGI_DEBUG 1*/
  53. #undef TEST_CONFIG /* for testing cn=config40 dummy entry instead of real one */
  54. char* const NULLSTR = 0;
  55. char* const class_top = "top";
  56. char* const class_organization = "organization";
  57. char* const class_organizationalUnit = "organizationalunit";
  58. char* const class_person = "person";
  59. char* const class_organizationalPerson = "organizationalperson";
  60. char* const class_inetOrgPerson = "inetorgperson";
  61. char* const class_groupOfUniqueNames = "groupofuniquenames";
  62. char* const class_domain = "domain";
  63. char* const class_extensibleObject = "extensibleObject";
  64. char* const class_adminDomain = "nsadmindomain";
  65. char* const class_country = "country";
  66. char* const class_locality = "locality";
  67. char* const name_objectClass = "objectclass";
  68. char* const name_cn = "cn";
  69. char* const name_sn = "sn";
  70. char* const name_givenname = "givenname";
  71. char* const name_uid = "uid";
  72. char* const name_userPassword = "userpassword";
  73. char* const name_passwordExpirationTime = "passwordExpirationTime";
  74. char* const name_o = "o";
  75. char* const name_ou = "ou";
  76. char* const name_dc = "dc";
  77. char* const name_member = "member";
  78. char* const name_uniqueMember = "uniquemember";
  79. char* const name_aci = "aci";
  80. char* const name_description = "description";
  81. char* const name_adminDomain = "nsadmindomainname";
  82. char* const name_c = "c";
  83. char* const name_st = "st";
  84. char* const name_l = "l";
  85. char* const value_configAdminGroupCN = "Configuration Administrators";
  86. char* const value_configAdminGroupRDN = "cn=Configuration Administrators";
  87. char* const value_configAdminCN = "Configuration Administrator";
  88. char* const value_configAdminSN = "Administrator";
  89. char* const value_configAdminGN = "Configuration";
  90. char* const value_globalPreferencesOU = "Global Preferences";
  91. char* const value_hostPreferencesOU = "Host Preferences";
  92. char* const value_netscapeConfigDesc = "Standard branch for configuration information";
  93. char* const value_peopleOU = "People";
  94. char* const value_peopleDesc = "Standard branch for people (uid) entries";
  95. char* const value_groupsOU = "Groups";
  96. char* const value_groupsDesc = "Standard Branch for group entries";
  97. #ifdef TEST_CONFIG
  98. char* const value_config40 = "config40";
  99. char* const value_config40DN = "cn=config40";
  100. #endif /* TEST_CONFIG */
  101. char* dbg_log_file = "ds_sscfg.log";
  102. char* const name_netscaperoot = "NetscapeRoot";
  103. char* const name_netscaperootDN = "o=NetscapeRoot";
  104. char* const name_topology = "TopologyManagement";
  105. char* const name_topologyRDN = "ou=TopologyManagement";
  106. char* const value_topologyDESC = "Branch for Configuration Administration users and groups";
  107. char* const name_administratorsOU = "Administrators";
  108. char* const name_administratorsRDN = "ou=Administrators";
  109. char* const value_administratorsDESC = "Standard branch for Configuration Administrator (uid) entries";
  110. char* const name_localDAGroup = "Directory Administrators";
  111. char* const value_localDAGroupDesc = "Entities with administrative access to this directory server";
  112. static char* const ACI_self_allow = "(targetattr=\""
  113. "carLicense ||"
  114. "description ||"
  115. "displayName ||"
  116. "facsimileTelephoneNumber ||"
  117. "homePhone ||"
  118. "homePostalAddress ||"
  119. "initials ||"
  120. "jpegPhoto ||"
  121. "labeledURL ||"
  122. "mail ||"
  123. "mobile ||"
  124. "pager ||"
  125. "photo ||"
  126. "postOfficeBox ||"
  127. "postalAddress ||"
  128. "postalCode ||"
  129. "preferredDeliveryMethod ||"
  130. "preferredLanguage ||"
  131. "registeredAddress ||"
  132. "roomNumber ||"
  133. "secretary ||"
  134. "seeAlso ||"
  135. "st ||"
  136. "street ||"
  137. "telephoneNumber ||"
  138. "telexNumber ||"
  139. "title ||"
  140. "userCertificate ||"
  141. "userPassword ||"
  142. "userSMIMECertificate ||"
  143. "x500UniqueIdentifier\")"
  144. "(version 3.0; acl \"Enable self write for common attributes\"; allow (write) "
  145. "userdn=\"ldap:///self\";)";
  146. static char* const ACI_anonymous_allow = "(targetattr!=\"userPassword\")"
  147. "(version 3.0; "
  148. "acl \"Enable anonymous access\"; allow (read, search, compare)"
  149. "userdn=\"ldap:///anyone\";)";
  150. static char* const ACI_anonymous_allow_with_filter =
  151. "(targetattr=\"*\")(targetfilter=(%s))"
  152. "(version 3.0; acl \"Default anonymous access\"; "
  153. "allow (read, search) userdn=\"ldap:///anyone\";)";
  154. static char* const ACI_config_admin_group_allow_all = "(targetattr=\"*\")"
  155. "(version 3.0; "
  156. "acl \"Enable Configuration Administrator Group modification\"; "
  157. "allow (all) groupdn=\"ldap:///%s, %s=%s, %s, %s\";)";
  158. static char* const ACI_config_admin_group_allow = "(targetattr=\"*\")"
  159. "(version 3.0; "
  160. "acl \"Configuration Administrators Group\"; allow (%s) "
  161. "groupdn=\"ldap:///%s\";)";
  162. static char* const ACI_local_DA_allow = "(targetattr = \"*\")(version 3.0; "
  163. "acl \"Local Directory Administrators Group\"; allow (%s) "
  164. "groupdn=\"ldap:///%s\";)";
  165. static char* const ACI_group_expansion = "(targetattr=\"*\")"
  166. "(version 3.0; acl \"Enable Group Expansion\"; "
  167. "allow (read, search, compare) groupdnattr=\"uniquemember\";)";
  168. static char* const ACI_user_allow_1 = "(targetattr=\"*\")(version 3.0; "
  169. "acl \"Configuration Administrator\"; allow (%s) "
  170. "userdn=\"ldap:///uid=%s, %s\";)";
  171. static char* const ACI_user_allow_2 = "(targetattr=\"*\")(version 3.0; "
  172. "acl \"Configuration Administrator\"; allow (%s) "
  173. "userdn=\"ldap:///%s\";)";
  174. /*
  175. This is a list of DSE entries that the Configuration Admin Group has
  176. access to and the access rights for that entry
  177. */
  178. static struct _DSEEntriesAndAccess {
  179. char *entryDN;
  180. char *access;
  181. } entryAndAccessList[] = {
  182. {"cn=config", "all"},
  183. {"cn=schema", "all"}
  184. };
  185. static int entryAndAccessListSize =
  186. sizeof(entryAndAccessList)/sizeof(entryAndAccessList[0]);
  187. int
  188. getEntryAndAccess(int index, const char **entry, const char **access)
  189. {
  190. if (!entry || !access)
  191. return 0;
  192. *entry = 0;
  193. *access = 0;
  194. if (index < 0 || index >= entryAndAccessListSize)
  195. return 0;
  196. *entry = entryAndAccessList[index].entryDN;
  197. *access = entryAndAccessList[index].access;
  198. return 1;
  199. }
  200. static int
  201. is_root_user(const char *name, QUERY_VARS* query)
  202. {
  203. if (!name || !query->rootDN) {
  204. return 0;
  205. }
  206. return !PL_strcasecmp(name, query->rootDN);
  207. }
  208. /*
  209. ** ---------------------------------------------------------------------------
  210. **
  211. ** Utility Routines - Functions for performing string and file operations.
  212. **
  213. */
  214. #ifdef CGI_DEBUG
  215. #include <stdarg.h>
  216. static void debug_log (const char* file, const char* format, ...)
  217. #ifdef __GNUC__
  218. __attribute__ ((format (printf, 2, 3)));
  219. #else
  220. ;
  221. #endif
  222. static void
  223. debug_log (const char* file, const char* format, ...)
  224. {
  225. va_list args;
  226. FILE* fp = fopen(file, "a+");
  227. if (fp) {
  228. va_start(args, format);
  229. vfprintf(fp, format, args);
  230. va_end(args);
  231. fflush(fp);
  232. fclose(fp);
  233. }
  234. }
  235. static void
  236. debug_log_array (const char* file, char* name, char** vals)
  237. {
  238. FILE* fp = fopen(file, "a+");
  239. if (fp) {
  240. if (vals != NULL) {
  241. for (; *vals != NULL; LDAP_UTF8INC(vals)) {
  242. fprintf (fp, "%s: %s\n", name, *vals);
  243. }
  244. fflush(fp);
  245. }
  246. fclose(fp);
  247. }
  248. }
  249. #endif /* CGI_DEBUG */
  250. static char *
  251. extract_name_from_dn(const char *dn)
  252. {
  253. char **rdnList = 0;
  254. char *ret = 0;
  255. if (!dn)
  256. return ret;
  257. rdnList = ldap_explode_dn(dn, 1); /* leave out types */
  258. if (!rdnList || !rdnList[0])
  259. ret = strdup(dn); /* the given dn is not really a dn */
  260. else
  261. ret = strdup(rdnList[0]);
  262. if (rdnList)
  263. ldap_value_free(rdnList);
  264. return ret;
  265. }
  266. int
  267. entry_exists(LDAP* ld, const char* entrydn)
  268. {
  269. int exists = 0;
  270. int err;
  271. struct timeval sto = { 10L, 0L };
  272. LDAPMessage* pLdapResult;
  273. err = ldap_search_st(ld, entrydn, LDAP_SCOPE_BASE,
  274. "objectClass=*", NULL, 0, &sto, &pLdapResult);
  275. if (err == LDAP_SUCCESS)
  276. {
  277. LDAPMessage* pLdapEntry;
  278. char* dn;
  279. for (pLdapEntry = ldap_first_entry(ld, pLdapResult);
  280. pLdapEntry != NULL;
  281. pLdapEntry = ldap_next_entry(ld, pLdapEntry))
  282. {
  283. if ((dn = ldap_get_dn(ld, pLdapEntry)) != NULL)
  284. {
  285. exists = 1;
  286. free(dn);
  287. /*ldap_memfree(dn);*/
  288. break;
  289. }
  290. }
  291. ldap_msgfree(pLdapResult);
  292. }
  293. return exists;
  294. }
  295. int
  296. add_aci(LDAP* ld, char* DN, char* privilege)
  297. {
  298. int err;
  299. int ret = 0;
  300. LDAPMod mod;
  301. LDAPMod* mods[2];
  302. char* aci[2];
  303. #ifdef CGI_DEBUG
  304. debug_log (dbg_log_file, "add_aci('%s', '%s')\n",
  305. DN ? DN : "NULL",
  306. privilege ? privilege : "NULL");
  307. #endif
  308. if (ld == NULL || DN == NULL || privilege == NULL)
  309. {
  310. return -1;
  311. }
  312. mods[0] = &mod;
  313. mods[1] = NULL;
  314. mod.mod_op = LDAP_MOD_ADD;
  315. mod.mod_type = name_aci;
  316. mod.mod_values = aci;
  317. aci[0] = privilege;
  318. aci[1] = NULL;
  319. /* fprintf (stdout, "ldap_modify_s('%s')<br>\n",DN); fflush (stdout); */
  320. err = ldap_modify_s (ld, DN, mods);
  321. if (err != LDAP_SUCCESS && err != LDAP_TYPE_OR_VALUE_EXISTS) {
  322. char* exp = "can't add privilege. ";
  323. char* explanation = PR_smprintf("%s (%i) returned from ldap_modify_s(%s, %i). Privilege: %s",
  324. ldap_err2string (err), err, DN, LDAP_MOD_ADD, aci[0]);
  325. ds_report_warning (DS_INCORRECT_USAGE, exp, explanation);
  326. PR_smprintf_free (explanation);
  327. ret = 1;
  328. }
  329. return ret;
  330. }
  331. /*
  332. Same as add_aci, except that the 3rd parameter is a format string
  333. in printf style format, and the 4th - Nth parameters are a NULL terminated
  334. list of strings to substitute in the format; basically just constructs
  335. the correct aci string and passes it to add_aci
  336. */
  337. int add_aci_v(LDAP* ld, char* DN, char* format, ...)
  338. #ifdef __GNUC__
  339. __attribute__ ((format (printf, 3, 4)));
  340. #else
  341. ;
  342. #endif
  343. int
  344. add_aci_v(LDAP* ld, char* DN, char* format, ...)
  345. {
  346. char* acistring = NULL;
  347. int len = 0;
  348. int status = 0;
  349. int fudge = 10; /* a little extra just to make sure */
  350. char *s = 0;
  351. va_list ap;
  352. #ifdef CGI_DEBUG
  353. debug_log (dbg_log_file, "add_aci_v('%s', '%s')\n",
  354. DN ? DN : "NULL",
  355. format ? format : "NULL");
  356. #endif
  357. if (ld == NULL || DN == NULL || format == NULL)
  358. {
  359. return -1;
  360. }
  361. /* determine the length of the string to allocate to hold
  362. the aci string
  363. */
  364. len += strlen(format) + fudge;
  365. va_start(ap, format);
  366. s = va_arg(ap, char*);
  367. while (s)
  368. {
  369. len += strlen(s) + 1;
  370. s = va_arg(ap, char*);
  371. }
  372. va_end(ap);
  373. va_start(ap, format);
  374. acistring = (char *)malloc(len);
  375. vsprintf(acistring, format, ap);
  376. va_end(ap);
  377. status = add_aci(ld, DN, acistring);
  378. free(acistring);
  379. return status;
  380. }
  381. /*
  382. Make a dn from lists of dn components. The format argument is in the
  383. standard printf format. The varargs list contains the various dn
  384. components. The string returned is malloc()'d and must be free()'d by
  385. the caller after use. example:
  386. make_dn("cn=%s, ou=%s, %s", "Admins", "TopologyManagement", "o=NetscapeRoot", NULL)
  387. returns
  388. "cn=Admins, ou=TopologyManagement, o=NetscapeRoot"
  389. */
  390. char *
  391. make_dn(const char* format, ...)
  392. {
  393. char *s;
  394. int len = 0;
  395. int fudge = 3;
  396. va_list ap;
  397. char *dnstring;
  398. #ifdef CGI_DEBUG
  399. debug_log (dbg_log_file, "make_dn('%s', ...)\n",
  400. format ? format : "NULL");
  401. #endif
  402. if (format == NULL)
  403. {
  404. return NULL;
  405. }
  406. /* determine the length of the string to allocate to hold
  407. the dn string
  408. */
  409. len += strlen(format) + fudge;
  410. va_start(ap, format);
  411. s = va_arg(ap, char*);
  412. while (s)
  413. {
  414. len += strlen(s) + 3;
  415. s = va_arg(ap, char*);
  416. }
  417. va_end(ap);
  418. va_start(ap, format);
  419. dnstring = (char *)malloc(len);
  420. vsprintf(dnstring, format, ap);
  421. va_end(ap);
  422. return dnstring;
  423. }
  424. char *
  425. admin_user_exists(LDAP* ld, char* base, char *userID)
  426. {
  427. int exists = 0;
  428. int err;
  429. char search_str[MAX_STRING_LEN];
  430. struct timeval sto = { 10L, 0L };
  431. LDAPMessage* pLdapResult;
  432. PR_snprintf (search_str, sizeof(search_str), "uid=%s*", userID ? userID : "admin");
  433. err = ldap_search_st(ld, base, LDAP_SCOPE_SUBTREE,
  434. search_str, NULL, 0, &sto, &pLdapResult);
  435. if (err == LDAP_SUCCESS)
  436. {
  437. LDAPMessage* pLdapEntry;
  438. char* dn = NULL;
  439. for (pLdapEntry = ldap_first_entry(ld, pLdapResult);
  440. pLdapEntry != NULL;
  441. pLdapEntry = ldap_next_entry(ld, pLdapEntry))
  442. {
  443. if ((dn = ldap_get_dn(ld, pLdapEntry)) != NULL)
  444. {
  445. exists = 1;
  446. /*ldap_memfree(dn);*/
  447. break;
  448. }
  449. }
  450. ldap_msgfree(pLdapResult);
  451. return dn;
  452. }
  453. return NULL;
  454. }
  455. static void
  456. getUIDFromDN(const char *userID, char *uid)
  457. {
  458. char **rdnListTypes = 0;
  459. char **rdnListNoTypes = 0;
  460. int ii = 0;
  461. int uidindex = -1;
  462. uid[0] = 0;
  463. rdnListTypes = ldap_explode_dn(userID, 0);
  464. if (!rdnListTypes)
  465. return; /* userID is not a DN */
  466. /* find the first rdn in the given userID DN which begins with
  467. "uid=" */
  468. for (ii = 0; uidindex < 0 && rdnListTypes[ii]; ++ii)
  469. {
  470. if (!PL_strncasecmp(rdnListTypes[ii], "uid=", 4))
  471. uidindex = ii;
  472. }
  473. ldap_value_free(rdnListTypes);
  474. if (uidindex < 0) /* did not find an rdn beginning with "uid=" */
  475. return;
  476. rdnListNoTypes = ldap_explode_dn(userID, 1);
  477. PL_strncpyz(uid, rdnListNoTypes[uidindex], 1024);
  478. ldap_value_free(rdnListNoTypes);
  479. return;
  480. }
  481. static char *
  482. create_ssadmin_user(LDAP* ld, char *base, char* userID, char* password)
  483. {
  484. int err;
  485. char *ret = 0;
  486. char entrydn[1024] = {0};
  487. char realuid[1024] = {0};
  488. char *admin_dn = NULL;
  489. #ifdef CGI_DEBUG
  490. debug_log (dbg_log_file, "create_ssadmin_user('%s','%s','%s')\n",
  491. base ? base : "NULL", userID ? userID : "NULL",
  492. password ? password : "NULL");
  493. #endif
  494. if (ld == NULL || base == NULL || userID == NULL || *userID == '\0' ||
  495. password == NULL || *password == '\0')
  496. {
  497. return NULL;
  498. }
  499. getUIDFromDN(userID, realuid);
  500. if (realuid[0])
  501. {
  502. PL_strncpyz(entrydn, userID, sizeof(entrydn));
  503. if (entry_exists(ld, entrydn))
  504. admin_dn = entrydn;
  505. }
  506. else
  507. {
  508. PR_snprintf(entrydn, sizeof(entrydn), "%s=%s, %s", name_uid, userID, base);
  509. admin_dn = admin_user_exists(ld, base, userID);
  510. PL_strncpyz(realuid, userID, sizeof(realuid));
  511. }
  512. if (admin_dn)
  513. {
  514. char error[BIG_LINE];
  515. PR_snprintf(error, sizeof(error), "A user with uid=%s \"%s\" already exists in the directory"
  516. " and will not be overwritten.", realuid[0] ? realuid : "admin", admin_dn);
  517. ds_send_error(error, 0);
  518. return admin_dn;
  519. }
  520. else
  521. {
  522. LDAPMod* attrs[8];
  523. LDAPMod attr[7];
  524. char* objectClasses[5];
  525. char* cn[2];
  526. char* sn[2];
  527. char* givenname[2];
  528. char* uid[2];
  529. char* userPassword[2];
  530. char* passwordExpirationTime[2];
  531. attrs[0] = &attr[0];
  532. attrs[1] = &attr[1];
  533. attrs[2] = &attr[2];
  534. attrs[3] = &attr[3];
  535. attrs[4] = &attr[4];
  536. attrs[5] = &attr[5];
  537. attrs[6] = &attr[6];
  538. attrs[7] = NULL;
  539. attr[0].mod_op = LDAP_MOD_ADD;
  540. attr[0].mod_type = name_objectClass;
  541. attr[0].mod_values = objectClasses;
  542. objectClasses[0] = class_top;
  543. objectClasses[1] = class_person;
  544. objectClasses[2] = class_organizationalPerson;
  545. objectClasses[3] = class_inetOrgPerson;
  546. objectClasses[4] = NULL;
  547. attr[1].mod_op = LDAP_MOD_ADD;
  548. attr[1].mod_type = name_cn;
  549. attr[1].mod_values = cn;
  550. cn[0] = value_configAdminCN;
  551. cn[1] = NULL;
  552. attr[2].mod_op = LDAP_MOD_ADD;
  553. attr[2].mod_type = name_sn;
  554. attr[2].mod_values = sn;
  555. sn[0] = value_configAdminSN;
  556. sn[1] = NULL;
  557. attr[3].mod_op = LDAP_MOD_ADD;
  558. attr[3].mod_type = name_givenname;
  559. attr[3].mod_values = givenname;
  560. givenname[0] = value_configAdminGN;
  561. givenname[1] = NULL;
  562. attr[4].mod_op = LDAP_MOD_ADD;
  563. attr[4].mod_type = name_uid;
  564. attr[4].mod_values = uid;
  565. uid[0] = realuid;
  566. uid[1] = NULL;
  567. attr[5].mod_op = LDAP_MOD_ADD;
  568. attr[5].mod_type = name_userPassword;
  569. attr[5].mod_values = userPassword;
  570. userPassword[0] = password;
  571. userPassword[1] = NULL;
  572. attr[6].mod_op = LDAP_MOD_ADD;
  573. attr[6].mod_type = name_passwordExpirationTime;
  574. attr[6].mod_values = passwordExpirationTime;
  575. passwordExpirationTime[0] = "20380119031407Z";
  576. passwordExpirationTime[1] = NULL;
  577. /* fprintf (stdout, "ldap_add_s(%s)<br>\n", entrydn); fflush (stdout); */
  578. err = ldap_add_s (ld, entrydn, attrs);
  579. if (err != LDAP_SUCCESS)
  580. {
  581. char *explanation = PR_smprintf("Unable to create administrative user."
  582. " (%s (%i) returned from ldap_add_s(%s))",
  583. ldap_err2string (err), err, entrydn);
  584. ds_report_warning (DS_NETWORK_ERROR, " can't create user", explanation);
  585. PR_smprintf_free (explanation);
  586. ret = NULL;
  587. }
  588. }
  589. return NULL;
  590. }
  591. static int
  592. create_base_entry(
  593. LDAP* ld,
  594. char* basedn,
  595. char *naming_attr_type,
  596. char *naming_attr_value,
  597. char *objectclassname
  598. )
  599. {
  600. int err;
  601. int ret = 0;
  602. #ifdef CGI_DEBUG
  603. debug_log (dbg_log_file, "create_base_entry('%s','%s')\n",
  604. basedn ? basedn : "NULL", naming_attr_value: "NULL");
  605. #endif
  606. if (ld == NULL || basedn == NULL || *basedn == '\0')
  607. {
  608. return -1;
  609. }
  610. if (!entry_exists(ld, basedn))
  611. {
  612. LDAPMod* attrs[3];
  613. LDAPMod attr[2];
  614. char* objectClasses[3];
  615. char* names[2];
  616. attrs[0] = &attr[0];
  617. attrs[2] = NULL;
  618. attr[0].mod_op = LDAP_MOD_ADD;
  619. attr[0].mod_type = name_objectClass;
  620. attr[0].mod_values = objectClasses;
  621. objectClasses[0] = class_top;
  622. objectClasses[1] = objectclassname;
  623. objectClasses[2] = NULL;
  624. attrs[1] = &attr[1];
  625. attr[1].mod_op = LDAP_MOD_ADD;
  626. attr[1].mod_type = naming_attr_type;
  627. attr[1].mod_values = names;
  628. names[0] = naming_attr_value;
  629. names[1] = NULL;
  630. /* fprintf (stdout, "ldap_add_s(%s)<br>\n", basedn); fflush (stdout); */
  631. err = ldap_add_s (ld, basedn, attrs);
  632. if (err != LDAP_SUCCESS)
  633. {
  634. char* explanation = PR_smprintf("Unable to create base entry."
  635. " (%s (%i) returned from ldap_add_s(%s))",
  636. ldap_err2string (err), err, basedn);
  637. ds_report_warning (DS_NETWORK_ERROR, " can't create base entry",
  638. explanation);
  639. PR_smprintf_free (explanation);
  640. ret = 1;
  641. }
  642. }
  643. return ret;
  644. }
  645. static int
  646. create_organization(LDAP* ld, char* base, char* org)
  647. {
  648. return create_base_entry(ld, base, name_o, org, class_organization);
  649. }
  650. static int
  651. create_organizational_unit(LDAP* ld, char* base, char* unit, char *description,
  652. char *extra_objectclassName,
  653. char *extra_attrName,
  654. char *extra_attrValue)
  655. {
  656. int err;
  657. int ret = 0;
  658. char *entrydn = NULL;
  659. #ifdef CGI_DEBUG
  660. debug_log (dbg_log_file, "create_organizational_unit('%s','%s')\n",
  661. base ? base : "NULL", unit ? unit : "NULL");
  662. #endif
  663. if (ld == NULL || unit == NULL || *unit == '\0')
  664. {
  665. return -1;
  666. }
  667. /*
  668. if base is null, assume the unit is the full DN of the entry
  669. to create; this assumes the caller knows what he/she is doing
  670. and has already created the parent entry(ies)
  671. */
  672. if (!base)
  673. entrydn = strdup(unit);
  674. else
  675. entrydn = make_dn("%s=%s, %s", name_ou, unit, base, NULLSTR);
  676. if (!entry_exists(ld, entrydn))
  677. {
  678. LDAPMod* attrs[5];
  679. LDAPMod attr[4];
  680. char* objectClasses[4];
  681. char* names[2];
  682. char* desc[2];
  683. char* extra[2];
  684. char *baseName = unit;
  685. int attrnum = 0;
  686. if (base)
  687. {
  688. baseName = strdup(unit);
  689. }
  690. else
  691. {
  692. /* since the unit is in DN form, we need to extract something to
  693. use for the ou: attribute */
  694. baseName = extract_name_from_dn(unit);
  695. }
  696. attrs[0] = &attr[0];
  697. attrs[1] = &attr[1];
  698. attrs[2] = NULL;
  699. attr[0].mod_op = LDAP_MOD_ADD;
  700. attr[0].mod_type = name_objectClass;
  701. attr[0].mod_values = objectClasses;
  702. objectClasses[0] = class_top;
  703. objectClasses[1] = class_organizationalUnit;
  704. objectClasses[2] = extra_objectclassName; /* may be null */
  705. objectClasses[3] = NULL;
  706. attr[1].mod_op = LDAP_MOD_ADD;
  707. attr[1].mod_type = name_ou;
  708. attr[1].mod_values = names;
  709. names[0] = baseName;
  710. names[1] = NULL;
  711. attrnum = 2;
  712. if (description && *description)
  713. {
  714. attr[attrnum].mod_op = LDAP_MOD_ADD;
  715. attr[attrnum].mod_type = name_description;
  716. attr[attrnum].mod_values = desc;
  717. desc[0] = description;
  718. desc[1] = NULL;
  719. attrs[attrnum] = &attr[attrnum];
  720. attrs[++attrnum] = NULL;
  721. }
  722. if (extra_attrName && extra_attrValue &&
  723. *extra_attrName && *extra_attrValue)
  724. {
  725. attr[attrnum].mod_op = LDAP_MOD_ADD;
  726. attr[attrnum].mod_type = extra_attrName;
  727. attr[attrnum].mod_values = extra;
  728. extra[0] = extra_attrValue;
  729. extra[1] = NULL;
  730. attrs[attrnum] = &attr[attrnum];
  731. attrs[++attrnum] = NULL;
  732. }
  733. /* fprintf (stdout, "ldap_add_s(%s)<br>\n", DN); fflush (stdout); */
  734. err = ldap_add_s (ld, entrydn, attrs);
  735. if (baseName)
  736. free(baseName);
  737. if (err != LDAP_SUCCESS)
  738. {
  739. char* explanation = PR_smprintf("Unable to create organizational unit."
  740. " (%s (%i) returned from ldap_add_s(%s))",
  741. ldap_err2string (err), err, entrydn);
  742. ds_report_warning (DS_NETWORK_ERROR, " can't create organizational unit",
  743. explanation);
  744. PR_smprintf_free (explanation);
  745. ret = 1;
  746. }
  747. }
  748. if (entrydn)
  749. free(entrydn);
  750. return ret;
  751. }
  752. static int
  753. create_domain_component(LDAP* ld, char* base, char* domcomp)
  754. {
  755. return create_base_entry(ld, base, name_dc, domcomp, class_domain);
  756. }
  757. static int
  758. create_country(LDAP* ld, char* base, char* country)
  759. {
  760. return create_base_entry(ld, base, name_c, country, class_country);
  761. }
  762. static int
  763. create_state(LDAP* ld, char* base, char* state)
  764. {
  765. return create_base_entry(ld, base, name_st, state, class_locality);
  766. }
  767. static int
  768. create_locality(LDAP* ld, char* base, char* locality)
  769. {
  770. return create_base_entry(ld, base, name_l, locality, class_locality);
  771. }
  772. static int
  773. create_base(LDAP* ld, char* base)
  774. {
  775. int ret = 0;
  776. char* attr;
  777. char **rdnList = 0;
  778. char **rdnListNoTypes = 0;
  779. enum BASETYPE { unknown, org, orgunit, domcomp, country, state, locality } base_type = unknown;
  780. #ifdef CGI_DEBUG
  781. debug_log (dbg_log_file, "create_base('%s')\n", base ? base : "NULL");
  782. #endif
  783. if (ld == NULL || base == NULL || *base == '\0')
  784. {
  785. return -1;
  786. }
  787. rdnList = ldap_explode_dn(base, 0);
  788. if (!rdnList)
  789. {
  790. char error[BIG_LINE];
  791. PR_snprintf(error, sizeof(error), "The given base suffix [%s] is not a valid DN", base);
  792. ds_send_error(error, 0);
  793. return -1;
  794. }
  795. if (PL_strncasecmp(rdnList[0], "o=", 2) == 0)
  796. {
  797. base_type = org;
  798. }
  799. else if (PL_strncasecmp(rdnList[0], "ou=", 3) == 0)
  800. {
  801. base_type = orgunit;
  802. }
  803. else if (PL_strncasecmp(rdnList[0], "dc=", 3) == 0)
  804. {
  805. base_type = domcomp;
  806. }
  807. else if (PL_strncasecmp(rdnList[0], "c=", 2) == 0)
  808. {
  809. base_type = country;
  810. }
  811. else if (PL_strncasecmp(rdnList[0], "st=", 3) == 0)
  812. {
  813. base_type = state;
  814. }
  815. else if (PL_strncasecmp(rdnList[0], "l=", 2) == 0)
  816. {
  817. base_type = locality;
  818. }
  819. else
  820. {
  821. ds_report_warning (DS_INCORRECT_USAGE, " Unable to create the root suffix.",
  822. "In order to create the root suffix in the directory, you must "
  823. "specify a distinguished name beginning with o=, ou=, dc=, c=, st=, or l=. "
  824. "If you wish to use something else for your root suffix, you "
  825. "should first create the directory with one of these suffixes, then you can "
  826. "create additional suffixes in any form you choose."
  827. );
  828. return -1;
  829. }
  830. ldap_value_free(rdnList);
  831. /*
  832. We need to extract from the base the value to use for the attribute
  833. name_attr e.g. ou: foo or o: org.
  834. */
  835. rdnListNoTypes = ldap_explode_dn(base, 1);
  836. attr = rdnListNoTypes[0];
  837. if (!entry_exists(ld, base))
  838. {
  839. if (base_type == org)
  840. {
  841. ret = create_organization(ld, base, attr);
  842. }
  843. else if (base_type == orgunit)
  844. {
  845. /* this function is smart enough to extract the name from the DN */
  846. ret = create_organizational_unit(ld, 0, base, 0, 0, 0, 0);
  847. }
  848. else if (base_type == domcomp)
  849. {
  850. ret = create_domain_component(ld, base, attr);
  851. }
  852. else if (base_type == country)
  853. {
  854. ret = create_country(ld, base, attr);
  855. }
  856. else if (base_type == state)
  857. {
  858. ret = create_state(ld, base, attr);
  859. }
  860. else if (base_type == locality)
  861. {
  862. ret = create_locality(ld, base, attr);
  863. }
  864. }
  865. ldap_value_free(rdnListNoTypes);
  866. /* now add the anon search and self mod acis */
  867. if (!ret)
  868. {
  869. ret = add_aci(ld, base, ACI_anonymous_allow);
  870. if (!ret)
  871. ret = add_aci(ld, base, ACI_self_allow);
  872. }
  873. return ret;
  874. }
  875. static int
  876. create_NetscapeRoot(LDAP* ld, const char *DN)
  877. {
  878. /*
  879. dn: o=NetscapeRoot
  880. o: NetscapeRoot
  881. objectclass: top
  882. objectclass: organization
  883. */
  884. int err;
  885. int ret = 0;
  886. #ifdef CGI_DEBUG
  887. debug_log (dbg_log_file, "create_NetscapeRoot()\n");
  888. #endif
  889. if (ld == NULL)
  890. {
  891. return -1;
  892. }
  893. if (!entry_exists(ld, DN))
  894. {
  895. LDAPMod* attrs[4];
  896. LDAPMod attr[3];
  897. char* objectClasses[4];
  898. char* names[2];
  899. attrs[0] = &attr[0];
  900. attrs[3] = NULL;
  901. attr[0].mod_op = LDAP_MOD_ADD;
  902. attr[0].mod_type = name_objectClass;
  903. attr[0].mod_values = objectClasses;
  904. objectClasses[0] = class_top;
  905. objectClasses[1] = class_organization;
  906. objectClasses[2] = NULL;
  907. attrs[1] = &attr[1];
  908. attr[1].mod_op = LDAP_MOD_ADD;
  909. attr[1].mod_type = name_o;
  910. attr[1].mod_values = names;
  911. names[0] = name_netscaperoot;
  912. names[1] = NULL;
  913. attrs[2] = NULL;
  914. /* fprintf (stdout, "ldap_add_s(%s)<br>\n", DN); fflush (stdout); */
  915. err = ldap_add_s (ld, DN, attrs);
  916. if (err != LDAP_SUCCESS)
  917. {
  918. char* explanation = PR_smprintf("Unable to create %s."
  919. " (%s (%i) returned from ldap_add_s(%s))",
  920. name_netscaperoot, ldap_err2string (err), err,
  921. DN);
  922. ds_report_warning (DS_NETWORK_ERROR, " can't create NetscapeRoot",
  923. explanation);
  924. PR_smprintf_free (explanation);
  925. ret = 1;
  926. }
  927. }
  928. return ret;
  929. }
  930. #ifdef TEST_CONFIG
  931. static int
  932. create_configEntry(LDAP* ld)
  933. {
  934. /*
  935. dn: cn=config40
  936. objectclass: top
  937. objectclass: extensibleObject
  938. cn: config40
  939. */
  940. char *entrydn = NULL;
  941. int err;
  942. int ret = 0;
  943. #ifdef CGI_DEBUG
  944. debug_log (dbg_log_file, "create_configEntry()\n");
  945. #endif
  946. if (ld == NULL)
  947. {
  948. return -1;
  949. }
  950. entrydn = make_dn("%s=%s", name_cn, value_config40, NULLSTR);
  951. if (!entry_exists(ld, entrydn))
  952. {
  953. LDAPMod* attrs[3];
  954. LDAPMod attr[2];
  955. char* objectClasses[3];
  956. char* names[2];
  957. attrs[0] = &attr[0];
  958. attrs[2] = NULL;
  959. attr[0].mod_op = LDAP_MOD_ADD;
  960. attr[0].mod_type = name_objectClass;
  961. attr[0].mod_values = objectClasses;
  962. objectClasses[0] = class_top;
  963. objectClasses[1] = class_extensibleObject;
  964. objectClasses[2] = NULL;
  965. attrs[1] = &attr[1];
  966. attr[1].mod_op = LDAP_MOD_ADD;
  967. attr[1].mod_type = name_cn;
  968. attr[1].mod_values = names;
  969. names[0] = value_config40;
  970. names[1] = NULL;
  971. /* fprintf (stdout, "ldap_add_s(%s)<br>\n", DN); fflush (stdout); */
  972. err = ldap_add_s (ld, entrydn, attrs);
  973. if (err != LDAP_SUCCESS)
  974. {
  975. char* explanation = PR_smprintf("Unable to create %s."
  976. " (%s (%i) returned from ldap_add_s(%s))",
  977. value_config40, ldap_err2string (err), err, entrydn);
  978. ds_report_warning (DS_NETWORK_ERROR, " can't create config40",
  979. explanation);
  980. PR_smprintf_free (explanation);
  981. ret = 1;
  982. }
  983. }
  984. if (entrydn)
  985. free(entrydn);
  986. return ret;
  987. }
  988. #endif
  989. int
  990. create_group(LDAP* ld, char* base, char* group)
  991. {
  992. int err;
  993. int ret = 0;
  994. LDAPMod* attrs[3];
  995. LDAPMod attr[2];
  996. char* objectClasses[3];
  997. char* names[2];
  998. char *entrydn = 0;
  999. #ifdef CGI_DEBUG
  1000. debug_log (dbg_log_file, "create_group('%s','%s')\n",
  1001. base ? base : "NULL", group ? group : "NULL");
  1002. #endif
  1003. if (ld == NULL || base == NULL || *base == '\0' ||
  1004. group == NULL || *group == '\0')
  1005. {
  1006. return -1;
  1007. }
  1008. entrydn = make_dn("%s=%s, %s", name_cn, group, base, NULLSTR);
  1009. if (!entry_exists(ld, entrydn))
  1010. {
  1011. attrs[0] = &attr[0];
  1012. attrs[1] = &attr[1];
  1013. attrs[2] = NULL;
  1014. attr[0].mod_op = LDAP_MOD_ADD;
  1015. attr[0].mod_type = name_objectClass;
  1016. attr[0].mod_values = objectClasses;
  1017. objectClasses[0] = class_top;
  1018. objectClasses[1] = class_groupOfUniqueNames;
  1019. objectClasses[2] = NULL;
  1020. attr[1].mod_op = LDAP_MOD_ADD;
  1021. attr[1].mod_type = name_cn;
  1022. attr[1].mod_values = names;
  1023. names[0] = group;
  1024. names[1] = NULL;
  1025. /* fprintf (stdout, "ldap_add_s(%s)<br>\n", entrydn); fflush (stdout); */
  1026. err = ldap_add_s (ld, entrydn, attrs);
  1027. if (err != LDAP_SUCCESS)
  1028. {
  1029. char* explanation = PR_smprintf("Unable to create group."
  1030. " (%s (%i) returned from ldap_add_s(%s))",
  1031. ldap_err2string (err), err, entrydn);
  1032. ds_report_warning (DS_NETWORK_ERROR, " can't create group", explanation);
  1033. PR_smprintf_free (explanation);
  1034. ret = 1;
  1035. }
  1036. }
  1037. if (entrydn)
  1038. free(entrydn);
  1039. return ret;
  1040. }
  1041. int
  1042. create_consumer_dn(LDAP* ld, char* dn, char* hashedpw)
  1043. {
  1044. int err;
  1045. int ret = 0;
  1046. LDAPMod* attrs[7];
  1047. LDAPMod attr[6];
  1048. char* objectClasses[3];
  1049. char* names[2];
  1050. char* snames[2];
  1051. char* desc[2];
  1052. char* pwd[2];
  1053. char* passwordExpirationTime[2];
  1054. #ifdef CGI_DEBUG
  1055. debug_log (dbg_log_file, "create_consumer_dn('%s','%s')\n",
  1056. dn ? dn : "NULL", hashedpw ? hashedpw : "NULL");
  1057. #endif
  1058. if (ld == NULL || dn == NULL || hashedpw == NULL)
  1059. {
  1060. return -1;
  1061. }
  1062. if (!entry_exists(ld, dn))
  1063. {
  1064. attrs[0] = &attr[0];
  1065. attrs[1] = &attr[1];
  1066. attrs[2] = &attr[2];
  1067. attrs[3] = &attr[3];
  1068. attrs[4] = &attr[4];
  1069. attrs[5] = &attr[5];
  1070. attrs[6] = NULL;
  1071. attr[0].mod_op = LDAP_MOD_ADD;
  1072. attr[0].mod_type = name_objectClass;
  1073. attr[0].mod_values = objectClasses;
  1074. objectClasses[0] = class_top;
  1075. objectClasses[1] = class_person;
  1076. objectClasses[2] = NULL;
  1077. attr[1].mod_op = LDAP_MOD_ADD;
  1078. attr[1].mod_type = name_cn;
  1079. attr[1].mod_values = names;
  1080. names[0] = "Replication Consumer";
  1081. names[1] = NULL;
  1082. attr[2].mod_op = LDAP_MOD_ADD;
  1083. attr[2].mod_type = name_sn;
  1084. attr[2].mod_values = snames;
  1085. snames[0] = "Consumer";
  1086. snames[1] = NULL;
  1087. attr[3].mod_op = LDAP_MOD_ADD;
  1088. attr[3].mod_type = name_description;
  1089. attr[3].mod_values = desc;
  1090. desc[0] = "Replication Consumer bind entity";
  1091. desc[1] = NULL;
  1092. attr[4].mod_op = LDAP_MOD_ADD;
  1093. attr[4].mod_type = name_userPassword;
  1094. attr[4].mod_values = pwd;
  1095. pwd[0] = hashedpw;
  1096. pwd[1] = NULL;
  1097. attr[5].mod_op = LDAP_MOD_ADD;
  1098. attr[5].mod_type = name_passwordExpirationTime;
  1099. attr[5].mod_values = passwordExpirationTime;
  1100. passwordExpirationTime[0] = "20380119031407Z";
  1101. passwordExpirationTime[1] = NULL;
  1102. /* fprintf (stdout, "ldap_add_s(%s)<br>\n", DN); fflush (stdout); */
  1103. err = ldap_add_s (ld, dn, attrs);
  1104. if (err != LDAP_SUCCESS)
  1105. {
  1106. char* explanation = PR_smprintf("Unable to create consumer dn."
  1107. " (%s (%i) returned from ldap_add_s(%s))",
  1108. ldap_err2string (err), err, dn);
  1109. ds_report_warning (DS_NETWORK_ERROR, " can't create consumer dn", explanation);
  1110. PR_smprintf_free (explanation);
  1111. ret = 1;
  1112. }
  1113. }
  1114. return ret;
  1115. }
  1116. static int
  1117. add_group_member(LDAP* ld, char* DN, char* attr, char* member)
  1118. {
  1119. int err;
  1120. int ret = 0;
  1121. LDAPMod mod;
  1122. LDAPMod* mods[2];
  1123. char* members[2];
  1124. #ifdef CGI_DEBUG
  1125. debug_log (dbg_log_file, "add_group_member('%s', '%s', '%s')\n",
  1126. DN ? DN : "NULL",
  1127. attr ? attr : "NULL",
  1128. member ? member : "NULL");
  1129. #endif
  1130. if (ld == NULL || DN == NULL || attr == NULL || member == NULL)
  1131. {
  1132. return -1;
  1133. }
  1134. mods[0] = &mod;
  1135. mods[1] = NULL;
  1136. mod.mod_op = LDAP_MOD_ADD;
  1137. mod.mod_type = attr;
  1138. mod.mod_values = members;
  1139. members[0] = member;
  1140. members[1] = NULL;
  1141. /* fprintf (stdout, "ldap_modify_s('%s')<br>\n",DN); fflush (stdout); */
  1142. err = ldap_modify_s (ld, DN, mods);
  1143. if (err != LDAP_SUCCESS && err != LDAP_TYPE_OR_VALUE_EXISTS) {
  1144. char* exp = "can't add member. ";
  1145. char* explanation = PR_smprintf("%s (%i) returned from ldap_modify_s(%s, %i).",
  1146. ldap_err2string (err), err, DN, LDAP_MOD_ADD);
  1147. ds_report_warning (DS_INCORRECT_USAGE, exp, explanation);
  1148. PR_smprintf_free (explanation);
  1149. ret = 1;
  1150. }
  1151. return ret;
  1152. }
  1153. static LDAP*
  1154. do_bind(SLAPD_CONFIG* slapd, char* rootdn, char* rootpw)
  1155. {
  1156. LDAP* connection = NULL;
  1157. int retrymax = 1800; /* wait up to 30 min; init dbcache could be slow. */
  1158. int err = LDAP_SUCCESS;
  1159. /* added error retry to work around the slow start introduced
  1160. by blackflag 624053 */
  1161. while ( retrymax-- )
  1162. {
  1163. if (connection == NULL) {
  1164. connection = ldap_open ("127.0.0.1", slapd->port);
  1165. }
  1166. if (connection) {
  1167. err = ldap_simple_bind_s (connection, rootdn, rootpw ? rootpw : "");
  1168. if (LDAP_SUCCESS == err)
  1169. break;
  1170. }
  1171. PR_Sleep(PR_SecondsToInterval(1));
  1172. }
  1173. if (connection == NULL) {
  1174. char* format = " Cannot connect to server.";
  1175. ds_report_warning (DS_NETWORK_ERROR, format, "");
  1176. } else if (err != LDAP_SUCCESS) {
  1177. char* explanation = PR_smprintf("Unable to bind to server."
  1178. " (%s (%i) returned from ldap_simple_bind_s(%s))",
  1179. ldap_err2string (err), err, rootdn);
  1180. ds_report_warning (DS_NETWORK_ERROR, " can't bind to server",
  1181. explanation);
  1182. PR_smprintf_free (explanation);
  1183. ldap_unbind (connection);
  1184. connection = NULL;
  1185. }
  1186. fflush (stdout);
  1187. return connection;
  1188. }
  1189. static int
  1190. write_ldap_info(SLAPD_CONFIG* slapd, char* base, char* admnm)
  1191. {
  1192. FILE* fp;
  1193. int ret = 0;
  1194. char* fmt = "%s/shared/config/ldap.conf";
  1195. char* infoFileName = PR_smprintf(fmt, slapd->slapd_server_root);
  1196. if ((fp = fopen(infoFileName, "w")) == NULL)
  1197. {
  1198. ret = -1;
  1199. }
  1200. else
  1201. {
  1202. fprintf(fp, "url\tldap://%s:%d/",
  1203. slapd->host, slapd->port);
  1204. if (base)
  1205. fprintf(fp, "%s", base);
  1206. fprintf(fp, "\n");
  1207. fprintf(fp, "admnm\t%s\n", admnm);
  1208. fclose(fp);
  1209. }
  1210. PR_smprintf_free(infoFileName);
  1211. return ret;
  1212. }
  1213. #ifdef TEST_CONFIG
  1214. int
  1215. config_configEntry(LDAP* connection, QUERY_VARS* query)
  1216. {
  1217. /* initial ACIs for o=NetscapeRoot */
  1218. int ret = add_aci_v (connection, value_config40DN, ACI_self_allow, NULLSTR);
  1219. return ret;
  1220. }
  1221. #endif
  1222. int
  1223. config_suitespot(SLAPD_CONFIG* slapd, QUERY_VARS* query)
  1224. {
  1225. LDAP* connection;
  1226. const char* DN_formatUID = "uid=%s,%s";
  1227. char* usageShortMsg = " Required field missing.";
  1228. char* usageErrorMsg = NULL;
  1229. int status = 0;
  1230. char *admin_domainDN = 0;
  1231. int ii = 0;
  1232. char *configAdminDN = 0;
  1233. char *adminGroupDN = 0;
  1234. char *parentDN = 0;
  1235. char *localDAGroupDN = 0;
  1236. char realuid[1024] = {0};
  1237. if (!query->rootDN || *query->rootDN == '\0') {
  1238. usageErrorMsg = "You must enter the distinguished name of a user with "
  1239. "unrestricted access to the directory.";
  1240. } else if (!query->rootPW || *query->rootPW == '\0') {
  1241. usageErrorMsg = "You must enter the password of the user with "
  1242. "unrestricted access to the directory.";
  1243. }
  1244. if (usageErrorMsg) {
  1245. ds_report_warning (DS_INCORRECT_USAGE, usageShortMsg, usageErrorMsg);
  1246. return -1;
  1247. }
  1248. if (!(connection = do_bind (slapd, query->rootDN, query->rootPW)))
  1249. return 1;
  1250. /* parent dn of admin uid entry */
  1251. if (query->netscaperoot) {
  1252. parentDN = make_dn("%s, %s, %s", name_administratorsRDN,
  1253. name_topologyRDN, query->netscaperoot, NULLSTR);
  1254. }
  1255. if (query->config_admin_uid) {
  1256. getUIDFromDN(query->config_admin_uid, realuid);
  1257. if (realuid[0]) {
  1258. /* admid is already a DN */
  1259. configAdminDN = strdup(query->config_admin_uid);
  1260. } else if (parentDN) {
  1261. /* create a DN for admid */
  1262. configAdminDN = make_dn(DN_formatUID, query->config_admin_uid, parentDN, NULLSTR);
  1263. } else {
  1264. /* create one from scratch */
  1265. configAdminDN = make_dn("%s=%s, %s, %s, %s", name_uid, query->config_admin_uid,
  1266. name_administratorsRDN, name_topologyRDN,
  1267. name_netscaperootDN, NULLSTR);
  1268. }
  1269. }
  1270. if (query->suffix)
  1271. {
  1272. status = create_base(connection, query->suffix);
  1273. if (!status)
  1274. {
  1275. if (configAdminDN && !is_root_user(configAdminDN, query)) {
  1276. add_aci_v(connection, query->suffix, ACI_user_allow_2,
  1277. "all", configAdminDN, NULLSTR);
  1278. }
  1279. status = create_group(connection, query->suffix, name_localDAGroup);
  1280. }
  1281. }
  1282. if (!status && query->consumerDN && query->consumerPW &&
  1283. PL_strcasecmp(query->consumerDN, query->rootDN))
  1284. status = create_consumer_dn(connection,
  1285. query->consumerDN, query->consumerPW);
  1286. if (!status)
  1287. {
  1288. /*
  1289. Give the Configuration Admin group access to the root DSE entries
  1290. */
  1291. if (query->netscaperoot) {
  1292. adminGroupDN = make_dn("%s, %s=%s, %s, %s", value_configAdminGroupRDN,
  1293. name_ou, value_groupsOU,
  1294. name_topologyRDN,
  1295. query->netscaperoot, NULLSTR);
  1296. }
  1297. if (query->suffix)
  1298. {
  1299. localDAGroupDN = make_dn("cn=%s, %s", name_localDAGroup,
  1300. query->suffix, NULLSTR);
  1301. }
  1302. else
  1303. {
  1304. localDAGroupDN = NULL;
  1305. }
  1306. for (ii = 0; ii < entryAndAccessListSize; ++ii)
  1307. {
  1308. if (query->cfg_sspt && adminGroupDN) {
  1309. add_aci_v(connection, entryAndAccessList[ii].entryDN,
  1310. ACI_config_admin_group_allow,
  1311. entryAndAccessList[ii].access,
  1312. adminGroupDN, NULLSTR);
  1313. }
  1314. if (configAdminDN && !is_root_user(configAdminDN, query)) {
  1315. add_aci_v(connection, entryAndAccessList[ii].entryDN,
  1316. ACI_user_allow_2,
  1317. entryAndAccessList[ii].access,
  1318. configAdminDN, NULLSTR);
  1319. }
  1320. if (localDAGroupDN)
  1321. {
  1322. add_aci_v(connection, entryAndAccessList[ii].entryDN,
  1323. ACI_local_DA_allow,
  1324. entryAndAccessList[ii].access,
  1325. localDAGroupDN, NULLSTR);
  1326. }
  1327. }
  1328. }
  1329. if (query->cfg_sspt)
  1330. {
  1331. /* create and set ACIs for o=netscaperoot entry */
  1332. if (!status)
  1333. status = create_NetscapeRoot(connection, query->netscaperoot);
  1334. if (!status)
  1335. status = add_aci_v(connection, query->netscaperoot,
  1336. ACI_config_admin_group_allow_all,
  1337. value_configAdminGroupRDN,
  1338. name_ou, value_groupsOU, name_topologyRDN,
  1339. query->netscaperoot, NULLSTR);
  1340. if (!status)
  1341. status = add_aci_v(connection, query->netscaperoot,
  1342. ACI_anonymous_allow_with_filter,
  1343. query->netscaperoot, NULLSTR);
  1344. if (!status)
  1345. status = add_aci_v(connection, query->netscaperoot, ACI_group_expansion,
  1346. query->netscaperoot, NULLSTR);
  1347. /* create "topologyOU, netscaperoot" entry and set ACIs */
  1348. if (!status)
  1349. {
  1350. char *dn = make_dn("%s, %s", name_topologyRDN,
  1351. query->netscaperoot, NULLSTR);
  1352. status = create_organizational_unit(connection, NULL, dn,
  1353. value_topologyDESC,
  1354. 0, 0, 0);
  1355. if (!status)
  1356. add_aci(connection, dn, ACI_anonymous_allow);
  1357. free(dn);
  1358. }
  1359. /* create "ou=Groups, ..." */
  1360. if (!status)
  1361. {
  1362. char *dn = make_dn("%s=%s, %s, %s", name_ou, value_groupsOU,
  1363. name_topologyRDN, query->netscaperoot, NULLSTR);
  1364. status = create_organizational_unit (connection, NULL, dn,
  1365. value_groupsDesc, 0, 0, 0);
  1366. free(dn);
  1367. }
  1368. /* create "ou=Administrators, ..." */
  1369. if (!status)
  1370. {
  1371. char *dn = make_dn("%s, %s, %s", name_administratorsRDN,
  1372. name_topologyRDN, query->netscaperoot, NULLSTR);
  1373. status = create_organizational_unit (connection, NULL, dn,
  1374. value_administratorsDESC,
  1375. 0, 0, 0);
  1376. free(dn);
  1377. }
  1378. /* create "cn=Configuration Administrators, ou=Groups, ..." */
  1379. if (!status)
  1380. {
  1381. char *dn = make_dn("%s=%s, %s, %s", name_ou, value_groupsOU,
  1382. name_topologyRDN,
  1383. query->netscaperoot, NULLSTR);
  1384. status = create_group (connection, dn, value_configAdminGroupCN);
  1385. free(dn);
  1386. }
  1387. /* create the ss admin user */
  1388. if (!status && !is_root_user(query->ssAdmID, query))
  1389. {
  1390. /* group to add the uid to */
  1391. char *groupdn = make_dn("%s, %s=%s, %s, %s", value_configAdminGroupRDN,
  1392. name_ou, value_groupsOU, name_topologyRDN,
  1393. query->netscaperoot, NULLSTR);
  1394. create_ssadmin_user(connection, parentDN,
  1395. query->ssAdmID, query->ssAdmPW1);
  1396. status = add_group_member (connection, groupdn,
  1397. name_uniqueMember, configAdminDN);
  1398. free (groupdn);
  1399. }
  1400. admin_domainDN = make_dn("%s=%s, %s", name_ou, query->admin_domain,
  1401. query->netscaperoot, NULLSTR);
  1402. if (!status)
  1403. status = create_organizational_unit (connection, 0,
  1404. admin_domainDN,
  1405. value_netscapeConfigDesc,
  1406. class_adminDomain,
  1407. name_adminDomain,
  1408. query->admin_domain);
  1409. if (!status) {
  1410. status = create_organizational_unit(connection,
  1411. admin_domainDN,
  1412. value_globalPreferencesOU, 0,
  1413. 0, 0, 0);
  1414. }
  1415. if (!status) {
  1416. status = create_organizational_unit(connection,
  1417. admin_domainDN,
  1418. value_hostPreferencesOU, 0,
  1419. 0, 0, 0);
  1420. }
  1421. /*
  1422. ** Write the ldap.info file and the SuiteSpot.ldif file
  1423. */
  1424. write_ldap_info(slapd, query->suffix, query->ssAdmID);
  1425. }
  1426. #ifdef TEST_CONFIG
  1427. if (!status && query->testconfig)
  1428. status = create_configEntry(connection);
  1429. if (!status && query->testconfig)
  1430. status = config_configEntry(connection, query);
  1431. #endif
  1432. if (connection)
  1433. ldap_unbind (connection);
  1434. if (adminGroupDN)
  1435. free(adminGroupDN);
  1436. if (configAdminDN)
  1437. free(configAdminDN);
  1438. if (parentDN)
  1439. free(parentDN);
  1440. if (localDAGroupDN)
  1441. free(localDAGroupDN);
  1442. return status;
  1443. }