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