config.c 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110
  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. /*
  39. * config.c -- parse config file for directory server gateway
  40. */
  41. #include <limits.h> /* ULONG_MAX */
  42. #include <stdio.h>
  43. #include <stdlib.h> /* strtoul */
  44. #include <string.h>
  45. #if !defined( XP_WIN32 )
  46. #include <sys/param.h>
  47. #endif
  48. #include "dsgw.h"
  49. #include "dbtdsgw.h"
  50. #include "../../include/portable.h"
  51. /* MLM - Include netsite.h to get ADMSERV_VERSION_STRING */
  52. #ifdef AIX
  53. #undef HAVE_TIME_R
  54. #endif
  55. #include "netsite.h"
  56. #include "ldaputil/errors.h"
  57. #include "ldaputil/ldaputil.h"
  58. #include "ldaputil/dbconf.h"
  59. extern char *get_userdb_dir(void); /* Can't include libadmin.h, so this */
  60. static void report_ldapu_error( int ldapu_err, int dsgw_err, int erropts );
  61. static void adderr( dsgwconfig *gc, char *str, char *filename, int lineno );
  62. static void fp_parse_line( char *line, int *argcp, char **argv );
  63. static void fp_getline_init( int *lineno );
  64. static char *fp_getline( FILE *fp, int *lineno );
  65. static void add_location( int *loccountp, dsgwloc **locarrayp,
  66. char *locsuffix, char **argv );
  67. static int add_newtype( dsgwnewtype **newentlistp, int loccount,
  68. dsgwloc *locarray, int argc, char **argv );
  69. static void add_tmplset( dsgwtmplset **tslp, int argc, char **argv );
  70. static void add_vcardproperty( dsgwvcprop **vcpropp, int argc, char **argv );
  71. static void add_avset( dsgwavset **avsp, char **argv );
  72. static void add_includeset( dsgwinclset **isp, char **argv );
  73. static void add_l10nset( dsgwsubst **l10np, char **argv );
  74. static void read_dsgwconfig( char *filename, char *locsuffix,
  75. int templatesonly, int binddnfile );
  76. static void get_dbconf_properties( char *filename );
  77. static int write_dbswitch_info( FILE *fp, dsgwconfig *cfgp, char *dbhandle );
  78. static int ldapdb_url_parse( char *url, LDAPDBURLDesc **ldbudpp );
  79. static int dsgw_valid_context();
  80. static int browser_is_msie40();
  81. static int browser_ignores_acceptcharset();
  82. static char *dsgw_ch_strdup_tolower( const char *s );
  83. static void set_dsgwcharset();
  84. #ifdef XP_WIN32
  85. static void dsgw_unix2dospath( char *path );
  86. #endif
  87. #define MAXARGS 100
  88. /*
  89. * Open and parse the dsgw config file. If an error occurs, this function
  90. * does not return.
  91. */
  92. dsgwconfig *
  93. dsgw_read_config()
  94. {
  95. char *scriptname;
  96. char *p, *fname;
  97. int servurllen = 0;
  98. int len;
  99. char *path;
  100. /* get rid of stupid warning: */
  101. if (ldapu_strings != NULL);
  102. /*
  103. * First, make sure that the context is valid. Don't want anything
  104. * tricky in there like dots or slashes.
  105. */
  106. if (!dsgw_valid_context ()) {
  107. dsgw_error( DSGW_ERR_BADFILEPATH, context,
  108. DSGW_ERROPT_EXIT, 0, NULL );
  109. }
  110. /* gc is a global */
  111. if (( gc = (dsgwconfig *) dsgw_ch_malloc( sizeof( dsgwconfig ))) == NULL ) {
  112. dsgw_error( DSGW_ERR_NOMEMORY,
  113. XP_GetClientStr(DBT_initializingConfigInfo_),
  114. DSGW_ERROPT_EXIT, 0, NULL );
  115. }
  116. memset( gc, 0, sizeof( dsgwconfig ));
  117. /*
  118. * set non-zero configuration defaults
  119. */
  120. gc->gc_ldapport = LDAP_PORT;
  121. gc->gc_configerrstr = dsgw_ch_strdup( "" );
  122. gc->gc_sslrequired = DSGW_SSLREQ_NEVER;
  123. gc->gc_authlifetime = DSGW_DEF_AUTH_LIFETIME;
  124. gc->gc_configdir = DSGW_CONFIGDIR_HTTP; /* may be overridden below */
  125. gc->gc_docdir = DSGW_DOCDIR_HTTP;
  126. gc->gc_tmpldir = DSGW_TMPLDIR_HTTP; /* may be overridden below */
  127. gc->gc_urlpfxmain = DSGW_URLPREFIX_MAIN_HTTP; /* may be overridden below */
  128. /*gc->gc_urlpfxcgi = DSGW_URLPREFIX_CGI_HTTP;*/
  129. gc->gc_urlpfxcgi = DSGW_URLPREFIX_BIN; /* may be overridden below */
  130. gc->gc_binddn = gc->gc_bindpw = "";
  131. gc->gc_charset = NULL; /* implicitly ISO-8859-1 */
  132. gc->gc_ClientLanguage = "";
  133. gc->gc_AdminLanguage = "";
  134. gc->gc_DefaultLanguage = "";
  135. gc->gc_httpversion = 0;
  136. gc->gc_orgchartsearchattr = "uid";
  137. /*
  138. * Figure out whether we are running under the admin server or not. This
  139. * also determines where our config and html files are. The hackage is:
  140. * if we're running under the admin server:
  141. * configdir is ../../../../admin-serv/config
  142. * htmldir is ../html
  143. * urlpfxmain is ""
  144. * urlpfxcgi is ""
  145. * dbswitchfile is NSHOME/userdb/dbswitch.conf
  146. *
  147. * If we're running under any other HTTP server:
  148. * configdir is ../config
  149. * htmldir is ../config (yes, that's right)
  150. * urlpfxmain is "lang?context=dsgw&file="
  151. * gc_urlpfxcgi is "/ds"
  152. * dbswitchfile is not used
  153. */
  154. /* Get the admin server name and chop off the version number */
  155. /* vs = dsgw_ch_strdup( ADMSERV_VERSION_STRING );
  156. if (( p = strchr( vs, '/')) != NULL ) {
  157. *p = '\0';
  158. }*/
  159. /*ss = getenv( "SERVER_SOFTWARE" );
  160. if ( ss != NULL ) {
  161. if ( !strncasecmp( vs, ss, strlen( vs ))) {
  162. char *server_names;*/
  163. /* We're running under the admin server */
  164. /* gc->gc_admserv = 1;
  165. gc->gc_configdir = DSGW_CONFIGDIR_ADMSERV;
  166. gc->gc_tmpldir = DSGW_TMPLDIR_ADMSERV;
  167. gc->gc_urlpfxmain = DSGW_URLPREFIX_MAIN_ADMSERV;
  168. gc->gc_urlpfxcgi = DSGW_URLPREFIX_CGI_ADMSERV;*/
  169. /* Check if running an end-user CGI under the admin server */
  170. /* if (( server_names = getenv( "SERVER_NAMES" )) != NULL &&
  171. strlen( server_names ) >= 4 &&
  172. strncmp( server_names, "user", 4 ) == 0 ) {
  173. gc->gc_enduser = 1;
  174. }
  175. }
  176. }*/
  177. /*
  178. * Get the strlen of the http://admin/port because getvp returns
  179. * that in the url, so we can't compare scriptname against what
  180. * getvp returns. We need to skip past the server url part.
  181. */
  182. servurllen = strlen(getenv("SERVER_URL"));
  183. /* Set mode (based on which CGI is currently running) */
  184. if (( scriptname = getenv( "SCRIPT_NAME" )) == NULL ) {
  185. gc->gc_mode = 0;
  186. } else {
  187. if ( !strncmp( scriptname, dsgw_getvp( DSGW_CGINUM_DOSEARCH ) + servurllen,
  188. strlen( scriptname ))) {
  189. gc->gc_mode = DSGW_MODE_DOSEARCH;
  190. } else if ( !strncmp( scriptname, dsgw_getvp( DSGW_CGINUM_BROWSE ) + servurllen,
  191. strlen( scriptname ))) {
  192. gc->gc_mode = DSGW_MODE_BROWSE;
  193. } else if ( !strncmp( scriptname, dsgw_getvp( DSGW_CGINUM_SEARCH ) + servurllen,
  194. strlen( scriptname ))) {
  195. gc->gc_mode = DSGW_MODE_SEARCH;
  196. } else if ( !strncmp( scriptname, dsgw_getvp( DSGW_CGINUM_CSEARCH )+ servurllen,
  197. strlen( scriptname ))) {
  198. gc->gc_mode = DSGW_MODE_CSEARCH;
  199. } else if ( !strncmp( scriptname, dsgw_getvp( DSGW_CGINUM_AUTH )+ servurllen,
  200. strlen( scriptname ))) {
  201. gc->gc_mode = DSGW_MODE_AUTH;
  202. } else if ( !strncmp( scriptname, dsgw_getvp( DSGW_CGINUM_EDIT )+ servurllen,
  203. strlen( scriptname ))) {
  204. gc->gc_mode = DSGW_MODE_EDIT;
  205. } else if ( !strncmp( scriptname, dsgw_getvp( DSGW_CGINUM_DOMODIFY )+ servurllen,
  206. strlen( scriptname ))) {
  207. gc->gc_mode = DSGW_MODE_DOMODIFY;
  208. } else {
  209. gc->gc_mode = DSGW_MODE_UNKNOWN;
  210. }
  211. }
  212. if (( p = getenv( "SERVER_PROTOCOL" )) != NULL ) {
  213. char *pp;
  214. pp = strchr(p, '/');
  215. if (pp != NULL) {
  216. gc->gc_httpversion = (float)atof(++pp);
  217. }
  218. }
  219. if (( p = getenv( "DefaultLanguage" )) != NULL ) {
  220. gc->gc_DefaultLanguage = p;
  221. }
  222. if (( p = getenv( "AdminLanguage" )) != NULL ) {
  223. gc->gc_AdminLanguage = p;
  224. }
  225. if (( p = getenv( "ClientLanguage" )) != NULL ) {
  226. gc->gc_ClientLanguage = p;
  227. }
  228. /* Accept-Language from user overrides ClientLanguage from environment */
  229. if (( p = getenv( "HTTP_ACCEPT_LANGUAGE" )) != NULL ) {
  230. gc->gc_ClientLanguage = p;
  231. }
  232. /* Set rest of config. by reading the appropriate config files */
  233. path = dsgw_ch_malloc( MAXPATHLEN );
  234. if ( gc->gc_admserv ) {
  235. PR_snprintf( path, MAXPATHLEN, "%s/dbswitch.conf", get_userdb_dir());
  236. get_dbconf_properties( path );
  237. }
  238. /*
  239. * If there is no config file name (context), then use
  240. * DSGW_CONFIGFILE in the config directory
  241. */
  242. if (context == NULL) {
  243. PR_snprintf( path, MAXPATHLEN, "%s$$LANGDIR/%s",
  244. DSGW_CONFIGDIR_HTTP, DSGW_CONFIGFILE);
  245. len = strlen( DSGW_CONFIGDIR_HTTP ) + strlen( DSGW_CONFIGFILE ) + 32;
  246. } else {
  247. PR_snprintf( path, MAXPATHLEN, "%s$$LANGDIR/%s.conf",
  248. DSGW_CONTEXTDIR_HTTP, context);
  249. /* increased the length from 11 -- fix for auth crash on AIX */
  250. len = strlen( DSGW_CONTEXTDIR_HTTP ) + strlen( context ) + 32;
  251. }
  252. /* allocate buffers with enough extra room to fit "$$LANGDIR/" */
  253. if ( NULL != gc->gc_ClientLanguage ) {
  254. len += strlen( gc->gc_ClientLanguage );
  255. }
  256. fname = dsgw_ch_malloc( len+MAXPATHLEN );
  257. if ( GetFileForLanguage( path, gc->gc_ClientLanguage, fname ) < 0 ) {
  258. if (context == NULL) {
  259. PR_snprintf( fname, len+MAXPATHLEN, "%s%s", DSGW_CONFIGDIR_HTTP,
  260. DSGW_CONFIGFILE);
  261. } else {
  262. PR_snprintf( fname, len+MAXPATHLEN, "%s%s.conf",
  263. DSGW_CONTEXTDIR_HTTP, context);
  264. }
  265. }
  266. free( path );
  267. if (context != NULL) {
  268. char urlpfx[MAXPATHLEN];
  269. /*set the urlpfxmain to be "lang?context=CONTEXT&file="*/
  270. /*sprintf(urlpfx, "%slang?context=%s&file=", DSGW_URLPREFIX_CGI_HTTP, context);*/
  271. PR_snprintf(urlpfx, MAXPATHLEN, "%s?context=%s&file=", dsgw_getvp(DSGW_CGINUM_LANG), context);
  272. gc->gc_urlpfxmain = dsgw_ch_strdup( urlpfx );
  273. }
  274. read_dsgwconfig( fname, NULL, gc->gc_admserv, 0 );
  275. free( fname );
  276. #if 0
  277. /* if necessary, try to set path to certificate database */
  278. #ifndef DSGW_NO_SSL
  279. if ( gc->gc_ldapssl && gc->gc_securitypath == NULL ) {
  280. if ( gc->gc_admserv ) {
  281. if (( p = get_nsadm_var( "CertFile" )) != NULL ) {
  282. gc->gc_securitypath = dsgw_ch_malloc( strlen( p ) + 4 );
  283. sprintf( gc->gc_securitypath, "%s.db", p );
  284. }
  285. } else {
  286. gc->gc_securitypath = DSGW_DEFSECURITYPATH;
  287. }
  288. }
  289. #endif
  290. #endif
  291. if ( browser_ignores_acceptcharset() ) {
  292. set_dsgwcharset();
  293. } else {
  294. /* Accept-Charset from user overrides charset from configuration */
  295. if (( p = getenv( "HTTP_ACCEPT_CHARSET" )) != NULL ) {
  296. gc->gc_charset = p;
  297. /* IE 4.0 doesn't send HTTP_ACCEPT_CHARSET, so we test for it specially -RJP */
  298. } else if (browser_is_msie40() ) {
  299. gc->gc_charset = MSIE40_DEFAULT_CHARSET;
  300. } else { /* charset file overrides charset from configuration */
  301. set_dsgwcharset();
  302. }
  303. }
  304. return( gc );
  305. }
  306. static void
  307. report_ldapu_error( int ldapu_err, int dsgw_err, int erropts )
  308. {
  309. char *extra = "";
  310. switch( ldapu_err ) {
  311. case LDAPU_ERR_CANNOT_OPEN_FILE:
  312. extra = XP_GetClientStr(DBT_cannotOpenFile_);
  313. break;
  314. case LDAPU_ERR_DBNAME_IS_MISSING:
  315. case LDAPU_ERR_NOT_PROPVAL:
  316. extra = XP_GetClientStr(DBT_malformedDbconfFile_);
  317. break;
  318. case LDAPU_ERR_PROP_IS_MISSING:
  319. extra = XP_GetClientStr(DBT_missingPropertyNameInDbconfFile_);
  320. break;
  321. case LDAPU_ERR_OUT_OF_MEMORY:
  322. extra = XP_GetClientStr(DBT_outOfMemory_1);
  323. break;
  324. case LDAPU_ERR_DIRECTIVE_IS_MISSING:
  325. extra = XP_GetClientStr(DBT_missingDirectiveInDbconfFile_);
  326. break;
  327. }
  328. dsgw_error( dsgw_err, extra, erropts, 0, NULL );
  329. }
  330. /*
  331. * Read the gateway config file (dsgw.conf).
  332. */
  333. static void
  334. read_dsgwconfig( char *filename, char *locsuffix, int templatesonly, int binddnfile )
  335. {
  336. char buf[ MAXPATHLEN + 100 ];
  337. int cargc;
  338. char *cargv[ MAXARGS ];
  339. FILE *fp;
  340. char *line;
  341. int lineno;
  342. int rc;
  343. LDAPURLDesc *ludp;
  344. if (( fp = fopen( filename, "r" )) == NULL ) {
  345. if ( strstr( filename, "dsgw-l10n.conf" ) != NULL ) {
  346. return; /* ignore if it's dsgw-l10n.conf */
  347. }
  348. PR_snprintf( buf, MAXPATHLEN + 100,
  349. XP_GetClientStr(DBT_cannotOpenConfigFileSN_), filename );
  350. dsgw_error( DSGW_ERR_BADCONFIG, buf, DSGW_ERROPT_EXIT, 0, NULL );
  351. }
  352. fp_getline_init( &lineno );
  353. while ( (line = fp_getline( fp, &lineno )) != NULL ) {
  354. /* skip comments and blank lines */
  355. if ( line[0] == '#' || line[0] == '\0' ) {
  356. continue;
  357. }
  358. fp_parse_line( line, &cargc, cargv );
  359. if ( cargc < 1 ) {
  360. continue;
  361. }
  362. if ( strcasecmp( cargv[0], "requireauth" ) == 0 ) {
  363. if ( templatesonly ) continue;
  364. gc->gc_authrequired = 1;
  365. }
  366. if ( strcasecmp( cargv[0], "authlifetime" ) == 0 ) {
  367. if ( templatesonly ) continue;
  368. if ( cargc < 2 ) {
  369. adderr( gc, XP_GetClientStr(DBT_missingArgumentForAuthlifetimeDi_),
  370. filename, lineno );
  371. continue;
  372. }
  373. gc->gc_authlifetime = (time_t) atol( cargv[ 1 ]);
  374. } else if ( strcasecmp( cargv[ 0 ], "changeHTML" ) == 0 ) {
  375. auto dsgwsubst *sub;
  376. if ( templatesonly ) continue;
  377. if ( cargc < 2 || cargv[ 1 ][ 0 ] == '\0') continue;
  378. sub = (dsgwsubst *)dsgw_ch_malloc( sizeof( dsgwsubst ));
  379. memset( sub, 0, sizeof( dsgwsubst ));
  380. sub->dsgwsubst_from = dsgw_ch_strdup( cargv[ 1 ] );
  381. if ( cargc > 2 ) {
  382. sub->dsgwsubst_to = dsgw_ch_strdup( cargv[ 2 ] );
  383. if ( cargc > 3 ) {
  384. auto size_t i;
  385. sub->dsgwsubst_charsets = (char **)dsgw_ch_malloc
  386. (sizeof(char*) * (cargc - 2));
  387. for (i = 3; i < cargc; ++i) {
  388. sub->dsgwsubst_charsets[ i-3 ] = dsgw_ch_strdup( cargv[ i ] );
  389. }
  390. sub->dsgwsubst_charsets[ i-3 ] = NULL;
  391. }
  392. }
  393. { /* append sub to gc->gc_changeHTML: */
  394. auto dsgwsubst **s = &(gc->gc_changeHTML);
  395. while (*s) s = &((*s)->dsgwsubst_next);
  396. *s = sub;
  397. }
  398. } else if ( strcasecmp( cargv[0], "dirmgr" ) == 0 ) {
  399. if ( templatesonly ) continue;
  400. if ( cargc < 2 ) {
  401. adderr( gc, XP_GetClientStr(DBT_missingArgumentForDirmgrDirectiv_),
  402. filename, lineno );
  403. continue;
  404. }
  405. gc->gc_rootdn = dsgw_ch_strdup( cargv[ 1 ]);
  406. } else if ( strcasecmp( cargv[0], "url-orgchart-base" ) == 0 ) {
  407. if ( templatesonly ) continue;
  408. if ( cargc < 2 ) {
  409. adderr( gc, XP_GetClientStr(DBT_missingArgumentForOrgChartURLDirectiv_),
  410. filename, lineno );
  411. continue;
  412. }
  413. gc->gc_orgcharturl = dsgw_ch_strdup( cargv[ 1 ]);
  414. } else if ( strcasecmp( cargv[0], "orgchart-attrib-farleft-rdn" ) == 0 ) {
  415. if ( templatesonly ) continue;
  416. if ( cargc < 2 ) {
  417. adderr( gc, XP_GetClientStr(DBT_missingArgumentForOrgChartSearchAttr_),
  418. filename, lineno );
  419. continue;
  420. }
  421. gc->gc_orgchartsearchattr = dsgw_ch_strdup( cargv[ 1 ]);
  422. } else if ( strcasecmp( cargv[0], "enable-aim-presence" ) == 0 ) {
  423. if ( templatesonly ) continue;
  424. if (cargc < 2 || strcasecmp(cargv[1], "true") == 0) {
  425. gc->gc_aimpresence = 1;
  426. } else {
  427. gc->gc_aimpresence = 0;
  428. }
  429. } else if ( strcasecmp( cargv[0], "baseurl" ) == 0 ) {
  430. if ( templatesonly ) continue;
  431. if ( cargc < 2 ) {
  432. adderr( gc, XP_GetClientStr(DBT_missingArgumentForBaseurlDirecti_),
  433. filename, lineno );
  434. continue;
  435. }
  436. gc->gc_baseurl = dsgw_ch_strdup( cargv[ 1 ]);
  437. if (( rc = ldap_url_parse( gc->gc_baseurl, &ludp )) != 0 ) {
  438. switch ( rc ) {
  439. case LDAP_URL_ERR_NODN:
  440. adderr( gc, XP_GetClientStr(DBT_badUrlProvidedForBaseurlDirectiv_), filename, lineno );
  441. break;
  442. case LDAP_URL_ERR_MEM:
  443. dsgw_error( DSGW_ERR_NOMEMORY,
  444. XP_GetClientStr(DBT_parsingBaseurlDirective_),
  445. DSGW_ERROPT_EXIT, 0, NULL );
  446. break;
  447. case LDAP_URL_ERR_NOTLDAP:
  448. adderr( gc, XP_GetClientStr(DBT_badUrlProvidedForBaseurlDirectiv_1), filename, lineno );
  449. break;
  450. }
  451. } else {
  452. gc->gc_ldapserver = ludp->lud_host;
  453. gc->gc_ldapport = ludp->lud_port;
  454. if ( ludp->lud_dn == NULL ) {
  455. gc->gc_ldapsearchbase = dsgw_ch_strdup( "" );
  456. } else {
  457. gc->gc_ldapsearchbase = ludp->lud_dn;
  458. }
  459. if (( ludp->lud_options & LDAP_URL_OPT_SECURE ) != 0 ) {
  460. #ifdef DSGW_NO_SSL
  461. adderr( gc, XP_GetClientStr(DBT_LdapsUrlsAreNotYetSupportedN_),
  462. filename, lineno );
  463. #else
  464. gc->gc_ldapssl = 1;
  465. #endif
  466. }
  467. }
  468. } else if ( strcasecmp( cargv[0], "template" ) == 0 ) {
  469. if ( cargc < 3 ) {
  470. adderr( gc, XP_GetClientStr(DBT_missingArgumentsForTemplateDirec_),
  471. filename, lineno );
  472. continue;
  473. }
  474. dsgw_addtemplate( &gc->gc_templates, cargv[1], cargc - 2,
  475. &cargv[2] );
  476. #ifndef DSGW_NO_SSL
  477. } else if ( strcasecmp( cargv[0], "sslrequired" ) == 0 ) {
  478. if ( templatesonly ) continue;
  479. if ( cargc < 2 ) {
  480. adderr( gc, XP_GetClientStr(DBT_missingArgumentForSslrequiredDir_),
  481. filename, lineno );
  482. continue;
  483. }
  484. if ( strcasecmp( cargv[1], "never" ) == 0 ) {
  485. gc->gc_sslrequired = DSGW_SSLREQ_NEVER;
  486. } else if ( strcasecmp( cargv[1], "whenauthenticated" ) == 0 ) {
  487. gc->gc_sslrequired = DSGW_SSLREQ_WHENAUTHENTICATED;
  488. } else if ( strcasecmp( cargv[1], "always" ) == 0 ) {
  489. gc->gc_sslrequired = DSGW_SSLREQ_ALWAYS;
  490. } else {
  491. adderr( gc, XP_GetClientStr(DBT_unknownArgumentToSslrequiredDire_), filename, lineno );
  492. }
  493. } else if ( strcasecmp( cargv[0], "securitypath" ) == 0 ) {
  494. if ( templatesonly ) continue;
  495. if ( cargc < 2 ) {
  496. adderr( gc, XP_GetClientStr(DBT_missingArgumentForSecuritypathDi_),
  497. filename, lineno );
  498. continue;
  499. }
  500. gc->gc_securitypath = dsgw_ch_strdup( cargv[1] );
  501. #endif /* !DSGW_NO_SSL */
  502. } else if ( strcasecmp( cargv[0], "htmldir" ) == 0 ) {
  503. int lenth = 0;
  504. if ( cargc < 2 ) {
  505. adderr( gc, XP_GetClientStr(DBT_missingArgumentForHtmlpathDi_),
  506. filename, lineno );
  507. continue;
  508. }
  509. lenth = strlen(cargv[1]);
  510. /*See if the user put a slash at the end of the htmldir directive..*/
  511. if (cargv[1][lenth - 1] == '/' || cargv[1][lenth - 1] == '\\') {
  512. gc->gc_docdir = dsgw_ch_strdup( cargv[1] );
  513. } else {
  514. /*If not, put it there*/
  515. lenth ++;
  516. gc->gc_docdir = dsgw_ch_malloc ((lenth+MAXPATHLEN) *sizeof (char));
  517. PR_snprintf(gc->gc_docdir, lenth + MAXPATHLEN, "%s/", cargv[1]);
  518. }
  519. /* The nametrans used. For the gw, it's /dsgw/html/ */
  520. } else if ( strcasecmp( cargv[0], "gwnametrans" ) == 0 ) {
  521. if ( cargc < 2 ) {
  522. adderr( gc, XP_GetClientStr(DBT_missingArgumentForNametransDi_),
  523. filename, lineno );
  524. continue;
  525. }
  526. /*
  527. * This is needed for redirection. Can't use relative paths
  528. * for Location:. If the gateway/phonebook/userDefinedGateway
  529. * is running under a web server, it should be the html nametrans
  530. * used to map to the html files. If it's under the admin server,
  531. * it should be /dsgw/DIRECTORY_OF_HTML_FILES/ (which should be
  532. * the same as the nameTrans.
  533. */
  534. gc->gc_gwnametrans = dsgw_ch_strdup( cargv[1] );
  535. } else if ( strcasecmp( cargv[0], "configdir" ) == 0 ) {
  536. int lenth = 0;
  537. if ( cargc < 2 ) {
  538. adderr( gc, XP_GetClientStr(DBT_missingArgumentForConfigpathDi_),
  539. filename, lineno );
  540. continue;
  541. }
  542. lenth = strlen(cargv[1]);
  543. /*See if the user put a slash at the end of the htmldir directive..*/
  544. if (cargv[1][lenth - 1] == '/' || cargv[1][lenth - 1] == '\\') {
  545. gc->gc_configdir = dsgw_ch_strdup( cargv[1] );
  546. } else {
  547. /*If not, put it there*/
  548. lenth ++;
  549. gc->gc_configdir = dsgw_ch_malloc ((lenth+MAXPATHLEN) * sizeof (char));
  550. PR_snprintf(gc->gc_configdir, lenth + MAXPATHLEN, "%s/",
  551. cargv[1]);
  552. }
  553. gc->gc_tmpldir = dsgw_ch_strdup( gc->gc_configdir );
  554. } else if ( strcasecmp( cargv[0], "location-suffix" ) == 0 ) {
  555. if ( templatesonly ) continue;
  556. if ( cargc < 2 ) {
  557. adderr( gc,
  558. XP_GetClientStr(DBT_missingArgumentForLocationSuffix_),
  559. filename, lineno );
  560. continue;
  561. }
  562. if ( locsuffix != NULL ) {
  563. free( locsuffix );
  564. }
  565. locsuffix = dsgw_ch_strdup( cargv[1] );
  566. } else if ( strcasecmp( cargv[0], "location" ) == 0 ) {
  567. if ( templatesonly ) continue;
  568. if ( cargc < 4 ) {
  569. adderr( gc,
  570. XP_GetClientStr(DBT_threeArgumentsAreRequiredForTheL_),
  571. filename, lineno );
  572. continue;
  573. }
  574. add_location( &gc->gc_newentryloccount, &gc->gc_newentrylocs,
  575. locsuffix, &cargv[1] );
  576. } else if ( strcasecmp( cargv[0], "newtype" ) == 0 ) {
  577. if ( templatesonly ) continue;
  578. if ( cargc < 3 ) {
  579. adderr( gc,
  580. XP_GetClientStr(DBT_atLeastTwoArgumentsAreRequiredFo_),
  581. filename, lineno );
  582. continue;
  583. }
  584. if ( add_newtype( &gc->gc_newentrytypes, gc->gc_newentryloccount,
  585. gc->gc_newentrylocs, cargc - 1, &cargv[1] ) < 0 ) {
  586. adderr( gc, XP_GetClientStr(DBT_unknownLocationInNewtypeDirectiv_),
  587. filename, lineno );
  588. }
  589. } else if ( strcasecmp( cargv[0], "tmplset" ) == 0 ) {
  590. if ( cargc != 4 && cargc != 5 ) {
  591. adderr( gc,
  592. XP_GetClientStr(DBT_threeOrFourArgumentsAreRequiredF_),
  593. filename, lineno );
  594. continue;
  595. }
  596. add_tmplset( &gc->gc_tmplsets, cargc - 1, &cargv[1] );
  597. } else if ( strcasecmp( cargv[0], "attrvset" ) == 0 ) {
  598. if ( cargc != 5 ) {
  599. adderr( gc,
  600. XP_GetClientStr(DBT_fourArgumentsAreRequiredForTheAt_),
  601. filename, lineno );
  602. continue;
  603. }
  604. add_avset( &gc->gc_avsets, &cargv[1] );
  605. } else if ( strcasecmp( cargv[0], "includeset" ) == 0 ) {
  606. if ( cargc != 3 ) {
  607. adderr( gc,
  608. XP_GetClientStr(DBT_twoArgumentsAreRequiredForTheInc_),
  609. filename, lineno );
  610. continue;
  611. }
  612. add_includeset( &gc->gc_includesets, &cargv[1] );
  613. } else if ( strcasecmp( cargv[0], "charset" ) == 0 ) {
  614. if ( cargc < 2 ) {
  615. adderr( gc, XP_GetClientStr(DBT_missingArgumentForCharsetDirecti_),
  616. filename, lineno );
  617. continue;
  618. }
  619. gc->gc_charset = dsgw_ch_strdup( cargv[1] );
  620. /* the following is not needed because AdminServer */
  621. /* puts these into environment from ns-admin.conf */
  622. #ifdef NEED_LANG_FROM_DSGW_CONF
  623. } else if ( strcasecmp( cargv[0], "ClientLanguage" ) == 0 ) {
  624. if ( cargc < 2 ) {
  625. adderr( gc,
  626. XP_GetClientStr(DBT_missingArgumentForClientlanguage_),
  627. filename, lineno );
  628. continue;
  629. }
  630. gc->gc_ClientLanguage = dsgw_ch_strdup( cargv[1] );
  631. } else if ( strcasecmp( cargv[0], "AdminLanguage" ) == 0 ) {
  632. if ( cargc < 2 ) {
  633. adderr( gc,
  634. XP_GetClientStr(DBT_missingArgumentForAdminlanguageD_),
  635. filename, lineno );
  636. continue;
  637. }
  638. gc->gc_AdminLanguage = dsgw_ch_strdup( cargv[1] );
  639. } else if ( strcasecmp( cargv[0], "DefaultLanguage" ) == 0 ) {
  640. if ( cargc < 2 ) {
  641. adderr( gc,
  642. XP_GetClientStr(DBT_missingArgumentForDefaultlanguag_),
  643. filename, lineno );
  644. continue;
  645. }
  646. gc->gc_DefaultLanguage = dsgw_ch_strdup( cargv[1] );
  647. #endif
  648. } else if ( strcasecmp( cargv[0], "NLS" ) == 0 ) {
  649. if ( cargc < 2 ) {
  650. adderr( gc,
  651. XP_GetClientStr(DBT_missingArgumentForNLS_),
  652. filename, lineno );
  653. continue;
  654. }
  655. gc->gc_NLS = dsgw_ch_strdup( cargv[1] );
  656. } else if ( strcasecmp( cargv[0], "vcard-property" ) == 0 ) {
  657. if ( cargc != 4 && cargc != 5 ) {
  658. adderr( gc,
  659. XP_GetClientStr(DBT_threeOrFourArgumentsAreRequiredF_2),
  660. filename, lineno );
  661. continue;
  662. }
  663. if ( strcmp( cargv[2], "cis" ) != 0
  664. && strcmp( cargv[2], "mls" ) != 0 ) {
  665. adderr( gc,
  666. XP_GetClientStr(DBT_vcardPropertySyntaxMustBeCisOrMl_),
  667. filename, lineno );
  668. continue;
  669. }
  670. add_vcardproperty( &gc->gc_vcardproperties, cargc - 1, &cargv[1] );
  671. } else if ( strcasecmp( cargv[0], "ignoreAcceptCharsetFrom" ) == 0 ) {
  672. int i;
  673. gc->gc_clientIgnoreACharset = (char **)dsgw_ch_malloc( cargc );
  674. --cargc;
  675. for (i = 0; i < cargc; i++)
  676. gc->gc_clientIgnoreACharset[i] = dsgw_ch_strdup_tolower( cargv[i+1] );
  677. gc->gc_clientIgnoreACharset[i] = NULL;
  678. } else if ( strcasecmp( cargv[0], "translate" ) == 0 ) {
  679. if ( cargc != 3 ) {
  680. adderr( gc,
  681. XP_GetClientStr(DBT_twoArgumentsAreRequiredForTheInc_),
  682. filename, lineno );
  683. continue;
  684. }
  685. add_l10nset( &gc->gc_l10nsets, &cargv[1] );
  686. /* include another config file */
  687. } else if ( strcasecmp( cargv[0], "include" ) == 0 ) {
  688. char *tmpfname = NULL;
  689. char *path = NULL;
  690. char *p;
  691. int len;
  692. if ( cargc < 2 ) {
  693. adderr( gc, XP_GetClientStr(DBT_missingFilenameForIncludeDirecti_),
  694. filename, lineno );
  695. continue;
  696. }
  697. len = strlen( cargv[1] ) + 11;
  698. tmpfname = dsgw_ch_malloc( len );
  699. p = strrchr( cargv[1], '/' );
  700. if ( p != NULL ) {
  701. *p++ = '\0';
  702. sprintf( tmpfname, "%s/$$LANGDIR/%s", cargv[1], p);
  703. *(--p) = DSGW_PATHSEP_CHAR;
  704. } else {
  705. p = cargv[1];
  706. sprintf( tmpfname, "$$LANGDIR/%s", p);
  707. }
  708. /* allocate buffers with enough extra room to fit "$$LANGDIR/" */
  709. if ( NULL != gc->gc_ClientLanguage ) {
  710. len += strlen( gc->gc_ClientLanguage );
  711. }
  712. path = dsgw_ch_malloc( len );
  713. if ( GetFileForLanguage( tmpfname, gc->gc_ClientLanguage, path ) < 0 )
  714. strcpy( path, cargv[1] );
  715. #ifdef DSGW_DEBUG
  716. dsgw_log( "tmpfile: %s, path: %s, lang: %s\n",
  717. tmpfname, path, gc->gc_ClientLanguage );
  718. #endif
  719. read_dsgwconfig( path, locsuffix, templatesonly, 0 );
  720. if ( tmpfname ) free( tmpfname );
  721. if ( path ) free( path );
  722. /*Special file that has binddn and password*/
  723. } else if ( strcasecmp( cargv[0], "binddnfile" ) == 0 ) {
  724. char *tmpfname;
  725. if ( cargc < 2 ) {
  726. adderr( gc, XP_GetClientStr(DBT_missingFilenameForBinddnfileDirecti_),
  727. filename, lineno );
  728. continue;
  729. }
  730. /* Make sure it has at least 1 slash in it */
  731. if ( strstr(cargv[1], "/") == NULL) {
  732. adderr( gc, XP_GetClientStr(DBT_badFilenameForBinddnfileDirecti_),
  733. filename, lineno );
  734. continue;
  735. }
  736. /* ... and no ".."'s */
  737. if ( strstr(cargv[1], "..") != NULL) {
  738. adderr( gc, XP_GetClientStr(DBT_badFilenameForBinddnfileDirecti_),
  739. filename, lineno );
  740. continue;
  741. }
  742. /* And no "dsgw" in it */
  743. if ( strstr(cargv[1], "/dsgw/") != NULL) {
  744. adderr( gc, XP_GetClientStr(DBT_badFilenameForBinddnfileDirecti_),
  745. filename, lineno );
  746. continue;
  747. }
  748. tmpfname = dsgw_ch_strdup( cargv[1] );
  749. read_dsgwconfig( tmpfname, locsuffix, templatesonly, 1 /*binddn file*/ );
  750. free( tmpfname );
  751. /*
  752. * Only consider the binddn directive if this file was
  753. * included from another file with the binddnfile
  754. * directive. This is to prevent the stupid user from
  755. * inlining the binddn and bindpw in dsgw.conf. This is
  756. * bad because you can read dsgw.conf with a browser if
  757. * you set up your web server to serve up the gateway.
  758. * Just goto http://host/dsgw/context/dsgw.conf . It is
  759. * my hope that the binddn file will be outside
  760. * NS-HOME/dsgw, because people can get at it if it's in
  761. * there.
  762. */
  763. } else if ( strcasecmp( cargv[0], "binddn" ) == 0 ) {
  764. if (!binddnfile) {
  765. adderr( gc, XP_GetClientStr(DBT_wrongPlaceForBinddnDirectiv_),
  766. filename, lineno );
  767. continue;
  768. }
  769. if ( templatesonly ) continue;
  770. if ( cargc < 2 ) {
  771. adderr( gc, XP_GetClientStr(DBT_missingArgumentForBinddnDirectiv_),
  772. filename, lineno );
  773. continue;
  774. }
  775. gc->gc_binddn = dsgw_ch_strdup( cargv[ 1 ]);
  776. } else if ( strcasecmp( cargv[0], "bindpw" ) == 0 ) {
  777. if (!binddnfile) {
  778. adderr( gc, XP_GetClientStr(DBT_wrongPlaceForBinddnDirectiv_),
  779. filename, lineno );
  780. continue;
  781. }
  782. if ( templatesonly ) continue;
  783. if ( cargc < 2 ) {
  784. adderr( gc, XP_GetClientStr(DBT_missingArgumentForBindpwDirectiv_),
  785. filename, lineno );
  786. continue;
  787. }
  788. gc->gc_bindpw = dsgw_ch_strdup( cargv[ 1 ]);
  789. } else {
  790. adderr( gc, XP_GetClientStr(DBT_unknownDirectiveInConfigFileN_),
  791. filename, lineno );
  792. }
  793. }
  794. if ( gc == NULL || gc->gc_configerr > 0 ) {
  795. dsgw_error( DSGW_ERR_BADCONFIG, ( gc->gc_configerrstr == NULL ) ?
  796. "" : gc->gc_configerrstr, DSGW_ERROPT_EXIT, 0, NULL );
  797. }
  798. }
  799. int
  800. erase_db() {
  801. FILE *fp;
  802. int rc, lineno;
  803. char *line;
  804. char *cargv[ MAXARGS ];
  805. int cargc;
  806. char cmd[ BIG_LINE ];
  807. if ( (fp = fopen( gc->gc_localdbconf, "r" )) == NULL ) {
  808. dsgw_emitf (XP_GetClientStr(DBT_EraseDbCouldNotOpenLcacheConfFil_),
  809. gc->gc_localdbconf);
  810. return( -1 );
  811. }
  812. fp_getline_init( &lineno );
  813. while ( (line = fp_getline( fp, &lineno )) != NULL ) {
  814. fp_parse_line( line, &cargc, cargv );
  815. if ( strcasecmp( cargv[0], "directory" ) == 0) {
  816. #ifdef XP_WIN32
  817. dsgw_unix2dospath( cargv[1] );
  818. #endif
  819. PR_snprintf (cmd, BIG_LINE, "%s %s%c* > %s 2>&1", DSGW_DELETE_CMD, cargv[1],
  820. DSGW_PATHSEP_CHAR, DSGW_NULL_DEVICE);
  821. fflush (0);
  822. if (system (cmd) == 0) {
  823. /*
  824. * success: display status message
  825. */
  826. dsgw_emits( XP_GetClientStr(DBT_FontSize1NPTheDatabaseHasBeenDel_) );
  827. rc = 0;
  828. }
  829. else {
  830. dsgw_emits( XP_GetClientStr(DBT_FontSize1NPTheDatabaseCouldNotBe_) );
  831. rc = -1;
  832. }
  833. dsgw_emits( "<HR>\n" );
  834. fclose( fp );
  835. return( rc );
  836. }
  837. }
  838. return -1;
  839. }
  840. void
  841. app_suffix (char *ldif, char *suffix)
  842. {
  843. FILE *oldfp, *newfp;
  844. char *orig_line;
  845. char *p;
  846. char buf[BUFSIZ];
  847. int i, cargc;
  848. char *cargv[ 100 ];
  849. char tmpldif[ 128 ];
  850. char *dns[] = { "aliasedobjectname:",
  851. "aliasedobjectname:",
  852. "associatedname:",
  853. "dependentupon:",
  854. "ditredirect:",
  855. "dn:",
  856. "documentauthor:",
  857. "documentauthor:",
  858. "documentavailable:",
  859. "errorsto:",
  860. "errorsto:",
  861. "imagefiles:",
  862. "lastmodifiedby:",
  863. "manager:",
  864. "member:",
  865. "memberofgroup:",
  866. "naminglink:",
  867. "naminglink:",
  868. "obsoletedbydocument:",
  869. "obsoletesdocument:",
  870. "owner:",
  871. "proxy:",
  872. "reciprocalnaminglink:",
  873. "reciprocalnaminglink:",
  874. "replicaroot:",
  875. "replicabinddn:",
  876. "requeststo:",
  877. "roleoccupant:",
  878. "secretary:",
  879. "seealso:",
  880. "uniqueMember:",
  881. "updatedbydocument:",
  882. "updatesdocument:",
  883. NULL
  884. };
  885. if ( (oldfp = fopen( ldif, "r" )) == NULL ) {
  886. dsgw_emitf (XP_GetClientStr(DBT_AppSuffixCouldNotOpenLdifFileSN_),
  887. ldif);
  888. return;
  889. }
  890. PR_snprintf( tmpldif, 128, "%s.tmp", ldif);
  891. if ( (newfp = fopen( tmpldif, "w" )) == NULL ) {
  892. dsgw_emitf (XP_GetClientStr(DBT_AppSuffixCouldNotOpenTmpFileSN_),
  893. ldif);
  894. return;
  895. }
  896. while ( fgets( buf, sizeof(buf), oldfp ) != NULL ) {
  897. /* skip comments and blank lines */
  898. if ( buf[0] == '#' || buf[0] == '\0' || buf[0] == '\n') {
  899. fputs( buf, newfp );
  900. continue;
  901. }
  902. orig_line = dsgw_ch_strdup( buf );
  903. fp_parse_line( buf, &cargc, cargv );
  904. for (i=0; dns[i]!=NULL; i++) {
  905. if ( strcasecmp( cargv[0], dns[i] ) == 0 ) {
  906. if ( (p = strchr( orig_line, '\n' )) != NULL ) {
  907. *p = '\0';
  908. }
  909. fprintf ( newfp, "%s, %s\n", orig_line, suffix );
  910. break;
  911. }
  912. }
  913. if ( dns[i] == NULL ) {
  914. fputs( orig_line, newfp );
  915. }
  916. free (orig_line);
  917. }
  918. fclose(newfp);
  919. fclose(oldfp);
  920. unlink( ldif );
  921. if ( rename( tmpldif, ldif ) != 0 ) {
  922. dsgw_emitf (XP_GetClientStr(DBT_unableToRenameSToS_), tmpldif, ldif );
  923. return;
  924. }
  925. }
  926. /*
  927. * Running under admserv - traverse the list of property/value pairs
  928. * returned by dbconf_read_default_dbinfo().
  929. */
  930. static void
  931. get_dbconf_properties( char *filename )
  932. {
  933. DBConfDBInfo_t *db_info;
  934. DBPropVal_t *dbp;
  935. int rc;
  936. LDAPURLDesc *ludp;
  937. LDAPDBURLDesc *ldbudp;
  938. if (( rc = dbconf_read_default_dbinfo( filename, &db_info ))
  939. != LDAPU_SUCCESS ) {
  940. report_ldapu_error( rc, DSGW_ERR_BADCONFIG, DSGW_ERROPT_EXIT );
  941. }
  942. if ( db_info == NULL ) {
  943. dsgw_error( DSGW_ERR_DBCONF,
  944. XP_GetClientStr(DBT_nullPointerReturnedByDbconfReadD_),
  945. DSGW_ERROPT_EXIT, 0, NULL );
  946. }
  947. if ( strcasecmp( db_info->dbname, DBCONF_DEFAULT_DBNAME ) != 0 ) {
  948. dsgw_error( DSGW_ERR_DBCONF, db_info->dbname, DSGW_ERROPT_EXIT, 0,
  949. NULL );
  950. }
  951. #ifdef DSGW_DEBUG
  952. dsgw_log( "opened dbconf, dbname is %s, dburl is %s\n", db_info->dbname,
  953. db_info->url );
  954. #endif
  955. /* Parse the LDAPURL or LDAPDBURL */
  956. gc->gc_baseurl = dsgw_ch_strdup( db_info->url );
  957. rc = ldapdb_url_parse( gc->gc_baseurl, &ldbudp );
  958. if ( rc == 0 ) {
  959. gc->gc_localdbconf = dsgw_ch_strdup( ldbudp->ludb_path );
  960. gc->gc_ldapserver = NULL;
  961. gc->gc_ldapport = -1;
  962. gc->gc_ldapsearchbase = dsgw_ch_strdup( ldbudp->ludb_dn );
  963. #ifndef DSGW_NO_SSL
  964. gc->gc_ldapssl = 0;
  965. #endif
  966. /* If url isn't "ldapdb://", let the code below have a crack */
  967. } else if ( rc != DSGW_ERR_LDAPDBURL_NOTLDAPDB ) {
  968. switch ( rc ) {
  969. case DSGW_ERR_LDAPDBURL_NODN:
  970. adderr( gc, XP_GetClientStr(DBT_badLdapdbUrlTheBaseDnIsMissingN_), NULL, 0 );
  971. break;
  972. case DSGW_ERR_LDAPDBURL_BAD:
  973. adderr( gc, XP_GetClientStr(DBT_badLdapdbUrlN_), NULL, 0 );
  974. break;
  975. }
  976. } else {
  977. if (( rc = ldap_url_parse( gc->gc_baseurl, &ludp )) != 0 ) {
  978. switch ( rc ) {
  979. case LDAP_URL_ERR_NODN:
  980. adderr( gc, XP_GetClientStr(DBT_badUrlProvidedForBaseurlDirectiv_2),
  981. NULL, 0 );
  982. break;
  983. case LDAP_URL_ERR_MEM:
  984. dsgw_error( DSGW_ERR_NOMEMORY,
  985. XP_GetClientStr(DBT_parsingBaseurlDirective_1),
  986. DSGW_ERROPT_EXIT, 0, NULL );
  987. break;
  988. case LDAP_URL_ERR_NOTLDAP:
  989. adderr( gc, XP_GetClientStr(DBT_badUrlProvidedForBaseurlDirectiv_3), NULL, 0 );
  990. break;
  991. }
  992. } else {
  993. gc->gc_ldapserver = ludp->lud_host;
  994. gc->gc_ldapport = ludp->lud_port;
  995. if ( ludp->lud_dn == NULL ) {
  996. gc->gc_ldapsearchbase = dsgw_ch_strdup( "" );
  997. } else {
  998. gc->gc_ldapsearchbase = ludp->lud_dn;
  999. }
  1000. if ( ( ludp->lud_options & LDAP_URL_OPT_SECURE ) != 0 ) {
  1001. #ifdef DSGW_NO_SSL
  1002. adderr( gc, XP_GetClientStr(DBT_LdapsUrlsAreNotYetSupportedN_1),
  1003. NULL, 0 );
  1004. #else
  1005. gc->gc_ldapssl = 1;
  1006. #endif
  1007. }
  1008. }
  1009. }
  1010. /* Look through the properties for binddn and bindpw */
  1011. for ( dbp = db_info->firstprop; dbp != NULL; dbp = dbp->next ) {
  1012. #ifdef DSGW_DEBUG
  1013. dsgw_log( "get prop: prop = %s, val = %s\n", dbp->prop, dbp->val );
  1014. #endif
  1015. if ( strcasecmp( dbp->prop, "binddn" ) == 0 ) {
  1016. if ( dbp->val == NULL || strlen( dbp->val ) == 0 ) {
  1017. dsgw_error( DSGW_ERR_DBCONF,
  1018. XP_GetClientStr(DBT_noValueGivenForBinddn_),
  1019. DSGW_ERROPT_EXIT, 0, NULL );
  1020. }
  1021. gc->gc_binddn = dsgw_ch_strdup( dbp->val );
  1022. } else if ( strcasecmp( dbp->prop, "bindpw" ) == 0 ) {
  1023. if ( dbp->val == NULL || strlen( dbp->val ) == 0 ) {
  1024. dsgw_error( DSGW_ERR_DBCONF,
  1025. XP_GetClientStr(DBT_noValueGivenForBindpw_),
  1026. DSGW_ERROPT_EXIT, 0, NULL );
  1027. }
  1028. gc->gc_bindpw = dsgw_ch_strdup( dbp->val );
  1029. }
  1030. }
  1031. if ( gc == NULL || gc->gc_configerr > 0 ) {
  1032. dsgw_error( DSGW_ERR_BADCONFIG, ( gc->gc_configerrstr == NULL ) ?
  1033. "" : gc->gc_configerrstr, DSGW_ERROPT_EXIT, 0, NULL );
  1034. }
  1035. if ( gc->gc_baseurl == NULL ) {
  1036. dsgw_error( DSGW_ERR_BADCONFIG,
  1037. XP_GetClientStr(DBT_thereIsNoDefaultDirectoryService_),
  1038. DSGW_ERROPT_EXIT, 0, NULL );
  1039. }
  1040. return;
  1041. }
  1042. /*
  1043. * Update the dbswitch.conf file (used under admin. server) to reflect
  1044. * the local/remote directory information contained in "cfgp". Our basic
  1045. * strategy is to read the existing dbswitch.conf file, replacing and adding
  1046. * lines that look like this:
  1047. * directory <dbhandle> ...
  1048. * <dbhandle>:binddn ...
  1049. * <dbhandle>:encoded bindpw ...
  1050. * as necessary. We write a new, temporary config file (copying all other
  1051. * lines over unchanged) and then replace the old file with our new one.
  1052. *
  1053. * If cfgp is configured for localdb mode, we only write a directory line.
  1054. *
  1055. * We return zero if all goes well and non-zero if not.
  1056. *
  1057. * Note that all reading and writing of the dbswitch.conf file is now done
  1058. * using the dbconf...() functions that are part of the ldaputil library, so
  1059. * any comments, blank lines, or unrecognized config file lines will be lost.
  1060. * Also, all "bindpw" property values will be encoded when re-written.
  1061. *
  1062. * Only these members of the cfgp structure are used in this function:
  1063. * gc_localdbconf (NULL if using remote LDAP server)
  1064. * gc_ldapsearchbase
  1065. * gc_ldapserver
  1066. * gc_ldapport
  1067. * gc_ldapssl
  1068. * gc_binddn
  1069. * gc_bindpw
  1070. * Actually, if gc_localdbconf is not NULL, only it and gc_ldapsearchbase are
  1071. * used.
  1072. */
  1073. int
  1074. dsgw_update_dbswitch( dsgwconfig *cfgp, char *dbhandle, int erropts )
  1075. {
  1076. char oldfname[ MAXPATHLEN ], newfname[ MAXPATHLEN ];
  1077. char *userdb_path, buf[ MAXPATHLEN + 100 ];
  1078. int rc, wrote_dbinfo;
  1079. FILE *newfp;
  1080. DBConfInfo_t *cip;
  1081. DBConfDBInfo_t *dbip;
  1082. DBPropVal_t *pvp;
  1083. if ( dbhandle == NULL ) {
  1084. dbhandle = "default";
  1085. }
  1086. if (( userdb_path = get_userdb_dir()) == NULL ) {
  1087. dsgw_error( DSGW_ERR_USERDB_PATH, NULL, erropts, 0, NULL );
  1088. return( -1 );
  1089. }
  1090. /* read old dbswitch.conf contents */
  1091. PR_snprintf( oldfname, MAXPATHLEN, "%s/%s", userdb_path,
  1092. DSGW_DBSWITCH_FILE );
  1093. if (( rc = dbconf_read_config_file( oldfname, &cip )) != LDAPU_SUCCESS ) {
  1094. report_ldapu_error( rc, DSGW_ERR_BADCONFIG, erropts );
  1095. return( -1 );
  1096. }
  1097. /* write db info to new file, replacing information for "dbhandle" */
  1098. PR_snprintf( newfname, MAXPATHLEN, "%s/%s", userdb_path,
  1099. DSGW_DBSWITCH_TMPFILE );
  1100. if (( newfp = fopen( newfname, "w" )) == NULL ) {
  1101. PR_snprintf( buf, MAXPATHLEN + 100,
  1102. XP_GetClientStr(DBT_cannotOpenConfigFileSForWritingN_), newfname );
  1103. dsgw_error( DSGW_ERR_UPDATE_DBSWITCH, buf, erropts, 0, NULL );
  1104. return( -1 );
  1105. }
  1106. wrote_dbinfo = 0;
  1107. for ( dbip = cip->firstdb; dbip != NULL; dbip = dbip->next ) {
  1108. if ( strcasecmp( dbip->dbname, dbhandle ) == 0 ) {
  1109. /*
  1110. * found db name to be replaced: replace with updated information
  1111. */
  1112. if (( rc = write_dbswitch_info( newfp, cfgp, dbhandle )) !=
  1113. LDAPU_SUCCESS ) {
  1114. report_ldapu_error( rc, DSGW_ERR_UPDATE_DBSWITCH, erropts );
  1115. return( -1 );
  1116. }
  1117. wrote_dbinfo = 1;
  1118. } else {
  1119. /*
  1120. * re-write existing db conf information without changes
  1121. */
  1122. if (( rc = dbconf_output_db_directive( newfp, dbip->dbname,
  1123. dbip->url )) != LDAPU_SUCCESS ) {
  1124. report_ldapu_error( rc, DSGW_ERR_UPDATE_DBSWITCH, erropts );
  1125. return( -1 );
  1126. }
  1127. for ( pvp = dbip->firstprop; pvp != NULL; pvp = pvp->next ) {
  1128. if (( rc = dbconf_output_propval( newfp, dbip->dbname,
  1129. pvp->prop, pvp->val,
  1130. strcasecmp( pvp->prop, "bindpw" ) == 0 ))
  1131. != LDAPU_SUCCESS ) {
  1132. report_ldapu_error( rc, DSGW_ERR_UPDATE_DBSWITCH, erropts );
  1133. return( -1 );
  1134. }
  1135. }
  1136. }
  1137. }
  1138. if ( !wrote_dbinfo ) {
  1139. if (( rc = write_dbswitch_info( newfp, cfgp, dbhandle )) !=
  1140. LDAPU_SUCCESS ) {
  1141. report_ldapu_error( rc, DSGW_ERR_UPDATE_DBSWITCH, erropts );
  1142. return( -1 );
  1143. }
  1144. }
  1145. dbconf_free_confinfo( cip );
  1146. fclose( newfp );
  1147. /* replace old file with new one */
  1148. #ifdef _WIN32
  1149. if ( !MoveFileEx( newfname, oldfname, MOVEFILE_REPLACE_EXISTING )) {
  1150. #else
  1151. if ( rename( newfname, oldfname ) != 0 ) {
  1152. #endif
  1153. PR_snprintf( buf, MAXPATHLEN + 100,
  1154. XP_GetClientStr(DBT_unableToRenameSToS_1), newfname, oldfname );
  1155. dsgw_error( DSGW_ERR_UPDATE_DBSWITCH, buf, erropts, 0, NULL );
  1156. return( -1 );
  1157. }
  1158. return( 0 );
  1159. }
  1160. static int
  1161. write_dbswitch_info( FILE *fp, dsgwconfig *cfgp, char *dbhandle )
  1162. {
  1163. char *escapeddn, *url;
  1164. int rc;
  1165. escapeddn = dsgw_strdup_escaped( cfgp->gc_ldapsearchbase );
  1166. if ( cfgp->gc_localdbconf == NULL ) { /* remote server: write ldap:// URL */
  1167. url = dsgw_ch_malloc( 21 + strlen( cfgp->gc_ldapserver )
  1168. + strlen( escapeddn )); /* room for "ldaps://HOST:PORT/DN" */
  1169. sprintf( url, "ldap%s://%s:%d/%s",
  1170. #ifdef DSGW_NO_SSL
  1171. "",
  1172. #else
  1173. cfgp->gc_ldapssl ? "s" : "",
  1174. #endif
  1175. cfgp->gc_ldapserver, cfgp->gc_ldapport, escapeddn );
  1176. } else { /* local db: write ldapdb:// URL */
  1177. url = dsgw_ch_malloc( 11 + strlen( cfgp->gc_localdbconf )
  1178. + strlen( escapeddn )); /* room for "ldapdb://PATH/DN" */
  1179. sprintf( url, "ldapdb://%s/%s\n", cfgp->gc_localdbconf, escapeddn );
  1180. }
  1181. rc = dbconf_output_db_directive( fp, dbhandle, url );
  1182. free( url );
  1183. free( escapeddn );
  1184. if ( rc != LDAPU_SUCCESS ) {
  1185. return( rc );
  1186. }
  1187. if ( cfgp->gc_localdbconf == NULL ) { /* using directory server */
  1188. if ( cfgp->gc_binddn != NULL &&
  1189. ( rc = dbconf_output_propval( fp, dbhandle, "binddn",
  1190. cfgp->gc_binddn, 0 ) != LDAPU_SUCCESS )) {
  1191. return( rc );
  1192. }
  1193. if ( cfgp->gc_bindpw != NULL &&
  1194. ( rc = dbconf_output_propval( fp, dbhandle, "bindpw",
  1195. cfgp->gc_bindpw, 1 ) != LDAPU_SUCCESS )) {
  1196. return( rc );
  1197. }
  1198. }
  1199. return( LDAPU_SUCCESS );
  1200. }
  1201. /* pass 0 for lineno if it is unknown or not applicable */
  1202. static void
  1203. adderr( dsgwconfig *gc, char *str, char *filename, int lineno )
  1204. {
  1205. char *lbuf = dsgw_ch_malloc( MAXPATHLEN + 200 );
  1206. gc->gc_configerr++;
  1207. if ( lineno == 0 ) {
  1208. PR_snprintf( lbuf, MAXPATHLEN + 200,
  1209. XP_GetClientStr(DBT_configFileS_), filename );
  1210. } else {
  1211. PR_snprintf( lbuf, MAXPATHLEN + 200,
  1212. XP_GetClientStr(DBT_configFileSLineD_), filename, lineno );
  1213. }
  1214. gc->gc_configerrstr = dsgw_ch_realloc( gc->gc_configerrstr,
  1215. strlen( gc->gc_configerrstr ) + strlen( str )
  1216. + strlen( lbuf ) + 6 );
  1217. strcat( gc->gc_configerrstr, lbuf );
  1218. strcat( gc->gc_configerrstr, str );
  1219. strcat( gc->gc_configerrstr, "<BR>\n" );
  1220. free( lbuf );
  1221. }
  1222. static void
  1223. add_location( int *loccountp, dsgwloc **locarrayp, char *locsuffix,
  1224. char **argv )
  1225. {
  1226. int len;
  1227. dsgwloc *locp;
  1228. *locarrayp = (dsgwloc *)dsgw_ch_realloc( *locarrayp,
  1229. ( *loccountp + 1 ) * sizeof( dsgwloc ));
  1230. locp = &((*locarrayp)[ *loccountp ]);
  1231. locp->dsloc_handle = dsgw_ch_strdup( argv[0] );
  1232. locp->dsloc_fullname = dsgw_ch_strdup( argv[1] );
  1233. len = strlen( argv[2] );
  1234. if ( argv[2][ len - 1 ] == '#' ) {
  1235. /* '#' implies that locsuffix is not to be appended */
  1236. locp->dsloc_dnsuffix = dsgw_ch_strdup( argv[2] );
  1237. locp->dsloc_dnsuffix[ len - 1 ] = '\0';
  1238. } else if ( locsuffix != NULL && *locsuffix != '\0' ) {
  1239. /* append suffix, preceded by ", " if location arg. is not "" */
  1240. locp->dsloc_dnsuffix = dsgw_ch_malloc( len + strlen( locsuffix ) + 3 );
  1241. if ( argv[2][0] != '\0' ) {
  1242. strcpy( locp->dsloc_dnsuffix, argv[2] );
  1243. strcat( locp->dsloc_dnsuffix, ", " );
  1244. strcat( locp->dsloc_dnsuffix, locsuffix );
  1245. } else {
  1246. strcpy( locp->dsloc_dnsuffix, locsuffix );
  1247. }
  1248. } else {
  1249. locp->dsloc_dnsuffix = dsgw_ch_strdup( argv[2] );
  1250. }
  1251. ++(*loccountp);
  1252. }
  1253. static int
  1254. add_newtype( dsgwnewtype **newentlistp, int loccount, dsgwloc *locarray,
  1255. int argc, char **argv )
  1256. {
  1257. int i, j;
  1258. dsgwnewtype *ntp, *prevntp;
  1259. ntp = (dsgwnewtype *)dsgw_ch_malloc( sizeof( dsgwnewtype ));
  1260. ntp->dsnt_template = dsgw_ch_strdup( argv[0] );
  1261. ntp->dsnt_fullname = dsgw_ch_strdup( argv[1] );
  1262. ntp->dsnt_rdnattr = dsgw_ch_strdup( argv[2] );
  1263. ntp->dsnt_next = NULL;
  1264. ntp->dsnt_loccount = argc - 3;
  1265. argv = &argv[3];
  1266. /* fill dsnt_locations array with indexes into gc->gc_newentrylocs */
  1267. if ( ntp->dsnt_loccount <= 0 ) {
  1268. ntp->dsnt_locations = NULL;
  1269. } else {
  1270. int foundit;
  1271. ntp->dsnt_locations = (int *)dsgw_ch_malloc( ntp->dsnt_loccount *
  1272. sizeof( int ));
  1273. for ( i = 0; i < ntp->dsnt_loccount; ++i ) {
  1274. foundit = 0;
  1275. for ( j = 0; j < loccount && !foundit; ++j ) {
  1276. if ( strcasecmp( argv[ i ], locarray[ j ].dsloc_handle )
  1277. == 0 ) {
  1278. ntp->dsnt_locations[ i ] = j;
  1279. foundit = 1;
  1280. }
  1281. }
  1282. /* if ( j >= loccount ) { */
  1283. if ( !foundit ) {
  1284. return( -1 ); /* unknown location -- error */
  1285. }
  1286. }
  1287. }
  1288. /* append to linked list of new entry structures */
  1289. if ( *newentlistp == NULL ) {
  1290. *newentlistp = ntp;
  1291. } else {
  1292. for ( prevntp = *newentlistp; prevntp->dsnt_next != NULL;
  1293. prevntp = prevntp->dsnt_next ) {
  1294. ;
  1295. }
  1296. prevntp->dsnt_next = ntp;
  1297. }
  1298. return( 0 );
  1299. }
  1300. static void
  1301. add_tmplset( dsgwtmplset **tslp, int argc, char **argv )
  1302. {
  1303. dsgwtmplset *prevtsp, *tsp;
  1304. dsgwview *prevvp, *vp;
  1305. prevtsp = NULL;
  1306. tsp = *tslp;
  1307. while ( tsp != NULL ) {
  1308. if ( strcasecmp( tsp->dstset_name, argv[0] ) == 0 ) {
  1309. break;
  1310. }
  1311. prevtsp = tsp;
  1312. tsp = tsp->dstset_next;
  1313. }
  1314. if ( tsp == NULL ) { /* new template set */
  1315. tsp = (dsgwtmplset *)dsgw_ch_malloc( sizeof( dsgwtmplset ));
  1316. memset( tsp, 0, sizeof( dsgwtmplset ));
  1317. tsp->dstset_name = dsgw_ch_strdup( argv[0] );
  1318. if ( prevtsp == NULL ) {
  1319. *tslp = tsp;
  1320. } else {
  1321. prevtsp->dstset_next = tsp;
  1322. }
  1323. }
  1324. /* add a new view to the end of this template set's view list */
  1325. vp = (dsgwview *)dsgw_ch_malloc( sizeof( dsgwview ));
  1326. memset( vp, 0, sizeof( dsgwview ));
  1327. vp->dsview_caption = dsgw_ch_strdup( argv[1] );
  1328. vp->dsview_template = dsgw_ch_strdup( argv[2] );
  1329. if ( argc > 3 ) {
  1330. vp->dsview_jscript = dsgw_ch_strdup( argv[3] );
  1331. }
  1332. if ( tsp->dstset_viewlist == NULL ) {
  1333. tsp->dstset_viewlist = vp;
  1334. } else {
  1335. for ( prevvp = tsp->dstset_viewlist; prevvp->dsview_next != NULL;
  1336. prevvp = prevvp->dsview_next ) {
  1337. ;
  1338. }
  1339. prevvp->dsview_next = vp;
  1340. }
  1341. ++tsp->dstset_viewcount;
  1342. }
  1343. static void
  1344. add_avset( dsgwavset **avsp, char **argv ) /* 4 args. in argv[] */
  1345. {
  1346. dsgwavset *prevavp, *avp;
  1347. /* is this the first element of a set? */
  1348. prevavp = NULL;
  1349. for ( avp = *avsp; avp != NULL; avp = avp->dsavset_next ) {
  1350. if ( strcasecmp( avp->dsavset_handle, argv[0] ) == 0 ) {
  1351. break;
  1352. }
  1353. prevavp = avp;
  1354. }
  1355. if ( avp == NULL ) { /* first element: add a new set */
  1356. avp = (dsgwavset *)dsgw_ch_malloc( sizeof( dsgwavset ));
  1357. memset( avp, 0, sizeof( dsgwavset ));
  1358. avp->dsavset_handle = dsgw_ch_strdup( argv[0] );
  1359. if ( prevavp == NULL ) {
  1360. *avsp = avp;
  1361. } else {
  1362. prevavp->dsavset_next = avp;
  1363. }
  1364. }
  1365. ++avp->dsavset_itemcount;
  1366. avp->dsavset_values = (char **)dsgw_ch_realloc( avp->dsavset_values,
  1367. avp->dsavset_itemcount * sizeof( char * ));
  1368. avp->dsavset_values[ avp->dsavset_itemcount - 1 ] =
  1369. dsgw_ch_strdup( argv[1] );
  1370. avp->dsavset_prefixes = (char **)dsgw_ch_realloc( avp->dsavset_prefixes,
  1371. avp->dsavset_itemcount * sizeof( char * ));
  1372. avp->dsavset_prefixes[ avp->dsavset_itemcount - 1 ] =
  1373. dsgw_ch_strdup( argv[2] );
  1374. avp->dsavset_suffixes = (char **)dsgw_ch_realloc( avp->dsavset_suffixes,
  1375. avp->dsavset_itemcount * sizeof( char * ));
  1376. avp->dsavset_suffixes[ avp->dsavset_itemcount - 1 ] =
  1377. dsgw_ch_strdup( argv[3] );
  1378. }
  1379. static void
  1380. add_includeset( dsgwinclset **isp, char **argv ) /* 2 args. in argv[] */
  1381. {
  1382. dsgwinclset *previsp, *tmpisp;
  1383. /* is this the first element of a set? */
  1384. previsp = NULL;
  1385. for ( tmpisp = *isp; tmpisp != NULL; tmpisp = tmpisp->dsiset_next ) {
  1386. if ( strcasecmp( tmpisp->dsiset_handle, argv[0] ) == 0 ) {
  1387. break;
  1388. }
  1389. previsp = tmpisp;
  1390. }
  1391. if ( tmpisp == NULL ) { /* first element: add a new set */
  1392. tmpisp = (dsgwinclset *)dsgw_ch_malloc( sizeof( dsgwinclset ));
  1393. memset( tmpisp, 0, sizeof( dsgwinclset ));
  1394. tmpisp->dsiset_handle = dsgw_ch_strdup( argv[0] );
  1395. if ( previsp == NULL ) {
  1396. *isp = tmpisp;
  1397. } else {
  1398. previsp->dsiset_next = tmpisp;
  1399. }
  1400. }
  1401. ++tmpisp->dsiset_itemcount;
  1402. tmpisp->dsiset_filenames =
  1403. (char **)dsgw_ch_realloc( tmpisp->dsiset_filenames,
  1404. tmpisp->dsiset_itemcount * sizeof( char * ));
  1405. tmpisp->dsiset_filenames[ tmpisp->dsiset_itemcount - 1 ] =
  1406. dsgw_ch_strdup( argv[1] );
  1407. }
  1408. static void
  1409. add_l10nset( dsgwsubst **l10np, char **argv ) /* 2 args, in argv[] */
  1410. {
  1411. dsgwsubst *tmpsp;
  1412. tmpsp = (dsgwsubst *)dsgw_ch_malloc( sizeof( dsgwsubst ));
  1413. tmpsp->dsgwsubst_from = dsgw_ch_strdup( argv[0] );
  1414. tmpsp->dsgwsubst_to = dsgw_ch_strdup( argv[1] );
  1415. tmpsp->dsgwsubst_next = *l10np;
  1416. *l10np = tmpsp;
  1417. }
  1418. static void
  1419. add_vcardproperty( dsgwvcprop **vcpropp, int argc, char **argv )
  1420. {
  1421. dsgwvcprop *prevvcp, *newvcp, *vcp;
  1422. newvcp = (dsgwvcprop *)dsgw_ch_malloc( sizeof( dsgwvcprop ));
  1423. newvcp->dsgwvcprop_next = NULL;
  1424. newvcp->dsgwvcprop_property = dsgw_ch_strdup( argv[0] );
  1425. newvcp->dsgwvcprop_syntax = dsgw_ch_strdup( argv[1] );
  1426. newvcp->dsgwvcprop_ldaptype = dsgw_ch_strdup( argv[2] );
  1427. if ( argc == 3 ) {
  1428. newvcp->dsgwvcprop_ldaptype2 = NULL;
  1429. } else {
  1430. newvcp->dsgwvcprop_ldaptype2 = dsgw_ch_strdup( argv[3] );
  1431. }
  1432. prevvcp = NULL;
  1433. for ( vcp = *vcpropp; vcp != NULL; vcp = vcp->dsgwvcprop_next ) {
  1434. prevvcp = vcp;
  1435. }
  1436. if ( prevvcp == NULL ) {
  1437. *vcpropp = newvcp;
  1438. } else {
  1439. prevvcp->dsgwvcprop_next = newvcp;
  1440. }
  1441. }
  1442. static char *
  1443. strtok_quote( char *line, char *sep )
  1444. /* This implementation can't handle characters > 127 in sep.
  1445. But it works fine for sep == " \t".
  1446. */
  1447. {
  1448. int inquote;
  1449. char *tmp;
  1450. static char *next;
  1451. if ( line != NULL ) {
  1452. next = line;
  1453. }
  1454. while ( *next && strchr( sep, *next ) ) {
  1455. next++;
  1456. }
  1457. if ( *next == '\0' ) {
  1458. next = NULL;
  1459. return( NULL );
  1460. }
  1461. tmp = next;
  1462. for ( inquote = 0; *next; ) {
  1463. switch ( *next ) {
  1464. case '"':
  1465. if ( inquote ) {
  1466. inquote = 0;
  1467. } else {
  1468. inquote = 1;
  1469. }
  1470. strcpy( next, next + 1 );
  1471. break;
  1472. #ifndef _WIN32
  1473. case '\\':
  1474. strcpy( next, next + 1 );
  1475. break;
  1476. #endif
  1477. default:
  1478. if ( ! inquote ) {
  1479. if ( strchr( sep, *next ) != NULL ) {
  1480. *next++ = '\0';
  1481. return( tmp );
  1482. }
  1483. }
  1484. next++;
  1485. break;
  1486. }
  1487. }
  1488. return( tmp );
  1489. }
  1490. static char buf[BUFSIZ];
  1491. static char *line;
  1492. static int lmax, lcur;
  1493. #define CATLINE( buf ) { \
  1494. int len; \
  1495. len = strlen( buf ); \
  1496. while ( lcur + len + 1 > lmax ) { \
  1497. lmax += BUFSIZ; \
  1498. line = (char *) dsgw_ch_realloc( line, lmax ); \
  1499. } \
  1500. strcpy( line + lcur, buf ); \
  1501. lcur += len; \
  1502. }
  1503. static void
  1504. fp_parse_line(
  1505. char *line,
  1506. int *argcp,
  1507. char **argv
  1508. )
  1509. {
  1510. char * token, buf[ 20 ];
  1511. *argcp = 0;
  1512. for ( token = strtok_quote( line, " \t" ); token != NULL;
  1513. token = strtok_quote( NULL, " \t" ) ) {
  1514. if ( *argcp == MAXARGS ) {
  1515. PR_snprintf( buf, 20,
  1516. XP_GetClientStr(DBT_maxD_), MAXARGS );
  1517. dsgw_error( DSGW_ERR_CONFIGTOOMANYARGS, buf,
  1518. DSGW_ERROPT_EXIT, 0, NULL );
  1519. }
  1520. argv[(*argcp)++] = token;
  1521. }
  1522. argv[*argcp] = NULL;
  1523. }
  1524. static char *
  1525. fp_getline( FILE *fp, int *lineno )
  1526. {
  1527. char *p;
  1528. lcur = 0;
  1529. while ( fgets( buf, sizeof(buf), fp ) != NULL ) {
  1530. if ( (p = strchr( buf, '\n' )) != NULL ) {
  1531. *p = '\0';
  1532. }
  1533. if ( lcur > 0 && ! ldap_utf8isspace( buf ) ) {
  1534. return( line ); /* return previously saved line */
  1535. }
  1536. CATLINE( buf );
  1537. (*lineno)++;
  1538. if ( ! ldap_utf8isspace( buf )) {
  1539. return( line ); /* return this line */
  1540. }
  1541. }
  1542. buf[0] = '\0';
  1543. return( lcur > 0 ? line : NULL );
  1544. }
  1545. static void
  1546. fp_getline_init( int *lineno )
  1547. {
  1548. *lineno = 0;
  1549. buf[0] = '\0';
  1550. }
  1551. static int
  1552. ldapdb_url_parse( char *url, LDAPDBURLDesc **ldbudpp )
  1553. {
  1554. /*
  1555. * Pick apart the pieces of an ldapdb:// quasi-URL
  1556. */
  1557. LDAPDBURLDesc *ldbudp;
  1558. char *basedn;
  1559. *ldbudpp = NULL;
  1560. if ( strncasecmp( url, LDAPDB_URL_PREFIX, LDAPDB_URL_PREFIX_LEN )) {
  1561. return( DSGW_ERR_LDAPDBURL_NOTLDAPDB );
  1562. }
  1563. /* allocate return struct */
  1564. ldbudp = (LDAPDBURLDesc *) dsgw_ch_malloc( sizeof( LDAPDBURLDesc ));
  1565. /* Make a copy */
  1566. url = dsgw_ch_strdup( url );
  1567. ldbudp->ludb_path = url + LDAPDB_URL_PREFIX_LEN;
  1568. /* Must start with a "/" (or "x:" on NT) */
  1569. if ( ldbudp->ludb_path[ 0 ] != '/'
  1570. #ifdef _WIN32
  1571. && ( !ldap_utf8isalpha( ldbudp->ludb_path )
  1572. || ldbudp->ludb_path[ 1 ] != ':' )
  1573. #endif
  1574. ) {
  1575. free( url );
  1576. free( ldbudp );
  1577. return( DSGW_ERR_LDAPDBURL_BAD );
  1578. }
  1579. /* Find base DN */
  1580. if (( basedn = strrchr( ldbudp->ludb_path, '/' )) == NULL ) {
  1581. free( url );
  1582. free( ldbudp );
  1583. return( DSGW_ERR_LDAPDBURL_BAD );
  1584. }
  1585. *basedn++ = '\0';
  1586. ldbudp->ludb_dn = basedn;
  1587. dsgw_form_unescape( ldbudp->ludb_dn );
  1588. *ldbudpp = ldbudp;
  1589. return( 0 );
  1590. }
  1591. #ifdef XP_WIN32
  1592. /* convert forward slashes to backwards ones */
  1593. static void
  1594. dsgw_unix2dospath( char *path )
  1595. {
  1596. if( path ) {
  1597. while( *path ) {
  1598. if( *path == '/' ) {
  1599. *path = '\\';
  1600. }
  1601. path++;
  1602. }
  1603. }
  1604. }
  1605. #endif
  1606. /*
  1607. * Function: dsgw_valid_context
  1608. *
  1609. * Returns: 1 if context doesn't have / . \ ,etc, 0 else
  1610. *
  1611. * Description: context is the name of the config file
  1612. * that is passed into the CGI.
  1613. * Let's say context = pb
  1614. * then it gets translated into: ../context/pb.conf
  1615. * so we have to make sure that context
  1616. * only contains numbers or letters, and nothing else
  1617. *
  1618. * Author: RJP
  1619. *
  1620. */
  1621. static int
  1622. dsgw_valid_context()
  1623. {
  1624. char *local_context = NULL;
  1625. /*Get a local pointer to the global context*/
  1626. local_context = context;
  1627. if (local_context == NULL) {
  1628. return(1);
  1629. }
  1630. for ( ; *local_context; LDAP_UTF8INC(local_context)) {
  1631. if (!ldap_utf8isalnum(local_context)) {
  1632. /*Allow dashes and underscores*/
  1633. if (*local_context == '-' || *local_context == '_') {
  1634. continue;
  1635. }
  1636. return(0);
  1637. }
  1638. }
  1639. return(1);
  1640. }
  1641. /*
  1642. * Function: dsgw_valid_docname
  1643. *
  1644. * Returns: 1 if context doesn't have / . \ ,etc, 0 else
  1645. *
  1646. * Description: Checks to make sure that filename contains
  1647. * only alphanumeric values and one dot
  1648. *
  1649. * Author: RJP
  1650. *
  1651. */
  1652. int
  1653. dsgw_valid_docname(char *filename)
  1654. {
  1655. int dots = 0;
  1656. char *local_filename = NULL;
  1657. local_filename = filename;
  1658. if (local_filename == NULL) {
  1659. return(1);
  1660. }
  1661. for ( ; *local_filename; LDAP_UTF8INC(local_filename)) {
  1662. /*If it's not a number or a letter...*/
  1663. if (!ldap_utf8isalnum(local_filename)) {
  1664. /*If it's a dot, and there haven't been any other dots...*/
  1665. if (*local_filename == '.' && dots == 0) {
  1666. /*Then increment the dot count and continue...*/
  1667. dots ++;
  1668. continue;
  1669. }
  1670. /*Allow dashes and underscores*/
  1671. if (*local_filename == '-' || *local_filename == '_') {
  1672. continue;
  1673. }
  1674. return (0);
  1675. }
  1676. }
  1677. return(1);
  1678. }
  1679. /*
  1680. * Function: dsgw_get_docdir
  1681. *
  1682. * Returns: a pointer to the html directory
  1683. *
  1684. * Description: Just returns gc->gc_docdir
  1685. *
  1686. * Author: RJP
  1687. *
  1688. */
  1689. char *
  1690. dsgw_get_docdir(void)
  1691. {
  1692. return(gc->gc_docdir);
  1693. }
  1694. /*
  1695. * Function: browser_is_msie40
  1696. *
  1697. * Returns: 1 if HTTP_USER_AGENT is MSIE 4.0 or greater, 0 else
  1698. *
  1699. * Description: MSIE 4.0 doesn't return HTTP_ACCEPT_CHARSET,
  1700. * but it does understand utf-8, so we need to
  1701. * make a special case for it. If the browser
  1702. * being used is MSIE 4.0 or greater, this function
  1703. * returns 1.
  1704. *
  1705. * Author: RJP
  1706. *
  1707. */
  1708. static int
  1709. browser_is_msie40()
  1710. {
  1711. char *p = NULL;
  1712. char *browzer = NULL;
  1713. char version[6];
  1714. int i;
  1715. /* Get the browser name */
  1716. if (( p = getenv( "HTTP_USER_AGENT" )) == NULL ) {
  1717. return(0);
  1718. }
  1719. /* Try to find MSIE in there */
  1720. browzer = strstr (p, "MSIE ");
  1721. /* If nothing, then we're done */
  1722. if (browzer == NULL) {
  1723. return (0);
  1724. }
  1725. /* Skip to the version */
  1726. browzer += 5;
  1727. /* Accumulate the version */
  1728. for (i=0; i < 5 && *browzer != '.' ; i++, browzer++) {
  1729. version[i] = *browzer;
  1730. }
  1731. /* Null terminate */
  1732. version[i] = '\0';
  1733. if (atoi(version) > 3) {
  1734. return(1);
  1735. }
  1736. return(0);
  1737. }
  1738. /*
  1739. * Function: browser_ignores_acceptcharset
  1740. *
  1741. * Returns: 1 if ignoreAcceptCharsetFrom contains the current HTTP_USER_AGENT,
  1742. * 0 else
  1743. *
  1744. * Description: bug fix for #97908:
  1745. * The dsgw doesn't respect the "charset" variable in the dsgw.conf file.
  1746. * E.g., ignoreAcceptCharsetFrom Mozilla/4.01x-NSCP Mozilla/4.03C-NSCP
  1747. *
  1748. */
  1749. static int
  1750. browser_ignores_acceptcharset()
  1751. {
  1752. char *p = NULL;
  1753. char *browzer = NULL;
  1754. int i;
  1755. if ( gc->gc_clientIgnoreACharset == NULL ||
  1756. gc->gc_clientIgnoreACharset[0] == NULL )
  1757. return 0;
  1758. /* Get the browser name */
  1759. if (( p = getenv( "HTTP_USER_AGENT" )) == NULL ) {
  1760. return 0;
  1761. }
  1762. browzer = dsgw_ch_strdup_tolower( p );
  1763. for ( i = 0; gc->gc_clientIgnoreACharset[i]; i++ ) {
  1764. if ( strstr( browzer, gc->gc_clientIgnoreACharset[i] ) != NULL )
  1765. return 1;
  1766. }
  1767. free( browzer );
  1768. return 0;
  1769. }
  1770. static void
  1771. set_dsgwcharset()
  1772. {
  1773. auto char* fname = dsgw_file2path (gc->gc_configdir, "dsgwcharset.conf");
  1774. auto FILE* f = fopen (fname, "r");
  1775. if (f != NULL) {
  1776. auto char buf[BUFSIZ];
  1777. if (fgets (buf, sizeof(buf), f)) {
  1778. auto const size_t buflen = strlen (buf);
  1779. if (buf[buflen-1] == '\n') {
  1780. buf[buflen-1] = '\0';
  1781. }
  1782. gc->gc_charset = dsgw_ch_strdup (buf);
  1783. }
  1784. fclose (f);
  1785. }
  1786. free (fname);
  1787. }
  1788. static char *
  1789. dsgw_ch_strdup_tolower( const char *s )
  1790. {
  1791. int len, i;
  1792. char *p, *sp, *dp;
  1793. len = strlen( s ) + 1;
  1794. dp = p = dsgw_ch_malloc( len );
  1795. sp = (char *)s;
  1796. for (i = 0; i < len; i++, dp++, sp++)
  1797. *dp = tolower(*sp);
  1798. return( p );
  1799. }
  1800. static scriptrange_t**
  1801. parse_scriptranges (char** cargv, size_t cargc)
  1802. {
  1803. auto scriptrange_t** result = (scriptrange_t**)
  1804. dsgw_ch_calloc (cargc + 1, sizeof(scriptrange_t*));
  1805. auto size_t i;
  1806. for (i = 0; i < cargc; ++i) {
  1807. auto scriptrange_t** last = result+i;
  1808. auto char* token;
  1809. auto char* cursor = NULL;
  1810. for (token = ldap_utf8strtok_r (cargv[i], ",;", &cursor); token;
  1811. token = ldap_utf8strtok_r (NULL, ",;", &cursor)) {
  1812. #ifdef DSGW_DEBUG
  1813. dsgw_log ("parse_scriptranges %s\n", token);
  1814. #endif
  1815. *last = dsgw_ch_malloc (sizeof(scriptrange_t));
  1816. (*last)->sr_min = (*token == '-') ? 0 : strtoul (token, &token, 16);
  1817. (*last)->sr_max = (*token != '-') ? (*last)->sr_min
  1818. : ((*++token == '\0') ? ULONG_MAX : strtoul (token, &token, 16));
  1819. last = &((*last)->sr_next);
  1820. }
  1821. *last = NULL;
  1822. }
  1823. result[cargc] = NULL;
  1824. return result;
  1825. }
  1826. scriptorder_t*
  1827. dsgw_scriptorder()
  1828. {
  1829. static scriptorder_t* result = NULL;
  1830. if (result == NULL) {
  1831. auto char* simplename = "dsgwcollate.conf";
  1832. auto char* fname = dsgw_file2path (gc->gc_configdir, simplename);
  1833. auto FILE* fp;
  1834. result = (scriptorder_t*) dsgw_ch_calloc (1, sizeof(scriptorder_t));
  1835. if (NULL == fname) {
  1836. #ifdef DSGW_DEBUG
  1837. dsgw_log ("dsgw_scriptorder can't find %s\n", simplename);
  1838. #endif
  1839. } else if (NULL == (fp = fopen (fname, "r"))) {
  1840. #ifdef DSGW_DEBUG
  1841. dsgw_log ("dsgw_scriptorder can't open %s\n", fname);
  1842. #endif
  1843. } else {
  1844. auto char* line;
  1845. auto int lineno;
  1846. fp_getline_init( &lineno );
  1847. while ( (line = fp_getline( fp, &lineno )) != NULL ) {
  1848. auto int cargc;
  1849. auto char* cargv[ MAXARGS ];
  1850. /* skip comments and blank lines */
  1851. if ( line[0] == '#' || line[0] == '\0' ) {
  1852. continue;
  1853. }
  1854. fp_parse_line( line, &cargc, cargv );
  1855. if ( !strcasecmp (cargv[0], "caseIgnoreAccents")) {
  1856. result->so_caseIgnoreAccents = 1;
  1857. } else if ( !strcasecmp (cargv[0], "sort")) {
  1858. result->so_sort = parse_scriptranges (cargv+1, cargc-1);
  1859. } else if ( !strcasecmp (cargv[0], "display")) {
  1860. result->so_display = parse_scriptranges (cargv+1, cargc-1);
  1861. } else {
  1862. #ifdef DSGW_DEBUG
  1863. dsgw_log ("%s/%i: unknown keyword %s\n", fname, lineno, cargv[0]);
  1864. #endif
  1865. }
  1866. }
  1867. fclose (fp);
  1868. #ifdef DSGW_DEBUG
  1869. dsgw_log ("dsgw_scriptorder %s line %i\n", fname, lineno);
  1870. #endif
  1871. }
  1872. if (fname) free (fname);
  1873. }
  1874. return result;
  1875. }