config.c 58 KB

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