| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560 |
- /** --- BEGIN COPYRIGHT BLOCK ---
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- --- END COPYRIGHT BLOCK --- */
- /*
- * ldaputil.c -- LDAP utility functions -- HTTP gateway
- */
- #include "dsgw.h"
- #include "dbtdsgw.h"
- #include "../../include/disptmpl.h"
- #ifndef NO_LIBLCACHE
- #include <lcache.h>
- #endif
- #if XP_WIN32
- #include <windows.h>
- #include <io.h>
- #include <fcntl.h>
- #endif
- static dsgwtmplinfo *init_listdisplay( char *tmplname, unsigned long options );
- static int do_search( dsgwtmplinfo *tip, LDAP *ld, char *base, int scope,
- char *filter, LDAPMessage **msgpp );
- static void handle_search_results( dsgwtmplinfo *tip, LDAP *ld, int rc,
- LDAPMessage *msgp, unsigned long options );
- static int LDAP_CALL LDAP_CALLBACK
- get_rebind_credentials( LDAP *ld, char **whop, char **credp,
- int *methodp, int freeit, void *arg );
- static void strcpy_special_undo( char *d, char *s );
- static int entry2htmlwrite( void *fp, char *buf, int len );
- static void emit_one_loc_dn( char *dn, char *friendlyname, char *rootname,
- int only_one );
- static char *uid2dn( LDAP *ld, char *uid, char *base, int *ldaprc,
- char **lderrtxtp, char **errsp );
- static void return_one_attr( LDAP *ld, LDAPMessage *entry, char *attrtype,
- char *mimetype, int valindex );
- static void break_up_one_attr( char *attr, char **attrtypep, char **mimetypep,
- int *valindexp );
- /* binddn and bindpasswd are used in get_rebind_credentials() */
- static char *binddn = NULL, *bindpasswd = NULL;
- #ifndef DSGW_NO_SSL
- /*static CERTCertDBHandle certdbh;*/
- static char * certdbh;
- #endif
- /*
- * initialize various LDAP library things -- any non-NULL parameters are
- * initialized and set. If an error occurs, this function will not
- * return at all.
- * If an LDAP connection was opened, this function will return either
- * DSGW_BOUND_ASUSER if a valid cookie was found in the environment
- * and we were able to bind to the directory as that user. If no
- * cookie was found, or the cookie would not be used to bind, then
- * an anonymous bind is performed and DSGW_BOUND_ANONYMOUS is returned.
- * If skipac (skip authentication check) is non-zero, then this
- * function will always authenticate as NULL.
- *
- * If we are configured to use a local LDAP database instead of a real
- * directory server, we always do an unauthenticated bind but we return
- * DSGW_BOUND_ASUSER. This is done to keep our CGIs that check for a
- * return code of DSGW_BOUND_ASUSER happy.
- *
- * If skipauthwarning is set, then we don't display the javascript
- * auth warning for searches. - RJP
- */
- int
- dsgw_init_ldap( LDAP **ldp, LDAPFiltDesc **lfdpp, int skipac, int skipauthwarning )
- {
- char *path;
- char *userid, *dn, *rndstr, *passwd, *cookie, *p;
- int ret = 0, optval, limit;
- #ifdef XP_WIN32
- WSADATA wsadata;
- #endif
- /* LDAP search filters */
- if ( lfdpp != NULL ) {
- path = dsgw_file2path( gc->gc_configdir, DSGW_FILTERFILE );
- if (( *lfdpp = ldap_init_getfilter( path )) == NULL ) {
- dsgw_error( DSGW_ERR_BADCONFIG, path, DSGW_ERROPT_EXIT, 0, NULL );
- }
- free( path );
- ret = 0;
- }
- #ifdef XP_WIN32
- if( ret = WSAStartup(0x0101, &wsadata ) != 0 )
- dsgw_error( DSGW_ERR_WSAINIT, NULL, DSGW_ERROPT_EXIT, 0, NULL );
- #endif /* XP_WIN32 */
- /* LDAP connection */
- if ( ldp != NULL ) {
- if ( gc == NULL ) {
- dsgw_error( DSGW_ERR_INTERNAL,
- XP_GetClientStr(DBT_ldapInitLcacheInitAttemptedBefor_),
- DSGW_ERROPT_EXIT, 0, NULL );
- }
- if ( gc->gc_localdbconf == NULL ) {
- /* "Real LDAP server" case */
- #ifdef DSGW_NO_SSL
- *ldp = ldap_init( gc->gc_ldapserver, gc->gc_ldapport );
- #else /* DSGW_NO_SSL */
- if ( gc->gc_ldapssl ) {
- if ( gc->gc_securitypath == NULL ) {
- dsgw_error( DSGW_ERR_NOSECPATH, NULL, DSGW_ERROPT_EXIT,
- 0, NULL );
- }
- if ( ldapssl_client_init( gc->gc_securitypath,
- &certdbh ) < 0 ) {
- dsgw_error( DSGW_ERR_SSLINIT, gc->gc_securitypath,
- DSGW_ERROPT_EXIT, 0, NULL );
- }
- *ldp = ldapssl_init( gc->gc_ldapserver, gc->gc_ldapport, 1 );
- dsgw_NSSInitializedAlready = 1;
- } else {
- *ldp = ldap_init( gc->gc_ldapserver, gc->gc_ldapport );
- }
- #endif /* !DSGW_NO_SSL */
- if ( *ldp == NULL ) {
- dsgw_error( DSGW_ERR_LDAPINIT, NULL, DSGW_ERROPT_EXIT, 0,
- NULL );
- }
- }
- #ifndef NO_LIBLCACHE
- else {
- /* Local DB case */
- if (( *ldp = ldap_init( NULL, 0 )) == NULL ) {
- dsgw_error( DSGW_ERR_LDAPINIT, NULL, DSGW_ERROPT_EXIT, 0,
- NULL );
- }
- if ( lcache_init( *ldp, gc->gc_localdbconf ) != 0 ) {
- dsgw_error( DSGW_ERR_LCACHEINIT, strerror(errno),
- DSGW_ERROPT_EXIT, 0, NULL );
- }
- optval = 1;
- (void) ldap_set_option( *ldp, LDAP_OPT_CACHE_ENABLE, &optval );
- optval = LDAP_CACHE_LOCALDB;
- (void) ldap_set_option( *ldp, LDAP_OPT_CACHE_STRATEGY, &optval );
- }
- #endif
- rndstr = dn = NULL;
- passwd = dsgw_get_cgi_var( "passwd", DSGW_CGIVAR_OPTIONAL );
- if (( p = dsgw_get_cgi_var( "ldapsizelimit", DSGW_CGIVAR_OPTIONAL ))
- != NULL ) {
- limit = atoi( p );
- (void) ldap_set_option( *ldp, LDAP_OPT_SIZELIMIT, &limit );
- }
- if (( p = dsgw_get_cgi_var( "ldaptimelimit", DSGW_CGIVAR_OPTIONAL ))
- != NULL ) {
- limit = atoi( p );
- (void) ldap_set_option( *ldp, LDAP_OPT_TIMELIMIT, &limit );
- }
- /*
- * we don't bother with authentication if:
- * the "skipac" flag is non-zero OR
- * no "passwd" form element was passed in and we are using local db
- */
- if ( !skipac && ( passwd != NULL || gc->gc_localdbconf == NULL )) {
- /*
- * There are several ways in which authentication might
- * happen.
- */
- if ( gc->gc_admserv ) {
- /*
- * We're running under the admin server, so ask libadmin
- * for the user's credentials. If a password comes as a form
- * field, it overrides value we get from admin server
- */
- (void)dsgw_get_adm_identity( *ldp, &userid, &dn,
- ( passwd == NULL ) ? &passwd : NULL, DSGW_ERROPT_EXIT );
- #ifdef DSGW_DEBUG
- dsgw_log( "dsgw_init_ldap: run under admserv, user id = %s, "
- "dn = %s, passwd = %s, skipac = %d, dn = 0x%x\n",
- userid == NULL ? "NULL" : userid,
- dn == NULL ? "NULL" : dn,
- passwd == NULL ? "NULL" : passwd,
- skipac, dn );
- #endif
- } else {
- /*
- * Not running under admin server. The DN and password
- * might come in as form fields, or the authentication
- * might be accomplished via a client-side cookie which
- * gets looked up in the gateway's cookie database.
- */
- /* check for dn/binddn in request */
- if ( passwd != NULL ) {
- if (( dn = dsgw_get_escaped_cgi_var( "escapedbinddn",
- "binddn", DSGW_CGIVAR_OPTIONAL )) == NULL &&
- ( dn = dsgw_get_cgi_var( "dn",
- DSGW_CGIVAR_OPTIONAL )) == NULL ) {
- free( passwd );
- passwd = NULL;
- } else {
- /* got DN: undo extra level of escaping */
- dsgw_form_unescape( dn );
- }
- }
- if ( passwd == NULL ) {
- /* Check for a valid authentication cookie */
- cookie = dsgw_get_auth_cookie();
- if ( cookie != NULL ) {
- if ( dsgw_parse_cookie( cookie, &rndstr, &dn ) == 0 ) {
- int ckrc;
- if (( ckrc = dsgw_ckdn2passwd( rndstr, dn,
- &passwd )) != 0 ) {
- passwd = NULL;
- dn = NULL;
- /*
- * Delete the cookie and print out the error message.
- * dn2passwd_error() returns 1 if the CGI should exit,
- * 0 if it should continue.
- */
- if (dsgw_dn2passwd_error( ckrc, skipauthwarning )) {
- exit( 0 );
- }
- }
- }
- }
- if ( rndstr != NULL ) {
- free( rndstr );
- }
- if ( cookie != NULL ) {
- free( cookie );
- }
- }
- }
- }
- /*
- * try to use LDAP version 3 but fall back to v2 if bind fails
- */
- optval = LDAP_VERSION3;
- (void)ldap_set_option( *ldp, LDAP_OPT_PROTOCOL_VERSION, &optval );
- /*
- * If everything above failed to set the dn/password, then use
- * the binddn and bindpw, if any.
- */
- if (dn == NULL && passwd == NULL &&
- strlen(gc->gc_binddn) > 0 && strlen(gc->gc_bindpw) > 0) {
- dn = dsgw_ch_strdup(gc->gc_binddn);
- passwd = dsgw_ch_strdup(gc->gc_bindpw);
- }
- if (( ret = ldap_simple_bind_s( *ldp, dn, passwd ))
- == LDAP_PROTOCOL_ERROR ) {
- optval = LDAP_VERSION2;
- (void)ldap_set_option( *ldp, LDAP_OPT_PROTOCOL_VERSION,
- &optval );
- ret = ldap_simple_bind_s( *ldp, dn, passwd );
- }
- if ( ret != LDAP_SUCCESS ){
- dsgw_ldap_error( *ldp, DSGW_ERROPT_DURINGBIND );
- /* Display back button */
- dsgw_form_begin( NULL, NULL );
- dsgw_emits( "\n<CENTER><TABLE border=2 width=\"100%\"><TR>\n" );
- dsgw_emits( "<TD WIDTH=\"100%\" ALIGN=\"center\">\n" );
- dsgw_emitf( "<INPUT TYPE=\"button\" VALUE=\"%s\" "
- "onClick=\"history.back()\">\n",
- XP_GetClientStr(DBT_goBack_) );
- dsgw_emits( "\n</TABLE></CENTER></FORM>\n" );
- exit(0);
- }
- if (( dn != NULL ) && ( passwd != NULL )) {
- ret = DSGW_BOUND_ASUSER;
- binddn = dn;
- bindpasswd = passwd;
- ldap_set_rebind_proc( *ldp, get_rebind_credentials, NULL );
- } else if ( gc->gc_localdbconf != NULL ) {
- ret = DSGW_BOUND_ASUSER; /* a small, harmless lie */
- } else {
- ret = DSGW_BOUND_ANONYMOUS;
- }
- }
- return ret;
- }
- /*
- * get user identity from the admin. server (if running under it)
- * if uidp is non-NULL, it is set to point to user's login id.
- * if dnp is non-NULL, it is set to point to user's DN.
- * if pwdp is non-NULL, it is set to point to user's password.
- * Returns: 0 if all goes well, -1 if an error occurs.
- *
- * Note that ld is used only if dnp != NULL, and then only if the admin server
- * returns NULL when asked for the DN.
- */
- int
- dsgw_get_adm_identity( LDAP *ld, char **uidp, char **dnp, char **pwdp,
- int erropts )
- {
- int rc, need_to_get_dn;
- char *uid;
- static int adm_inited = 0;
- if ( !gc->gc_admserv ) {
- dsgw_error( DSGW_ERR_ADMSERV_CREDFAIL,
- XP_GetClientStr(DBT_notRunningUnderTheAdministration_),
- erropts, 0, NULL );
- return( -1 );
- }
- if ( !adm_inited ) {
- if ( ADM_InitializePermissions( &rc ) < 0 ) {
- dsgw_error( DSGW_ERR_ADMSERV_CREDFAIL,
- XP_GetClientStr(DBT_couldNotInitializePermissions_),
- erropts, 0, NULL );
- return( -1 );
- }
- adm_inited = 1;
- }
- need_to_get_dn = ( dnp != NULL );
- if ( need_to_get_dn && ADM_GetUserDNString( &rc, dnp ) < 0 ) {
- dsgw_error( DSGW_ERR_ADMSERV_CREDFAIL,
- XP_GetClientStr(DBT_couldNotMapUsernameToADnErrorFro_),
- erropts, 0, NULL );
- return( -1 );
- }
- /*
- * get userid if:
- * 1. requested by caller (uidp != NULL)
- * or 2. DN was requested but Admin Server didn't return the DN
- */
- if (( uidp != NULL || ( need_to_get_dn && *dnp == NULL )) &&
- ( ADM_GetCurrentUsername( &rc, &uid ) < 0 || uid == NULL )) {
- dsgw_error( DSGW_ERR_ADMSERV_CREDFAIL,
- XP_GetClientStr(DBT_couldNotGetCurrentUsername_), erropts,
- 0, NULL );
- return( -1 );
- }
- if ( uidp != NULL ) {
- *uidp = uid;
- }
- if ( need_to_get_dn && *dnp == NULL ) {
- /*
- * try to map userid to DN using LDAP search
- */
- int lderr;
- char *errstr, *lderrtxt;
- if (( *dnp = uid2dn( ld, uid, gc->gc_ldapsearchbase, &lderr,
- &lderrtxt, &errstr )) == NULL ) {
- dsgw_error( DSGW_ERR_ADMSERV_CREDFAIL, errstr, erropts, lderr,
- lderrtxt );
- return( -1 );
- }
- }
- if ( pwdp != NULL && ADM_GetCurrentPassword( &rc, pwdp ) < 0 ) {
- dsgw_error( DSGW_ERR_ADMSERV_CREDFAIL,
- XP_GetClientStr(DBT_couldNotGetCurrentUserPassword_), erropts,
- 0, NULL );
- return( -1 );
- }
- return( 0 );
- }
- void
- dsgw_ldap_error( LDAP *ld, int erropts )
- {
- int lderr;
- char *lderrtxt = NULL;
- lderr = ldap_get_lderrno( ld, NULL, &lderrtxt );
- dsgw_error( DSGW_ERR_LDAPGENERAL, dsgw_ldaperr2string( lderr ),
- erropts, lderr, lderrtxt );
- }
- struct ldap_searchobj *
- dsgw_type2searchobj( struct ldap_searchobj *solistp, char *type )
- {
- struct ldap_searchobj *sop;
- for ( sop = ldap_first_searchobj( solistp ); sop != NULL;
- sop = ldap_next_searchobj( solistp, sop )) {
- if ( strcasecmp( type, sop->so_objtypeprompt ) == 0 ) {
- return( sop );
- }
- }
- return( NULL );
- }
- struct ldap_searchattr *
- dsgw_label2searchattr( struct ldap_searchobj *sop, char *label )
- {
- struct ldap_searchattr *sap;
- for ( sap = sop->so_salist; sap != NULL; sap = sap->sa_next ) {
- if ( strcasecmp( label, sap->sa_attrlabel ) == 0 ) {
- return( sap );
- }
- }
- return( NULL );
- }
- struct ldap_searchmatch *
- dsgw_prompt2searchmatch( struct ldap_searchobj *sop, char *prompt )
- {
- struct ldap_searchmatch *smp;
- for ( smp = sop->so_smlist; smp != NULL; smp = smp->sm_next ) {
- if ( strcasecmp( prompt, smp->sm_matchprompt ) == 0 ) {
- return( smp );
- }
- }
- return( NULL );
- }
- static dsgwtmplinfo *
- init_listdisplay( char *tmplname, unsigned long options )
- {
- char *s;
- if (( s = dsgw_get_cgi_var( "listtemplate", DSGW_CGIVAR_OPTIONAL ))
- != NULL ) {
- tmplname = s;
- }
- return( dsgw_display_init( DSGW_TMPLTYPE_LIST, tmplname, options ));
- }
- void
- dsgw_smart_search( LDAP *ld, struct ldap_searchobj *sop, LDAPFiltDesc *lfdp,
- char *base, char *value, unsigned long options )
- {
- int rc;
- LDAPFiltInfo *lfip;
- dsgwtmplinfo *tip;
- LDAPMessage *msgp;
- ldap_setfilteraffixes( lfdp, sop->so_filterprefix, NULL );
- tip = init_listdisplay( sop->so_objtypeprompt, options );
- if (( lfip = ldap_getfirstfilter( lfdp, sop->so_filtertag, value ))
- == NULL ) {
- dsgw_error( DSGW_ERR_NOFILTERS, sop->so_objtypeprompt,
- DSGW_ERROPT_EXIT, 0, NULL );
- }
- for ( ; lfip != NULL; lfip = ldap_getnextfilter( lfdp )) {
- dsgw_set_searchdesc( tip, NULL, lfip->lfi_desc, value );
- rc = do_search( tip, ld, base, sop->so_defaultscope, lfip->lfi_filter,
- &msgp );
- if ( rc != LDAP_SUCCESS ||
- ( msgp != NULL && ldap_count_entries( ld, msgp ) > 0 )) {
- if ( strstr( lfip->lfi_filter, "~=" ) != NULL ) {
- /* always list if approximate filter used to find entry */
- options |= DSGW_DISPLAY_OPT_LIST_IF_ONE;
- }
- break; /* error or got some entries: stop searching */
- }
- }
- handle_search_results( tip, ld, rc, msgp, options );
- }
- void
- dsgw_pattern_search( LDAP *ld, char *listtmpl,
- char *searchdesc2, char *searchdesc3, char *searchdesc4,
- char *filtpattern, char *filtprefix, char *filtsuffix, char *attr,
- char *base, int scope, char *value, unsigned long options )
- {
- char buf[ 4096 ];
- int rc;
- dsgwtmplinfo *tip;
- LDAPMessage *msgp;
- tip = init_listdisplay( listtmpl, options );
- ldap_build_filter( buf, sizeof( buf ), filtpattern,
- filtprefix, filtsuffix, attr, value, NULL );
- dsgw_set_searchdesc( tip, searchdesc2, searchdesc3, searchdesc4 );
- rc = do_search( tip, ld, base, scope, buf, &msgp );
- handle_search_results( tip, ld, rc, msgp, options );
- }
- /*
- * Perform URL-based search.
- * Note that if "ld" is NULL, this routine sets gc->gc_ldapserver and
- * gc->gc_ldapport globals itself, calls dsgw_init_ldap(), and then does
- * the URL-based search. If "ld" is not NULL, no initialization is done
- * here.
- */
- void
- dsgw_ldapurl_search( LDAP *ld, char *ldapurl )
- {
- int rc, ec, saveport, did_init_ldap;
- LDAPMessage *msgp;
- LDAPURLDesc *ludp;
- char *saveserver;
- unsigned long no_options = 0;
- int one_attr = 0;
- if (( rc = ldap_url_parse( ldapurl, &ludp )) != 0 ) {
- switch ( rc ) {
- case LDAP_URL_ERR_NODN:
- ec = DSGW_ERR_LDAPURL_NODN;
- break;
- case LDAP_URL_ERR_BADSCOPE:
- ec = DSGW_ERR_LDAPURL_BADSCOPE;
- break;
- case LDAP_URL_ERR_MEM:
- ec = DSGW_ERR_NOMEMORY;
- break;
- case LDAP_URL_ERR_NOTLDAP:
- default:
- ec = DSGW_ERR_LDAPURL_NOTLDAP;
- break;
- }
- dsgw_error( ec, ldapurl, DSGW_ERROPT_EXIT, 0, NULL );
- }
- if ( ld == NULL ) {
- saveserver = gc->gc_ldapserver;
- gc->gc_ldapserver = ludp->lud_host;
- saveport = gc->gc_ldapport;
- gc->gc_ldapport = ludp->lud_port;
- one_attr = ( ludp->lud_attrs != NULL && ludp->lud_attrs[ 0 ] != NULL && ludp->lud_attrs[ 1 ] == NULL );
- (void)dsgw_init_ldap( &ld, NULL, 0, one_attr );
- did_init_ldap = 1;
- } else {
- did_init_ldap = 0;
- }
- /* XXX a bit of a hack: if it looks like only a DN was included, we
- * assume that a read of the entry is desired.
- */
- if ( ludp->lud_scope == LDAP_SCOPE_BASE && strcasecmp( ludp->lud_filter,
- "(objectClass=*)" ) == 0 ) {
- dsgw_read_entry( ld, ludp->lud_dn, NULL, NULL, ludp->lud_attrs,
- no_options );
- } else {
- dsgwtmplinfo *tip;
- dsgw_send_header();
- tip = init_listdisplay( "urlsearch", no_options );
- dsgw_set_searchdesc( tip, NULL, XP_GetClientStr(DBT_theLDAPFilterIs_), ldapurl );
- rc = do_search( tip, ld, ludp->lud_dn, ludp->lud_scope,
- ludp->lud_filter, &msgp );
- handle_search_results( tip, ld, rc, msgp, no_options );
- }
- if ( did_init_ldap ) {
- ldap_unbind( ld );
- gc->gc_ldapserver = saveserver;
- gc->gc_ldapport = saveport;
- }
- }
- /*
- * do the actual search over LDAP. Return an LDAP error code.
- */
- static int
- do_search( dsgwtmplinfo *tip, LDAP *ld, char *base, int scope, char *filter,
- LDAPMessage **msgpp )
- {
- char **attrlist, *attrs[ 3 ];
- *msgpp = NULL;
- if ( tip == NULL || tip->dsti_attrs == NULL ) {
- attrs[ 0 ] = DSGW_ATTRTYPE_OBJECTCLASS;
- if ( tip != NULL && tip->dsti_sortbyattr != NULL ) {
- attrs[ 1 ] = tip->dsti_sortbyattr;
- attrs[ 2 ] = NULL;
- } else {
- attrs[ 1 ] = NULL;
- }
- attrlist = attrs;
- } else {
- attrlist = tip->dsti_attrs;
- }
- #ifdef DSGW_DEBUG
- dsgw_log ("ldap_search_s(ld,\"%s\",%i,\"%s\")\n", base, scope, filter);
- #endif
- return( ldap_search_s( ld, base, scope, filter, attrlist, 0, msgpp ));
- }
- static int
- is_subtype( const char *sub, const char *sup )
- {
- auto const size_t subLen = strlen( sub );
- auto const size_t supLen = strlen( sup );
- if ( subLen < supLen ) return 0;
- if ( subLen == supLen ) return !strcasecmp( sub, sup );
- if ( sub[supLen] != ';' ) return 0;
- return !strncasecmp( sub, sup, strlen( sup ));
- }
- static const struct berval* LDAP_C LDAP_CALLBACK
- dsgw_keygen( void *arg, LDAP *ld, LDAPMessage *entry )
- {
- auto const char* sortbyattr = (char*)arg;
- auto struct berval* result = NULL;
- if (sortbyattr == NULL) { /* sort by DN */
- auto char* DN = ldap_get_dn( ld, entry );
- if (DN) {
- result = dsgw_strkeygen( CASE_INSENSITIVE, DN );
- ldap_memfree( DN );
- }
- } else {
- auto char* attr;
- auto BerElement *ber;
- for (attr = ldap_first_attribute( ld, entry, &ber ); attr != NULL;
- attr = ldap_next_attribute ( ld, entry, ber ) ) {
- auto char **vals;
- if ( is_subtype( attr, sortbyattr ) &&
- NULL != ( vals = ldap_get_values( ld, entry, attr ))) {
- auto size_t i;
- for ( i = 0; vals[i] != NULL; ++i ) {
- auto struct berval* key = dsgw_strkeygen( CASE_INSENSITIVE, vals[i] );
- if ( result == NULL || dsgw_keycmp( NULL, key, result ) < 0 ) {
- auto struct berval* tmp = result;
- result = key;
- key = tmp;
- #ifdef DSGW_DEBUG
- {
- auto char* ev = dsgw_strdup_escaped( vals[i] );
- auto char* DN = ldap_get_dn( ld, entry );
- dsgw_log( "dsgw_keygen(%s,%s) %p %s\n", sortbyattr, DN, (void*)result, ev );
- ldap_memfree( DN );
- free( ev );
- }
- #endif
- }
- if ( key != NULL ) {
- dsgw_keyfree( arg, key );
- }
- }
- ldap_value_free( vals );
- }
- ldap_memfree( attr );
- }
- if ( ber != NULL ) {
- ldap_ber_free( ber, 0 );
- }
- }
- return result ? result : /* no such attribute */ dsgw_key_last;
- }
- static void
- handle_search_results( dsgwtmplinfo *tip, LDAP *ld, int rc, LDAPMessage *msgp,
- unsigned long options )
- {
- int count;
- LDAPMessage *entry;
- char *dn, *errortext, *lderrtxt, **ocvals;
- count = ( msgp == NULL ) ? 0 : ldap_count_entries( ld, msgp );
- if ( rc == LDAP_SUCCESS ) {
- errortext = NULL;
- lderrtxt = NULL;
- } else {
- errortext = dsgw_ldaperr2string( rc );
- (void)ldap_get_lderrno( ld, NULL, &lderrtxt );
- }
- dsgw_set_search_result( tip, count, errortext, lderrtxt );
- if ( count > 0 ) {
- entry = ldap_first_entry( ld, msgp );
- if ( count == 1 && ( options & DSGW_DISPLAY_OPT_LIST_IF_ONE ) == 0 ) {
- /* found exactly one entry: read and display it */
- dn = ldap_get_dn( ld, entry );
- ocvals = ldap_get_values( ld, entry, DSGW_ATTRTYPE_OBJECTCLASS );
- ldap_msgfree( msgp );
- dsgw_read_entry( ld, dn, ocvals, NULL, NULL, options );
- if ( ocvals != NULL ) {
- ldap_value_free( ocvals );
- }
- return;
- }
- /* list entries */
- #ifdef DSGW_DEBUG
- dsgw_log( "handle_search_results: sort entries by %s\n",
- tip->dsti_sortbyattr ? tip->dsti_sortbyattr : "DN" );
- #endif
- ldap_keysort_entries( ld, &msgp, tip->dsti_sortbyattr,
- dsgw_keygen, dsgw_keycmp, dsgw_keyfree );
- for ( entry = ldap_first_entry( ld, msgp ); entry != NULL;
- entry = ldap_next_entry( ld, entry )) {
- dsgw_display_entry( tip, ld, entry, NULL, NULL );
- }
- if ( options & DSGW_DISPLAY_OPT_DNLIST_JS ) {
- int i;
- char *edn, *js0, *js1;
- char **xdn;
- char **sn;
- dsgw_emits( "<SCRIPT LANGUAGE=\"JavaScript\">\n" );
- dsgw_emits( "var dnlist = new Array;\n" );
- for ( i = 0, entry = ldap_first_entry( ld, msgp ); entry != NULL;
- i++, entry = ldap_next_entry( ld, entry )) {
- dn = ldap_get_dn( ld, entry );
- edn = dsgw_strdup_escaped( dn );
- xdn = ldap_explode_dn( dn, 1 );
- dsgw_emitf( "dnlist[%d] = new Object\n", i );
- dsgw_emitf( "dnlist[%d].edn = '%s';\n", i, edn );
- js0 = dsgw_escape_quotes( xdn[ 0 ] );
- if ( xdn[1] != NULL ) {
- js1 = dsgw_escape_quotes( xdn[ 1 ] );
- dsgw_emitf( "dnlist[%d].rdn = '%s, %s';\n", i, js0, js1 );
- free( js1 );
- } else {
- dsgw_emitf( "dnlist[%d].rdn = '%s';\n", i, js0 );
- }
- free( js0 );
- if (( sn = ldap_get_values( ld, entry, "sn" )) == NULL ) {
- js0 = NULL;
- } else {
- js0 = dsgw_escape_quotes( sn[ 0 ] );
- ldap_value_free( sn );
- }
- dsgw_emitf( "dnlist[%d].sn = '%s';\n", i, ( js0 == NULL ) ?
- " " : js0 );
- if ( js0 != NULL ) {
- free( js0 );
- }
- dsgw_emitf( "dnlist[%d].selected = false;\n", i );
- free( edn );
- ldap_value_free( xdn );
- ldap_memfree( dn );
- }
- dsgw_emitf( "dnlist.count = %d;\n", i );
- dsgw_emitf( "</SCRIPT>\n" );
- }
- ldap_msgfree( msgp );
- } else {
- /* Count <= 0 */
- if ( options & DSGW_DISPLAY_OPT_DNLIST_JS ) {
- dsgw_emitf( "<SCRIPT LANGUAGE=\"JavaScript\">\n" );
- dsgw_emitf( "var dnlist = new Array;\n" );
- dsgw_emitf( "dnlist.count = 0;\n" );
- dsgw_emitf( "</SCRIPT>\n" );
- }
- }
- dsgw_display_done( tip );
- }
- /*
- * read and display a single entry. If ocvals is non-NULL, it should
- * contain the list of objectClass values for this entry.
- */
- void
- dsgw_read_entry( LDAP *ld, char *dn, char **ocvals, char *tmplname,
- char **attrs, unsigned long options )
- {
- int rc, one_attr, freeocvals, valindex;
- char *tmpattr, *attr0, *mimetype;
- LDAPMessage *msgp, *entry, *aomsgp, *aoentry;
- dsgwtmpl *tmpl;
- dsgwtmplinfo *tip;
- if (( options & DSGW_DISPLAY_OPT_AUTH ) != 0 ) {
- /*
- * XXX hack -- if we are trying to authenticate, we don't generate an
- * entry display at all. Instead, we generate an authenticate form.
- */
- dsgw_send_header();
- dsgw_emit_auth_form( dn );
- return;
- }
- one_attr = ( attrs != NULL && attrs[ 0 ] != NULL && attrs[ 1 ] == NULL );
- if ( one_attr ) {
- break_up_one_attr( attrs[ 0 ], &tmpattr, &mimetype, &valindex );
- if ( strcasecmp( tmpattr, "_vcard" ) == 0 ) { /* VCards are special */
- dsgw_vcard_from_entry( ld, dn, mimetype );
- return;
- }
- attr0 = attrs[ 0 ]; /* replace first & only attr. */
- attrs[ 0 ] = tmpattr;
- } else {
- attr0 = NULL;
- }
- if ( tmplname == NULL && ( tmplname = dsgw_get_cgi_var( "displaytemplate",
- DSGW_CGIVAR_OPTIONAL )) == NULL && attrs == NULL ) {
- /* determine what display template to use based on objectClass values */
- freeocvals = 0;
- if ( ocvals == NULL ) { /* read entry to get objectClasses */
- char *attrs[ 2 ];
- attrs[ 0 ] = DSGW_ATTRTYPE_OBJECTCLASS;
- attrs[ 1 ] = NULL;
- if (( rc = ldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*",
- attrs, 0, &msgp )) != LDAP_SUCCESS ||
- ( entry = ldap_first_entry( ld, msgp )) == NULL ) {
- dsgw_ldap_error( ld, DSGW_ERROPT_EXIT );
- }
- ocvals = ldap_get_values( ld, msgp, DSGW_ATTRTYPE_OBJECTCLASS );
- freeocvals = 1;
- ldap_msgfree( msgp );
- }
- if ( ocvals == NULL || ( tmpl = dsgw_oc2template( ocvals )) == NULL ) {
- tmplname = NULL;
- } else {
- tmplname = tmpl->dstmpl_name;
- }
- if ( freeocvals ) {
- ldap_value_free( ocvals );
- }
- }
- if ( tmplname == NULL ) {
- tip = NULL;
- if ( !one_attr ) {
- char *title;
- if (( title = ldap_dn2ufn( dn )) == NULL ) {
- title = dn;
- }
- dsgw_send_header();
- dsgw_html_begin( title, 1 );
- dsgw_emitf( "<FONT SIZE=\"+1\">\n%s\n</FONT>\n",
- XP_GetClientStr(DBT_noteThereIsNoDisplayTemplateForT_) );
- }
- } else if (( tip = dsgw_display_init( DSGW_TMPLTYPE_DISPLAY, tmplname,
- options )) != NULL ) {
- dsgw_send_header();
- attrs = tip->dsti_attrs;
- }
- /* now read the attributes needed for the template */
- if (( rc = ldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*",
- attrs, 0, &msgp )) != LDAP_SUCCESS ) {
- dsgw_ldap_error( ld, DSGW_ERROPT_EXIT );
- }
- if (( entry = ldap_first_entry( ld, msgp )) == NULL ) {
- ldap_msgfree( msgp );
- dsgw_ldap_error( ld, DSGW_ERROPT_EXIT );
- }
- /* and retrieve attribute types only if we need any of them */
- if ( one_attr || tip == NULL || tip->dsti_attrsonly_attrs == NULL ) {
- aomsgp = NULL;
- } else {
- if (( rc = ldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*",
- tip->dsti_attrsonly_attrs, 1, &aomsgp )) != LDAP_SUCCESS ) {
- dsgw_ldap_error( ld, DSGW_ERROPT_EXIT );
- }
- /*
- * if no entries were returned, "aoentry" will be set to NULL by the
- * next statement. We don't treat that as an error since we know the
- * entry exists. It probably just means none of the "attrsonly" types
- * were present in the entry.
- */
- aoentry = ldap_first_entry( ld, aomsgp );
- }
- /* display it (finally!) */
- if ( one_attr ) {
- return_one_attr( ld, entry, attrs[ 0 ], mimetype, valindex );
- } else if ( tip == NULL ) {
- /* no template available -- display in an ugly but complete manner */
- if (( rc = ldap_entry2html( ld, NULL, entry, NULL, NULL, NULL,
- entry2htmlwrite, stdout, "\n", 0, LDAP_DISP_OPT_HTMLBODYONLY,
- NULL, NULL )) != LDAP_SUCCESS ) {
- dsgw_ldap_error( ld, DSGW_ERROPT_EXIT );
- }
- dsgw_html_end();
- } else {
- /* use template to create a nicely formatted display */
- dsgw_display_entry( tip, ld, entry, aoentry, NULL );
- dsgw_display_done( tip );
- }
- if ( attr0 != NULL ) {
- attrs[ 0 ] = attr0; /* if we replaced this, put original back */
- }
- if ( msgp != NULL ) {
- ldap_msgfree( msgp );
- }
- if ( aomsgp != NULL ) {
- ldap_msgfree( aomsgp );
- }
- }
- /*
- * return 1 if the entry already exists, 0 if not, -1 if some error occurs
- */
- int
- dsgw_ldap_entry_exists( LDAP *ld, char *dn, char **matchedp,
- unsigned long erropts )
- {
- LDAPMessage *msgp;
- int rc;
- msgp = NULL;
- if ( matchedp != NULL ) {
- *matchedp = NULL;
- }
- if (( rc = do_search( NULL, ld, dn, LDAP_SCOPE_BASE, "(objectClass=*)",
- &msgp )) != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT ) {
- dsgw_ldap_error( ld, erropts );
- }
- if ( msgp == NULL || rc == LDAP_NO_SUCH_OBJECT ) {
- rc = 0;
- if ( matchedp != NULL ) {
- (void)ldap_get_lderrno( ld, matchedp, NULL );
- }
- } else {
- rc = ( ldap_count_entries( ld, msgp ) > 0 ? 1 : 0 );
- ldap_msgfree( msgp );
- }
- return( rc );
- }
- static int
- entry2htmlwrite( void *fp, char *buf, int len )
- {
- return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
- }
- /*
- * return 1 if the entry's parent exists, 0 if not, -1 if some error occurs.
- * If the entry is the same as gc->gc_ldapsearchbase, then we return 1,
- * so we don't prevent people from adding their organizational entry.
- */
- int
- dsgw_ldap_parent_exists( LDAP *ld, char *dn, unsigned long erropts )
- {
- LDAPMessage *msgp;
- int rc;
- /* Is "dn" == gc->gc_ldapsearchbase? */
- msgp = NULL;
- if (( rc = do_search( NULL, ld, dn, LDAP_SCOPE_BASE, "(objectClass=*)",
- &msgp )) != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT ) {
- dsgw_ldap_error( ld, erropts );
- }
- if ( msgp == NULL ) {
- rc = 0;
- } else {
- rc = ( ldap_count_entries( ld, msgp ) > 0 ? 1 : 0 );
- ldap_msgfree( msgp );
- }
- return( rc );
- }
- /*
- * this function is called back by LIBLDAP when chasing referrals
- */
- static int LDAP_CALL LDAP_CALLBACK
- get_rebind_credentials( LDAP *ld, char **whop, char **credp,
- int *methodp, int freeit, void *arg )
- {
- if ( !freeit ) {
- *whop = binddn;
- *credp = bindpasswd;
- *methodp = LDAP_AUTH_SIMPLE;
- }
- return( LDAP_SUCCESS );
- }
- char *
- dsgw_get_binddn()
- {
- return( binddn );
- }
- /*
- * return 1 if bound using "dn"
- * return 0 if definitely bound as someone else
- * return "def_answer" is we can't tell for sure
- */
- int
- dsgw_bound_as_dn( char *dn, int def_answer )
- {
- int i, rc;
- char **rdns1, **rdns2;
- if ( binddn == NULL ) {
- /*
- * not authenticated: if not using local db or using it as an
- * end-user, return the default
- */
- if ( gc->gc_localdbconf == NULL || gc->gc_enduser ) {
- return( def_answer );
- }
- /*
- * if using local db as an admin, return "bound as someone else"
- * since there is no access control enforced anyways.
- */
- return( 0 );
- }
- /* first try a simple case-insensitive comparison */
- if ( strcasecmp( binddn, dn ) == 0 ) {
- return( 1 ); /* DNs are the same */
- }
- /*
- * These DNs may not have the same spacing or punctuation. Compare RDN
- * components to eliminate any differences.
- */
- if (( rdns1 = ldap_explode_dn( binddn, 0 )) == NULL ) {
- return( def_answer ); /* we don't know: return the default */
- }
- if (( rdns2 = ldap_explode_dn( dn, 0 )) == NULL ) {
- ldap_value_free( rdns1 );
- return( def_answer ); /* we don't know: return the default */
- }
- for ( i = 0; rdns1[ i ] != NULL && rdns2[ i ] != NULL; ++i ) {
- if ( strcasecmp( rdns1[ i ], rdns2[ i ] ) != 0 ) {
- break; /* DNs are not the same */
- }
- }
- rc = ( rdns1[ i ] == NULL && rdns2[ i ] == NULL );
- ldap_value_free( rdns1 );
- ldap_value_free( rdns2 );
- return( rc );
- }
- /*
- * Compare 2 DNs. Return 1 if they are equivalent, 0 if not.
- */
- int
- dsgw_dn_cmp( char *dn1, char *dn2 )
- {
- int i, rc;
- char **rdns1, **rdns2;
- /* first try a simple case-insensitive comparison */
- if ( dsgw_utf8casecmp( (unsigned char *)dn1, (unsigned char *)dn2 ) == 0 ) {
- return( 1 ); /* DNs are the same */
- }
- /*
- * These DNs may not have the same spacing or punctuation. Compare RDN
- * components to eliminate any differences.
- */
- if (( rdns1 = ldap_explode_dn( dn1, 0 )) == NULL ) {
- return( 0 ); /* we don't know: return 0 */
- }
- if (( rdns2 = ldap_explode_dn( dn2, 0 )) == NULL ) {
- ldap_value_free( rdns1 );
- return( 0 ); /* we don't know: return 0 */
- }
- for ( i = 0; rdns1[ i ] != NULL && rdns2[ i ] != NULL; ++i ) {
- if ( dsgw_utf8casecmp( (unsigned char *)rdns1[ i ], (unsigned char *)rdns2[ i ] ) != 0 ) {
- break; /* DNs are not the same */
- }
- }
- rc = ( rdns1[ i ] == NULL && rdns2[ i ] == NULL );
- ldap_value_free( rdns1 );
- ldap_value_free( rdns2 );
- return( rc );
- }
- /*
- * Return the parent of dn. The caller is responsible for freeing the
- * returned value. Returns NULL on error.
- */
- char *
- dsgw_dn_parent( char *dn )
- {
- char *dnp;
- int i;
- char **rdns;
- if ( dn == NULL ) {
- return( NULL );
- }
- dnp = dsgw_ch_malloc( strlen( dn ));
- dnp[ 0 ] = '\0';
- if (( rdns = ldap_explode_dn( dn, 0 )) == NULL ) {
- return NULL;
- }
- for ( i = 1; rdns[ i ] != NULL; i++ ) {
- strcat( dnp, rdns[ i ] );
- strcat( dnp, "," );
- }
- /* Get rid of the trailing "," we just appended */
- dnp[ strlen( dnp ) - 1 ] = '\0';
- ldap_value_free( rdns );
- return( dnp );
- }
-
- /*
- * Return 1 if dn1 is the immediate ancestor of dn2, 0 otherwise.
- */
- int
- dsgw_is_dnparent( char *dn1, char *dn2 )
- {
- char *dnp;
- int rc;
- /* A null or zero-length DN cannot have a parent */
- if ( dn2 == NULL || strlen( dn2 ) == 0 ) {
- return 0;
- }
- dnp = dsgw_dn_parent( dn2 );
- rc = dsgw_dn_cmp( dn1, dnp );
- free( dnp );
- return rc;
- }
- /*
- * return malloc'd array of RDN attribute value pairs
- * each element of the array is a string that looks like: TAG=VALUE
- * this is used to extract values from the RDN when a new entry is added
- */
- char **
- dsgw_rdn_values( char *dn )
- {
- char **rdns, **rdncomps, *val;
- int i;
- if (( rdns = ldap_explode_dn( dn, 0 )) == NULL ) {
- return( NULL );
- }
- rdncomps = ldap_explode_rdn( rdns[0], 0 );
- ldap_value_free( rdns );
- if ( rdncomps == NULL ) {
- return( NULL );
- }
- for ( i = 0; rdncomps[ i ] != NULL; ++i ) {
- if (( val = strchr( rdncomps[ i ], '=' )) == NULL ) {
- ldap_value_free( rdncomps );
- return( NULL );
- }
- ++val;
- strcpy_special_undo( val, val ); /* undo in place */
- }
- return( rdncomps );
- }
- /*
- * the following routine was lifted from servers/slapd/ava.c
- * it removes special quoting, etc. from values that appear in an LDAP DN
- */
- static void
- strcpy_special_undo( char *d, char *s )
- {
- int quote;
-
- quote = 0;
- if ( *s == '"' ) {
- s++;
- quote = 1;
- }
- for ( ; *s; LDAP_UTF8INC(s)) {
- switch ( *s ) {
- case '"':
- break;
- case '\\':
- s++;
- /* FALL */
- default:
- d += LDAP_UTF8COPY (d, s);
- break;
- }
- }
- *d = '\0'; LDAP_UTF8DEC(d);
- if ( quote && *d == '"' ) {
- *d = '\0';
- }
- }
- static char *
- uid2dn( LDAP *ld, char *uid, char *base, int *ldaprc, char **lderrtxtp,
- char **errsp )
- {
- char *attrs[] = { "objectclass", NULL };
- char filtbuf[ 85 ]; /* max of 80 char. uid + "uid=" + zero terminator */
- int rc, count;
- LDAPMessage *result;
- LDAPMessage *e;
- char *dn;
-
- *ldaprc = LDAP_SUCCESS; /* optimistic */
- *errsp = *lderrtxtp = NULL;
- if ( ld == NULL || uid == NULL || strlen( uid ) > 80 ) {
- *errsp = XP_GetClientStr(DBT_invalidUserIdOrNullLdapHandle_);
- return NULL;
- }
- PR_snprintf( filtbuf, 85, "uid=%s", uid );
- if (( rc = ldap_search_s( ld, base, LDAP_SCOPE_SUBTREE, filtbuf,
- attrs, 1, &result )) != LDAP_SUCCESS ) {
- *ldaprc = rc;
- (void)ldap_get_lderrno( ld, NULL, lderrtxtp );
- return NULL;
- }
- if (( count = ldap_count_entries( ld, result )) != 1 ) {
- /* Search either returned no entries, or more than one entry */
- ldap_msgfree( result );
- if ( count == 0 ) {
- *errsp = XP_GetClientStr(DBT_noMatchForUserId_);
- } else {
- *errsp = XP_GetClientStr(DBT_moreThanOneMatchForUserId_);
- }
- return NULL;
- }
- dn = NULL;
- if (( e = ldap_first_entry( ld, result )) == NULL ||
- ( dn = ldap_get_dn( ld, e )) == NULL ) {
- *ldaprc = ldap_get_lderrno( ld, NULL, NULL );
- }
- ldap_msgfree( result );
- return( dn );
- }
- /*
- * Emit an HTML "SELECT" object that contains all the o's and ou's that
- * are underneath our default searchbase. If there are none other than
- * the searchbase, we emit a hidden HTML TEXT object that contains the
- * searchbase and the "prefix" and "suffix" are not used. The values for
- * the SELECT options and for the TEXT object are all escaped DNs.
- *
- * Location popup directives look like this:
- * <-- DS_LOCATIONPOPUP "name=VARNAME" "prefix=PREFIX" "suffix=SUFFIX" -->
- *
- * If "prefix" and/or "suffix" are omitted, they default to "".
- * If "name" is omitted it defaults to "base".
- *
- * If there are "location" directives in the dsgw.conf file, we use those
- * instead of actually searching the directory.
- */
- void
- dsgw_emit_location_popup( LDAP *ld, int argc, char **argv, int erropts )
- {
- char line[BIG_LINE];
- char *varname, *prefix, *suffix, *rootname, *dn;
- int i, count, did_init_ldap;
- LDAPMessage *res, *e;
- if (( varname = get_arg_by_name( "name", argc, argv )) == NULL ) {
- varname = "base";
- }
- if (( prefix = get_arg_by_name( "prefix", argc, argv )) == NULL ) {
- prefix = "";
- }
- if (( suffix = get_arg_by_name( "suffix", argc, argv )) == NULL ) {
- suffix = "";
- }
- rootname = get_arg_by_name( "rootname", argc, argv );
- did_init_ldap = 0;
- res = NULL;
- if ( gc->gc_newentryloccount > 0 ) {
- count = gc->gc_newentryloccount;
- } else {
- char *attrs[ 3 ];
- int rc;
- if ( ld == NULL ) {
- (void)dsgw_init_ldap( &ld, NULL, 0, 0 );
- did_init_ldap = 1;
- }
- attrs[ 0 ] = "o";
- attrs[ 1 ] = "ou";
- attrs[ 2 ] = NULL;
- rc = ldap_search_s( ld, gc->gc_ldapsearchbase, LDAP_SCOPE_SUBTREE,
- "(|(objectclass=organization)(objectclass=organizationalunit))",
- attrs, 1, &res );
- if ( rc != LDAP_SUCCESS || res == NULL ) {
- dsgw_ldap_error( ld, erropts );
- return;
- }
- count = ldap_count_entries( ld, res );
- if ( gc->gc_ldapsearchbase == NULL || *gc->gc_ldapsearchbase == '\0' ) {
- ++count; /* include base DN even if it is "" */
- } else {
- /*
- * check to see if search base was one of the entries returned
- * we want to always list the base entry, so we need to check
- */
- for ( e = ldap_first_entry( ld, res ); e != NULL;
- e = ldap_next_entry( ld, e )) {
- if (( dn = ldap_get_dn( ld, e )) == NULL ) {
- dsgw_ldap_error( ld, erropts );
- ldap_msgfree( res );
- return;
- }
- rc = dsgw_dn_cmp( dn, gc->gc_ldapsearchbase );
- free( dn );
- if ( rc ) { /* base DN was returned */
- break;
- }
- }
- if ( e == NULL ) {
- ++count; /* include base DN even if was not returned */
- }
- }
- }
- if ( count > 1 ) {
- util_snprintf( line, BIG_LINE, "%s\n<SELECT NAME=\"%s\">\n",
- prefix, varname );
- } else {
- util_snprintf( line, BIG_LINE, "<INPUT TYPE=\"hidden\" NAME=\"%s\" ",
- varname );
- }
- dsgw_emits( line );
- if ( gc->gc_newentryloccount > 0 ) {
- for ( i = 0; i < gc->gc_newentryloccount; ++i ) {
- emit_one_loc_dn( gc->gc_newentrylocs[ i ].dsloc_dnsuffix,
- gc->gc_newentrylocs[i].dsloc_fullname, rootname,
- ( count < 2 ));
- }
- } else {
- /* always include the base dn first */
- emit_one_loc_dn( gc->gc_ldapsearchbase, NULL, rootname, ( count < 2 ));
- /* XXXmcs it would be nice to do a more intelligent sort here */
- #ifdef DSGW_DEBUG
- dsgw_log( "dsgw_emit_location_popup: ldap_sort_entries(NULL)\n" );
- #endif
- ldap_sort_entries( ld, &res, NULL, dsgw_strcmp (CASE_INSENSITIVE));
- for ( e = ldap_first_entry( ld, res ); e != NULL;
- e = ldap_next_entry( ld, e )) {
- if (( dn = ldap_get_dn( ld, e )) == NULL ) {
- dsgw_ldap_error( ld, erropts );
- ldap_msgfree( res );
- return;
- }
- if ( !dsgw_dn_cmp( dn, gc->gc_ldapsearchbase )) {
- emit_one_loc_dn( dn, NULL, rootname, ( count < 2 ));
- }
- free( dn );
- }
- }
- if ( count > 1 ) {
- util_snprintf( line, BIG_LINE, "</SELECT>\n%s\n", suffix );
- dsgw_emits( line );
- }
- if ( res != NULL ) {
- ldap_msgfree( res );
- }
- if ( did_init_ldap ) {
- ldap_unbind( ld );
- }
- }
- static void
- emit_one_loc_dn( char *dn, char *friendlyname, char *rootname, int only_one )
- {
- char *escapeddn, **rdns, line[ BIG_LINE ];
- rdns = NULL;
- escapeddn = dsgw_strdup_escaped( dn );
- if ( !only_one ) {
- dsgw_emits( "<OPTION" );
- }
- if ( friendlyname == NULL ) { /* use first component of DN */
- if ( *dn == '\0' ) {
- friendlyname = ( rootname == NULL ? XP_GetClientStr(DBT_theEntireDirectory_)
- : rootname );
- } else if (( rdns = ldap_explode_dn( dn, 1 )) == NULL
- || rdns[ 0 ] == NULL ) {
- friendlyname = dn;
- } else {
- friendlyname = rdns[ 0 ];
- }
- }
- util_snprintf( line, BIG_LINE, " VALUE=\"%s\">%s\n", escapeddn,
- only_one ? "" : friendlyname );
- free( escapeddn );
- if ( rdns != NULL ) {
- ldap_value_free( rdns );
- }
- dsgw_emits( line );
- }
- /*
- * Return a MIME document that contains a single value.
- * XXX: does this really belong in ldaputil.c?
- */
- static void
- return_one_attr( LDAP *ld, LDAPMessage *entry, char *attrtype, char *mimetype,
- int valindex )
- {
- char *val;
- struct berval **bvals;
- unsigned long vlen;
- if (( bvals = ldap_get_values_len( ld, entry, attrtype )) == NULL ) {
- dsgw_error( DSGW_ERR_NOATTRVALUE, attrtype, DSGW_ERROPT_EXIT, 0, NULL );
- }
- if ( valindex > ldap_count_values_len( bvals )) {
- dsgw_error( DSGW_ERR_NOATTRVALUE, attrtype, DSGW_ERROPT_EXIT, 0, NULL );
- }
- val = bvals[ valindex ]->bv_val;
- vlen = bvals[ valindex ]->bv_len;
- fprintf( stdout, "Content-Type: %s\n", mimetype );
- fprintf( stdout, "Content-Length: %ld\n\n", vlen );
- #ifdef XP_WIN32
- /* flush any data on stdout before changing the mode */
- fflush( stdout );
- /* set the mode to binary
- so windows doesn't replace with carriage
- return line feed and mess everything up
- */
- _setmode( _fileno( stdout ), _O_BINARY );
- #endif
- fwrite( val, vlen, 1, stdout );
- #ifdef XP_WIN32
- /* flush any remaining binary data */
- fflush( stdout );
- /* set the mode back to text */
- _setmode( _fileno( stdout ), _O_TEXT );
- #endif
- ldap_value_free_len( bvals );
- free( attrtype );
- }
- /*
- * The general format of attrtype is:
- * <attrtype> [ &<mimetype> ] [ &<valindex> ]
- * This routine breaks it up. Callers should free( *attrtypep ) after they
- * are done using attrtypep and mimetypep.
- */
- static void
- break_up_one_attr( char *attr, char **attrtypep, char **mimetypep,
- int *valindexp )
- {
- char *p;
- *attrtypep = dsgw_ch_strdup( attr );
- *mimetypep = "text/plain"; /* default */
- *valindexp = 0; /* default: retrieve first value */
- if (( p = strchr( *attrtypep, '&' )) != NULL ) {
- *p++ = '\0';
- if ( *p != '\0' ) {
- *mimetypep = p;
- if (( p = strchr( *mimetypep, '&' )) != NULL ) {
- *p++ = '\0';
- *valindexp = atoi( p );
- }
- }
- }
- }
|