]> git.sur5r.net Git - openldap/blob - contrib/web_ldap/web_ldap.c
Merge in all -devel changes made since branch was created.
[openldap] / contrib / web_ldap / web_ldap.c
1 /* web_ldap.c
2  * Form Processing Web application that returns html based
3  * LDAP data with definitions from a configuration file.
4  *
5  * Jens Moller - Dec 11, 1998
6  */
7
8 #include "portable.h"
9
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <stdio.h>
14
15 #include <ac/stdlib.h>
16 #include <ac/string.h>
17 #include <ac/time.h>
18 #include <ac/unistd.h>
19
20 #include <lber.h>
21 #include <ldap.h>
22 #include "ldif.h"
23 #include "maint_form.h" /* for HTML Form manipulations */
24
25 /* default values */
26 #ifndef LDAP_PORT
27 #define LDAP_PORT 389
28 #endif
29 #ifndef SERVER
30 #define SERVER "ldap.bigfoot.com"
31 #endif
32 #ifndef CONFIG
33 #define CONFIG "web_ldap.cfg"
34 #endif
35
36 #define MAX_ATTRIB 100
37 #define MAX_CHARS  256
38 #define version "v 1.1"
39
40 entry entries[MAX_ENTRIES];
41
42 typedef struct {
43    char servername[MAX_CHARS];
44    char query[MAX_CHARS];
45    char searchbase[MAX_CHARS];
46    char htmlfile[MAX_CHARS];
47    int  ldap_port_num;
48    int  num_of_attrib;
49    int  debug; /* if zero, no debug text displayed */
50 } LDAP_INFO;
51
52 typedef struct {
53    char  title[40];
54 } ATTRIB_TITLE; 
55
56 /* function Prototypes */
57 void process_cfg(char *config, 
58                  LDAP_INFO *ldap_data,
59                  char *attribute_array[],
60                  ATTRIB_TITLE *disp_attrib);
61
62 int  strscn(char *istring, 
63             char *tstring);
64
65 void upcase_string(char *array, 
66                    char *uparray);
67
68 int  find_comma(char *array);
69
70 int find_colon(char *array);
71
72 void squeeze_blanks(char *array);
73
74 /* Pass in nothing and use the default config file, or
75  * pass in the config file to use */
76
77 main(int argc, char ** argv) {
78    LDAP         *ld;
79    LDAPMessage  *res, *e;
80    int          i, j, cl, x, how_many;
81    char         *a, *dn, *value;
82    BerElement   *ptr;
83    char         **vals;
84    char         *read_attrs[MAX_ATTRIB]; /* up to MAX_ATTRIB attribs returned */
85    struct       berval **bvals;
86    char         attrs_name[MAX_CHARS];
87    char         config_file[MAX_CHARS];
88    char         temp[MAX_CHARS];
89    char         passed_in[MAX_CHARS];
90    LDAP_INFO    ldap_data;
91    ATTRIB_TITLE attribute[MAX_ATTRIB];
92    time_t       now;
93    FILE         *logfp;
94    
95    
96    /* html initialization */
97    printf("Content-type: text/html\n\n");
98    printf("<html>\n<head>\n<title>Web Ldap Results</title>\n");
99    printf("</head>\n");
100    printf("<body text=\"#000000\" bgcolor=\"#FFFFFF\">\n");
101    printf("<h2>Web LDAP Results</h2>\n");
102    
103    /* initialize ldap_data structure */
104    memset(ldap_data.servername,0,MAX_CHARS);
105    memset(ldap_data.query,0,MAX_CHARS);
106    memset(ldap_data.searchbase,0,MAX_CHARS);
107    memset(ldap_data.htmlfile,0,MAX_CHARS);
108    ldap_data.ldap_port_num  = 0;
109    ldap_data.num_of_attrib  = 0;
110    ldap_data.debug          = 0;
111    
112    memset(passed_in,0,MAX_CHARS);
113
114    if (argc > 1) { /* interactive mode */
115       
116       /* To use in this fashion when run from a Unix command line:
117        * 
118        * > web_ldap DEF "cn=j*moller"
119        * > web_ldap DEF cn=jens moller
120        *
121        * NOTE: The quotes are required if a special
122        * character is a part of the LDAP request such
123        * as the asterix (*) in the above example.
124        */
125       
126       /* Parameters passed in are
127        * 
128        * argv[0] = Program Name     (argc =  1)
129        * argv[1] = Config File Name (argc =  2)
130        * argv[2] = Ldap Request     (argc => 3)
131        */
132       
133       /* do we use a different config file ? */
134       strcpy(config_file, CONFIG);
135    
136       if (argc == 2){
137          if ((strcmp(argv[1],"DEF")) == 0) {
138             strcpy(config_file, CONFIG);
139          }
140          else {
141             strcpy(config_file, argv[1]);
142          }
143       }
144    
145       /* is there an LDAP request?   
146        * if so, it may take up to 3 argv[x] values */
147       
148       if (argc >= 3) {
149          if (argc == 3) {
150             strcpy(temp, argv[2]);
151          }
152          
153          if (argc == 4) {
154             strcpy(temp, argv[2]);
155             strcat(temp, " ");
156             strcat(temp, argv[3]);
157          }
158          
159          if (argc == 5) {
160             strcpy(temp, argv[2]);
161             strcat(temp, " ");
162             strcat(temp, argv[3]);
163             strcat(temp, " ");
164             strcat(temp, argv[4]);
165          }
166          
167          j = 0;
168          for (i=0; i<strlen(temp);i++) {
169             if ((temp[i] != '"') &&
170                 (temp[i] != '\\')){
171                passed_in[j] = temp[i];
172                j++;
173             }
174          }
175       }
176    }
177    else { /* Non Interactive Mode - read from a form */
178       if (strcompare(getenv("REQUEST_METHOD"),"POST"))
179         {
180            printf("<p>++ Error - This script should be referenced with a METHOD of POST.\n");
181            exit( EXIT_FAILURE );
182         }
183       if (strcompare(getenv("CONTENT_TYPE"),"application/x-www-form-urlencoded"))
184         {
185            printf("<p>++ Error - This script can only be used to decode form results. \n");
186            exit( EXIT_FAILURE );
187         }
188       cl = atoi(getenv("CONTENT_LENGTH"));
189       
190       for(x=0; cl && (!feof(stdin));x++)
191         {
192            entries[x].val = fmakeword(stdin,'&',&cl);
193            plustospace(entries[x].val);
194            unescape_url(entries[x].val);
195            entries[x].name = makeword(entries[x].val,'=');
196            how_many = x; /* keep track of how many we got */
197            
198 #ifdef DEBUG_TEXT
199            printf("entries[%d].name=%s - ",x,entries[x].name);
200            printf("entries[%d].val =%s<br>\n",x,entries[x].val);
201 #endif
202         }
203       
204       entries[x].name = NULL;    /* entry after last valid one */
205       entries[x].val = NULL;     /* is set to NULL */
206       
207       if(!getvalue(entries, "FORM", &value))
208         {
209            printf("%s%s%s", "This script expected a 'FORM' value returned ",
210                   "and did not get one.  Make sure the HTML used for this ",
211                   "script is correct.");
212            exit( EXIT_FAILURE );
213         } 
214       
215       /* Looking for:
216        * LDAP_REQUEST - actual LDAP request, ie 'cn=j*moller'
217        * CONFIG       = Configuration file
218        */
219
220       strcpy(config_file, CONFIG);
221       
222       if(getvalue(entries, "LDAP_REQUEST", &value)) {
223                 strcpy(passed_in,value);
224       }
225       
226       if(getvalue(entries, "CONFIG", &value)) {
227          if ((strcmp("DEF",value)) == 0) {
228             strcpy(config_file, CONFIG);
229          }
230          else {
231             strcpy(config_file, value);
232          }
233       }
234       
235    }
236    
237    /* zero out the attribute pointers/data area */
238    for (i = 0; i < MAX_ATTRIB; i++) {
239       read_attrs[i] = NULL;
240       memset(attribute[i].title,0,40);
241    } 
242    
243    /* read in the config file */
244    process_cfg(config_file, &ldap_data, read_attrs, attribute);
245    
246    if (passed_in[0] != 0) {
247       strcpy(ldap_data.query,passed_in);
248    }
249    
250    if (ldap_data.debug != 0) {
251       if ((logfp = fopen("web_ldap.log","w")) == 0) {
252          printf("<font color=red size=5>\n");
253          printf("<p>Unable to open requested log file: web_ldap.log<p>\n");
254          printf("</font>\n");
255       }
256       else { 
257          time(&now);
258          sprintf(temp,"==> web_ldap request made at: %s\n",ctime(&now));
259          fputs(temp,logfp);
260          if (argc > 1) {
261             sprintf(temp," Interactive Unix Command Line Request:\n\n");
262          }
263          else {
264             sprintf(temp," Browser/Form Request:\n\n");
265          }
266          fputs(temp,logfp);
267          sprintf(temp," Server Name: %s\n", ldap_data.servername);
268          fputs(temp,logfp);
269          sprintf(temp," Query: %s\n", ldap_data.query);
270          fputs(temp,logfp);
271          sprintf(temp," Passed In: %s\n", passed_in);
272          fputs(temp,logfp);
273          sprintf(temp," Searchbase: %s\n",ldap_data.searchbase);
274          fputs(temp,logfp);
275          if (ldap_data.htmlfile[0] != 0) {
276             sprintf(temp," HTML File: %s\n",ldap_data.htmlfile);
277          }
278          else {
279             sprintf(temp," HTML File: Non Provided - Use Default Processing\n");
280          }
281          fputs(temp,logfp);
282          sprintf(temp," LDAP Port: %d\n",ldap_data.ldap_port_num);
283          fputs(temp,logfp);
284          sprintf(temp," Number of Attributes: %d\n",ldap_data.num_of_attrib);
285          fputs(temp,logfp);
286          if (ldap_data.num_of_attrib > 0) {
287             for (i = 0; i < ldap_data.num_of_attrib; i++) {
288                sprintf(temp," - %s\n",read_attrs[i]);
289                fputs(temp,logfp);
290             }
291          }
292          
293          sprintf(temp,"\n==< Process Arguments: %d >==\n\n argv[0]: %s\n",
294                  argc, argv[0]);
295          fputs(temp,logfp);
296          if (argc >= 2) {
297            sprintf(temp," argv[1]: %s\n",argv[1]);
298             fputs(temp,logfp);
299          }
300          if (argc >= 3) {
301             sprintf(temp," argv[2]: %s\n",argv[2]);
302             fputs(temp,logfp);
303          }
304          if (argc >= 4) {
305             sprintf(temp," argv[3]: %s\n",argv[3]);
306             fputs(temp,logfp);
307          }
308          if (argc >= 5) {
309             sprintf(temp," argv[4]: %s\n",argv[4]);
310             fputs(temp,logfp);
311          }
312          fflush(logfp);
313          fclose(logfp);
314       }
315    }
316    
317    if (ldap_data.debug != 0) {
318       if ((logfp = fopen("web_ldap.log","a")) == 0) {
319       }
320       else {
321          time(&now);
322          sprintf(temp,"\n==< Results >==\n\n");
323          fputs(temp,logfp);
324          sprintf(temp,"** performing ldap_init at %s\n", ctime(&now));
325          fputs(temp,logfp);
326          fflush(logfp);
327          fclose(logfp);
328       }
329    }
330    if ( (ld = ldap_init(ldap_data.servername, ldap_data.ldap_port_num) ) == NULL)
331      {
332         printf("<font color=red><b>ldap_init error</b></font>\n");
333         if (ldap_data.debug != 0) {
334            if ((logfp = fopen("web_ldap.log","a")) == 0) {
335            }
336            else {
337               sprintf(temp,"++ ldap_init error\n");
338               fputs(temp,logfp);
339               fflush(logfp);
340               fclose(logfp);
341            }
342         }
343         printf("</body>\n</html>\n");
344         exit( EXIT_FAILURE );
345      }
346    
347    /*authenticate as nobody */
348    if (ldap_data.debug != 0) {
349       if ((logfp = fopen("web_ldap.log","a")) == 0) {
350       }
351       else {
352          time(&now);
353          sprintf(temp,"** performing ldap_bind_s at %s\n",ctime(&now));
354          fputs(temp,logfp);
355          fflush(logfp);
356          fclose(logfp);
357       }   
358    }   
359    if(ldap_bind_s(ld, "", "", LDAP_AUTH_SIMPLE) != 0)
360      {
361         printf("<font color=red><b>");
362         ldap_perror (ld, "ldap_simple_bind_s");
363         printf("</b></font>\n");
364
365         if (ldap_data.debug != 0) {
366            if ((logfp = fopen("web_ldap.log","a")) == 0) {
367            }
368            else {
369               sprintf(temp,"++ ldap_bind_s error\n");
370               fputs(temp,logfp);
371               fflush(logfp);
372               fclose(logfp);
373            }
374         }
375         printf("</body>\n</html>\n");
376         exit( EXIT_FAILURE );
377      }
378    
379    printf("<b>Directory Lookup Results</b>\n<pre>\n");
380    printf("<hr><p>\n<pre>\n");
381    
382    /* Get data */
383    if (ldap_data.debug != 0) {
384       if ((logfp = fopen("web_ldap.log","a")) == 0) {
385       }
386       else {
387          time(&now);
388          sprintf(temp,"** performing ldap_search_s at %s\n",ctime(&now));
389          fputs(temp,logfp);
390          fflush(logfp);
391          fclose(logfp);
392       }
393    }
394    if(ldap_search_s(ld, ldap_data.searchbase, LDAP_SCOPE_SUBTREE,
395                     ldap_data.query, read_attrs, 0, &res)
396       != LDAP_SUCCESS)
397      {
398         ldap_perror(ld, "ldap_search_s");
399      }
400    
401    for (e=ldap_first_entry(ld, res); e != NULL; e=ldap_next_entry(ld, e))
402      {
403         dn = ldap_get_dn(ld, e);
404         
405         if (ldap_data.debug != 0) {     
406            if ((logfp = fopen("web_ldap.log","a")) == 0) {
407            }
408            else {
409               sprintf(temp," dn=%s\n", dn);
410               fputs(temp,logfp);
411               fflush(logfp);
412               fclose(logfp);
413            }
414         }
415         
416         /*print each attribute */
417         for (a = ldap_first_attribute(ld, e, &ptr);
418              a != NULL;
419              a = ldap_next_attribute(ld, e, ptr) )
420           {
421              strcpy(attrs_name, a);
422              /* print attribute name */
423              printf("%s: ", attrs_name);
424              
425              /*print each value */
426              
427              vals = ldap_get_values(ld, e, a);
428              
429              for(i=0; vals[i] != NULL; i++)
430                /* print value of attribute */
431                printf("%s\n", vals[i],strlen(vals[i]));
432            
433              ldap_value_free(vals);
434           } /*end for*/
435         free(a);
436         free(dn);
437         printf("<p>\n");
438      }
439    /*free the search results */
440    ldap_msgfree (res);
441    
442    printf("</pre>\n");
443
444    ldap_unbind(ld);
445    
446    if (ldap_data.debug != 0) {
447       if ((logfp = fopen("web_ldap.log","a")) == 0) {
448       }
449       else {
450          time(&now);
451          sprintf(temp,"\nFinished gathering results at %s\n",ctime(&now));
452          fputs(temp,logfp);
453          sprintf(temp,"==< Done >==\n");
454          fputs(temp,logfp);
455          fflush(logfp);
456          fclose(logfp);
457       }
458    }
459    printf("</body>\n</html>\n");
460 }
461    
462 /* Process the user passed in configuration file */
463 void process_cfg(char *config, 
464                  LDAP_INFO *ldap_data,
465                  char *attribute_array[],
466                  ATTRIB_TITLE *disp_attrib) {
467    
468    char   file_data[1024];
469    char   upfile_data[1024];
470    char   temp[1024];
471    int    lcomma, lcolon, attrib_pos;
472    FILE * fp;
473    
474    strcpy(ldap_data->servername,SERVER);
475    ldap_data->ldap_port_num = LDAP_PORT;
476    strcpy(ldap_data->query,"cn=jens*moller");
477    
478    /* config file needs to be in the cgi-bin directory */
479    if ((fp = fopen(config,"r")) == 0) {
480       return;
481    }
482    
483    attrib_pos = 0;
484    
485    for (;;) { /* read until eof */
486       fgets (file_data,1024,fp);
487       if (feof(fp)) break;
488       if (file_data[0] != '#') { /* skip commented lines */
489          upcase_string(file_data,upfile_data);
490
491          /* get the server specific data */
492          if (strscn(upfile_data,"SERVER:") == 0) {
493             lcolon = find_colon(file_data) + 1;
494             lcomma = find_comma(file_data);
495             if (lcomma > 0) {
496                memset(ldap_data->servername,0,MAX_CHARS);
497                strncpy(ldap_data->servername,&file_data[lcolon],
498                        lcomma - lcolon);
499                ldap_data->ldap_port_num = atoi(&file_data[lcomma + 1]);
500             }
501             else {
502                strcpy(ldap_data->servername,&file_data[lcolon]);
503             }
504             squeeze_blanks(ldap_data->servername);
505          }
506          else if (strscn(upfile_data,"SEARCHBASE:") == 0) {
507             lcolon = find_colon(file_data) + 1;
508             strcpy(ldap_data->searchbase,&file_data[lcolon]);
509             squeeze_blanks(ldap_data->searchbase);
510          }
511          else if (strscn(upfile_data,"HTMLFILE:") == 0) {
512             lcolon = find_colon(file_data) + 1;
513             strcpy(ldap_data->htmlfile,&file_data[lcolon]);
514          }
515          else if (strscn(upfile_data,"DEBUG:") == 0) {
516             lcolon = find_colon(file_data) + 1;
517             ldap_data->debug = atoi(&file_data[lcolon]);
518          }
519          
520          /* get the attribute list */
521          else if ((file_data[0] != ' ') && (file_data[0] != 0)) {
522             memset(temp,0,1024);
523             /* data appears as a comma delimited list, where:
524              * 
525              * attrib_name (char),display_length (int)
526              *
527              * (default length = 20 if display_length undefined)
528              * 
529              * is how each record is defined */
530             lcomma = find_comma(file_data);
531             if (lcomma < 0) {
532                strcpy(temp,file_data);
533                squeeze_blanks(temp);
534             }
535             else {
536                strncpy(temp,file_data,lcomma);
537                squeeze_blanks(temp);
538             }
539             attribute_array[attrib_pos] = malloc(strlen(temp));
540             strcpy(attribute_array[attrib_pos],temp);
541             attrib_pos++;
542             ldap_data->num_of_attrib = attrib_pos;
543          }
544       }
545    }
546 }
547
548 /* find character substring matches */
549 int strscn(char * istring, 
550            char * tstring) {
551    int  i, status, icmp, len;
552    status = -1;
553    len = (strlen(istring) + 1) - strlen(tstring);
554    if (len < 1) len = 1;
555    for (i=0;i<len ;i++) {
556       icmp = memcmp(&istring[i],tstring,strlen(tstring));
557       if (icmp == 0) {
558          status = i;
559          break;
560       }
561    }
562    return status;
563 }
564
565 /* convert the array to uparray, where uparray contains upper
566  * case characters */
567 void upcase_string(char *array, 
568                    char *uparray) {
569    int  i;
570    for (i=0; i < strlen(array); i++) {
571       uparray[i] = toupper((unsigned char) array[i]);
572       uparray[i + 1] = 0;
573    }
574    return;
575 }
576
577 /* return the position of the first comma - ',' - from within a string */
578 int find_comma(char *array){
579    int  i;
580    for (i = 0; i < strlen(array); i++) {
581       if (array[i] == ',') return(i);
582    }
583    return -1;
584 }
585
586 /* return the position of the first colon - '.' - from within a string */
587 int find_colon(char *array){
588    int  i;
589    for (i = 0; i < strlen(array); i++) {
590       if (array[i] == ':') return(i);
591    }
592    return -1;
593 }
594
595 /* Remove unneeded blanks from a character array. Don't leave 
596  * any at the end & throw away any newline characters  */
597 void squeeze_blanks(char *array){
598    int  i, pos, blank;
599    char temp[1024];
600    memset(temp,0,1024);
601    
602    pos   = 0; /* location within temp array */
603    blank = 0; /* # of blanks written in a row */
604  
605    for (i = 0; i < strlen(array); i++) {
606       if (array[i] != ' ') {
607          temp[pos] = array[i];
608          blank = 0;
609          pos++;
610       }
611       else if ((blank == 0) && 
612                (array[i] == ' ') &&
613                (pos != 0)) {
614          temp[pos] = array[i];
615          blank += 1;
616          pos++;
617       }
618    }
619    strcpy(array,temp);
620    if (array[strlen(array) - 1] <= ' ') 
621      array[strlen(array) - 1] = 0;
622 }