1 /*_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
5 * Function:..WorldWideWeb-X.500-Gateway - Server-Functions *
6 * Based on web500gw.c 1.3 written by Frank Richter, TU Chemmniz *
7 * which is based on go500gw by Tim Howes, University of *
8 * Michigan - All rights reserved *
10 * Authors:...Dr. Kurt Spanier & Bernhard Winkler, *
11 * Zentrum fuer Datenverarbeitung, Bereich Entwicklung *
12 * neuer Dienste, Universitaet Tuebingen, GERMANY *
15 * Creation date: Z D D V V *
16 * August 16 1995 Z D D V V *
17 * Last modification: Z D D V V *
18 * September 13 1999 ZZZZ DDD V *
20 _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_*/
23 * $Id: queries.c,v 1.8 1999/09/13 13:47:47 zrnsk01 Exp $
30 PUBLIC void do_queries( s, glob , ip_addr, ip_port, hp)
37 char buf[100*BUFSIZ], *query, *tail;
41 struct timeval timeout;
50 /* get time for performance log */
51 gettimeofday(×tore[2], NULL);
53 /* open output-port to waiting client */
54 if ( (fp = fdopen( s, "a+")) == NULL ) {
59 tblsize = getdtablesize();
60 timeout.tv_sec = glob->timeout;
63 FD_SET( fileno( fp ), &readfds );
66 time(&glob->expiretime);
67 if(glob->cache_expire) {
68 glob->expiretime += glob->cache_expire;
71 free(glob->nowtimestr);
72 free(glob->expiretimestr);
74 strftime(tstring, 99, GMT_FORMAT, gmtime(&glob->nowtime));
75 glob->nowtimestr = strdup(tstring);
76 strftime(tstring, 99, GMT_FORMAT2, gmtime(&glob->expiretime));
77 glob->expiretimestr = strdup(tstring);
79 /* get client-query out from the system */
80 if((rc=select(tblsize,(fd_set *)&readfds,NULL,NULL,&timeout))<=0)
83 if ( fgets( buf, sizeof(buf), fp ) == NULL )
86 /* Analyse Web-Client-Type / proxy + log-message */
87 checkwwwclient(fp, ip_addr, ip_port, hp, glob);
91 fprintf( stderr, "got %d bytes\n", len );
94 ber_bprint( buf, len );
96 lber_bprint( buf, len );
101 /* strip of white spaces */
102 query = trim (buf, WSPACE);
107 /* strip "HTTP" from the end of the request */
108 if ((tail = strstr(query, " HTTP")) != NULL ||
109 (tail = strstr(query, " http")) != NULL) {
114 /* recognize GET/HEAD */
115 if (!strncasecmp (query, "get", 3)) {
120 } else if (!strncasecmp (query, "head", 4)) {
127 /* Error because of neither GET- nor HEAD-request */
128 do_error(fp, -2, NOT_IMPLEMENTED, glob);
129 /* fprintf(fp, "HTTP/1.0 501 %s<br>", glob->la[5]); */
134 /* strip off leading white space and '/' */
135 while ( isspace( *query ) || *query == '/') {
140 /* Now the real request is to be analized and served */
142 /* refuse robots if according robots.txt file exists */
144 if (!strcasecmp(query, "robots.txt")){
145 if (http == 1) PRINT_PLAIN_HEADER;
146 disp_file(glob, ROBOTS_TXT_FILE, fp);
151 if( glob->ton_urls && *query == cTON) {
152 if(!glob->ton_urls->admin)
154 if(glob->ton_urls->pass_oc) {
155 glob->max_person = 10000;
156 glob->no_browse = FALSE;
163 /* get time for performance log */
164 gettimeofday(×tore[3], NULL);
166 /* perform handling of pulldown/form retcodes
167 -> gwswitch-redirect || pass */
168 if(*query == cPULLDOWN) {
169 if(strstr(query, "http")) {
173 PRINT_REDIRECT_HEADER;
183 /* perform handling of buttons/form retcodes
184 -> gwswitch-redirect || pass */
185 if(*query == cBUTTON) {
189 strptr = strrchr( query, '=' );
192 if(strstr(query, "http")) {
195 PRINT_REDIRECT_HEADER;
205 /* 1. requests that may be served without DSA */
209 /* display Help-File */
212 syslog (LOG_INFO, "working on query: %c (%s,%u) <%08d>",
213 cHELP, ip_addr, ip_port, glob->svc_cnt);
214 if (http == 1) PRINT_HTML_HEADER;
215 fprintf(fp, "<HTML><HEAD>");
216 disp_file(glob, glob->helpfile, fp);
221 /* request error-explanation */
224 syslog (LOG_INFO, "working on query: %c (%s,%u) <%08d>",
225 cERROR, ip_addr, ip_port, glob->svc_cnt);
226 /* fprintf(fp, HTML_HEAD_TITLE, "Errors", glob->la[100]);
228 do_error( fp, 0 , 1, glob );
232 /* RCC: remote configuration control */
235 syslog (LOG_INFO, "working on query: %c (%s,%u) <%08d>",
236 cCONFIG, ip_addr, ip_port, glob->svc_cnt);
237 if (http == 1) PRINT_HTML_HEADER;
238 fprintf(fp, HTML_HEAD_TITLE, "Configuration", glob->la[100]);
239 output(fp, glob, TRUE);
240 langoutput(fp, glob, TRUE);
245 /* query access-statistic */
248 syslog (LOG_INFO, "working on query: %c (%s,%u) <%08d>",
249 cSTATS, ip_addr, ip_port, glob->svc_cnt);
250 if (http == 1) PRINT_HTML_HEADER;
251 fprintf(fp, HTML_HEAD_TITLE, "Statistics", glob->la[100]);
253 "\n<strong>#############STATISTIC-DISPLAY#############</strong><br>\n" );
254 fprintf( fp, "\n%s\n\n<p>\n", version );
255 (void) put_hackStats (fp, 0);
263 /* with ldap-referral use this host + port + use do_read */
264 /* query looks like this: Wldap://host:port/dn */
265 if ( *query == cREFERRAL ) {
266 char *host, *port, *dn = NULL;
268 glob->ldap_referral_mode = 1;
269 if ( ( host = strstr( query, "ldap://" ) ) ) {
271 if ( ( port = strchr( host, ':' ) ) ) {
273 if ( ( dn = strchr( port, '/' ) ) ) {
275 glob->ldapd = strdup ( host );
276 glob->ldapport = atoi ( port );
286 /* from here on there is needed a connection to the DSA */
287 if ( (ld = ldap_open( glob->ldapd, glob->ldapport )) == NULL ) {
288 if ( debug ) perror( "ldap_open" );
289 do_error( fp, LDAP_SERVER_DOWN, SERVER_ERROR, glob);
294 if(glob->caching_terms)
295 trade_cache(fp, ld, query, glob);
297 /* performance of STRICT-BASEDN (blind out accesses != BASEDN) */
299 if(glob->strict_basedn)
300 strict_basednf(fp, ld, query, glob);
303 /* 2. queries with binding of the owner */
306 /* request of the modification-formulare */
308 /* log the request without password */
311 char qbuf[BUFSIZ], *qbufp;
314 if( ( qbufp = strchr(qbuf, '?')) )
316 syslog (LOG_INFO, "working on query: %s (%s,%u) <%08d>",
317 qbuf, ip_addr, ip_port, glob->svc_cnt);
321 /* follow aliases while searching */
324 ldap_opt = LDAP_DEREF_ALWAYS;
325 ldap_set_option( ld, LDAP_OPT_DEREF, &ldap_opt );
328 ld->ld_deref = LDAP_DEREF_ALWAYS;
331 if ( !searchaliases )
334 ldap_opt = LDAP_DEREF_FINDING;
335 ldap_set_option( ld, LDAP_OPT_DEREF, &ldap_opt );
338 ld->ld_deref = LDAP_DEREF_FINDING;
341 /* send WWW-Formulare with contence of the desired entry
343 do_form( ld, fp, ++query, glob);
345 close_ldap_connections(glob);
349 /* return of the modification-formulare */
352 /* log the request in readable form without password if desired */
355 char qbuf[100*BUFSIZ], *qbufp;
358 if( ( qbufp = strchr (qbuf, '?')) )
361 syslog (LOG_INFO, "working on query: %s (%s,%u) <%08d>",
362 qbuf, ip_addr, ip_port, glob->svc_cnt);
366 /* perform modification with the original request */
367 do_modify( ld, fp, ++query, glob);
369 close_ldap_connections(glob);
377 /* perform all the other requests */
379 /* log the request in readable form first */
382 syslog (LOG_INFO, "working on query: %s (%s,%u) <%08d>",
383 *query ? trimright(query, WSPACE) : "BASEDN", ip_addr, ip_port,
386 /* accesses with resolvation of alias-entries */
389 ldap_opt = LDAP_DEREF_ALWAYS;
390 ldap_set_option( ld, LDAP_OPT_DEREF, &ldap_opt );
393 ld->ld_deref = LDAP_DEREF_ALWAYS;
396 if ( !searchaliases )
399 ldap_opt = LDAP_DEREF_FINDING;
400 ldap_set_option( ld, LDAP_OPT_DEREF, &ldap_opt );
403 ld->ld_deref = LDAP_DEREF_FINDING;
406 /* bind to DSA by order of the user as Web-DN
407 (DN1 or DN2 was decided at check4access) */
411 /* a dummy call as long as socket connections are not settled
415 syslog( LOG_INFO, "do_queries(): calling ldap_simple_bind_s()...\n" );
419 if ( (rc=ldap_simple_bind_s( ld, glob->webdn, glob->webpw ))
421 if ( debug ) ldap_perror( ld, "ldap_simple_bind_s" );
422 do_error( fp, rc, SERVER_ERROR, glob);
427 /* 3. requests to the GW by order of the user */
428 switch ( *query++ ) {
432 do_read( ld, fp, query, 0, glob );
435 /* display second page */
437 do_read( ld, fp, query, 1, glob);
442 do_search( ld, fp, query, glob );
445 /* list entries (browsing) */
447 do_menu( ld, fp, query, "", glob );
451 /* list entries (browsing TON instead of DN) */
454 do_ton( ld, fp, query, glob );
458 /* request GIF-photo (Photo in X.500 as JPEG) */
460 do_pict( ld, fp, query, 1, glob);
463 /* display JPEG-Photo */
465 do_pict( ld, fp, query, 2, glob);
468 /* display X.500-G3FAX-Photo */
470 do_pict( ld, fp, query, 0, glob);
473 /* play Audio-attribute */
475 do_audio( ld, fp, query, 0, glob);
478 /* eXtended query format */
480 do_xtend( ld, fp, query, 0, glob);
483 /* Default (empty query) is browsing of BASEDN */
485 do_menu( ld, fp, glob->basedn->dn, "", glob );
489 /* Job done, terminate connection to the DSA and bye! */
491 close_ldap_connections(glob);
496 /* end of function: do_queries */
498 PUBLIC void timeoutf(sig)
501 /* fprintf(stderr, "timeout!"); */
504 /* end of function: timeoutf */
507 PRIVATE void strict_basednf(fp, ld, query, glob)
513 char dnbuf[BUFSIZ], basednbuf[BUFSIZ], *strptr;
514 LDAPMessage *res, *e;
515 int rc, flag = 0, i, j;
516 struct timeval timeout;
517 char *url = NULL, **uri, *urlnola = NULL;
518 pGW_SWITCH_LINE gw_ptr;
520 char **dnarray, **bdnarray;
524 if( glob->ton_urls && (*query == cTON))
528 /* Patch for FORMs/PULLDOWNs (cPULLDOWN) */
529 if( glob->pull_down_menus && (*query == cPULLDOWN))
532 /* Patch for FORMs/BUTTONs (cBUTTONs) */
533 if( glob->pull_down_menus && (*query == cBUTTON))
537 strcpy(dnbuf, query+1);
541 strcpy(basednbuf, glob->basedn->dn);
543 if( ( strptr = strchr(dnbuf, '?')) )
546 if( *query && !dn_issuffix( dn_normalize(dnbuf), dn_normalize(basednbuf))) {
548 dnarray = dn2charray(dnbuf);
549 bdnarray = glob->basedn->dnarray;
552 if (glob->gw_switch) {
553 for(gw_ptr = glob->gw_switch->list;
554 !flag && gw_ptr; gw_ptr = gw_ptr->next) {
555 if (!dn_cmp ("root", gw_ptr->dn)) {
562 fprintf(stderr, "Fehler:strict_basedn w/o root-switch!!!!\n");
566 for(j=0; bdnarray[j] && dnarray[j]; j++) {
571 dnbufb = strdup(dnbuf);
572 sprintf(dnbuf, "%s%s%s", dnarray[j], *dnbuf ? "," : "" , dnbufb);
574 if ( glob->gw_switch && glob->gw_switch->dynamic) {
576 if ( (rc=ldap_simple_bind_s( ld, glob->webdn, glob->webpw ))
578 if ( debug ) ldap_perror( ld, "ldap_simple_bind_s" );
579 do_error( fp, rc, SERVER_ERROR, glob);
584 timeout.tv_sec = glob->timeout;
587 if ( (rc = ldap_search_st( ld, dnbuf, LDAP_SCOPE_BASE, "objectClass=*",
588 NULL, 0, &timeout, &res )) != LDAP_SUCCESS ) {
589 /* do_error(fp, rc, NOT_FOUND, glob);
595 if ( (e = ldap_first_entry( ld, res )) == NULL ) {
596 do_error(fp, -2, SERVER_ERROR, glob);
601 uri = ldap_get_values( ld, e, "labeledURI" );
602 for(i=0; uri && uri[i] && *uri[i]; i++) {
605 if( ( sp = strchr(uri[i], ' ')) ) {
607 if(strstr(sp, glob->gw_switch->lagws)) {
611 } else if(strstr(sp, GWS))
616 if(!flag && urlnola) {
620 if (glob->gw_switch) {
622 for(gw_ptr = glob->gw_switch->list;
623 !flag && gw_ptr; gw_ptr = gw_ptr->next) {
624 if (!dn_cmp (dnbuf, gw_ptr->dn)) {
630 if(strcmp(bdnarray[j], dnarray[j]))
634 if (http == 1) PRINT_HTML_HEADER;
635 fprintf( fp, HTML_HEAD_TITLE, "ACCESS DENIED", glob->la[100]);
636 disp_file(glob, glob->header, fp);
637 fprintf( fp, "%s\n", glob->la[96]);
638 url_tmp = strdup(url_complete(url, query, ""));
639 fprintf( fp, "<P><A HREF=\"%s\"><b>%s</b></A>\n",
641 disp_file(glob, glob->footer, fp);
644 close_ldap_connections(glob);
648 /* end of function: strict_basednf */
650 PRIVATE void trade_cache(fp, ld, query, glob)
656 pCACHING_TERMS_LINE ca_ptr;
657 char dnbuf[BUFSIZ], rdn[BUFSIZ], *strptr;
661 struct timeval timeout;
662 LDAPMessage *res, *e;
667 strcpy(dnbuf, query+1);
669 strcpy(dnbuf, glob->basedn->dn);
671 if( ( strptr = strchr(dnbuf, '?')) )
674 if( ( strptr = strQuoteChr(rdn, ',')) )
677 for(ca_ptr = glob->caching_terms; ca_ptr; ca_ptr = ca_ptr->next) {
678 if((toupper(*query) == toupper(*ca_ptr->access_type)) ||
679 ( !*query && (toupper(*ca_ptr->access_type) == 'M'))) {
681 if(ca_ptr->rdn_oc && (strstr(str_tolower(rdn), ca_ptr->pattern) ||
682 (*ca_ptr->pattern == '*'))) {
683 time(&glob->expiretime);
684 glob->expiretime += ca_ptr->time;
685 free(glob->expiretimestr);
686 strftime(tstring, 99, GMT_FORMAT2, gmtime(&glob->expiretime));
687 glob->expiretimestr = strdup(tstring);
688 glob->caching = TRUE;
690 if(!ca_ptr->rdn_oc) {
693 if ( (rc=ldap_simple_bind_s( ld, glob->webdn, glob->webpw ))
695 if ( debug ) ldap_perror( ld, "ldap_simple_bind_s" );
696 do_error( fp, rc, SERVER_ERROR, glob);
701 timeout.tv_sec = glob->timeout;
704 if ( (rc = ldap_search_st( ld, dnbuf, LDAP_SCOPE_BASE, "objectClass=*",
705 NULL, 0, &timeout, &res )) != LDAP_SUCCESS ) {
706 do_error(fp, rc, NOT_FOUND, glob);
711 if ( (e = ldap_first_entry( ld, res )) == NULL ) {
712 do_error(fp, -2, SERVER_ERROR, glob);
717 vals = ldap_get_values( ld, e, "objectClass" );
720 if(charray_inlist( vals, ca_ptr->pattern )) {
721 time(&glob->expiretime);
722 glob->expiretime += ca_ptr->time;
723 free(glob->expiretimestr);
724 strftime(tstring, 99, GMT_FORMAT2, gmtime(&glob->expiretime));
725 glob->expiretimestr = strdup(tstring);
726 glob->caching = TRUE;
734 /* end of function: trade_cache */