From b063f5e83b5eb499f1b7293dd096ae71f153d0cf Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Mon, 14 Dec 1998 23:10:02 +0000 Subject: [PATCH] Initial import of web_ldap written and contributed by Jens Moller . --- contrib/web_ldap/COPYRIGHT | 25 ++ contrib/web_ldap/Makefile | 28 ++ contrib/web_ldap/README | 17 + contrib/web_ldap/maint_form.h | 114 +++++ contrib/web_ldap/process_form.h | 32 ++ contrib/web_ldap/util.c | 540 +++++++++++++++++++++++ contrib/web_ldap/web_ldap.c | 612 +++++++++++++++++++++++++++ contrib/web_ldap/web_ldap.cfg | 27 ++ contrib/web_ldap/web_ldap.html | 50 +++ contrib/web_ldap/web_ldap.log.sample | 34 ++ contrib/web_ldap/web_ldap_usage.html | 355 ++++++++++++++++ contrib/web_ldap/web_ldap_usage.txt | 346 +++++++++++++++ 12 files changed, 2180 insertions(+) create mode 100644 contrib/web_ldap/COPYRIGHT create mode 100644 contrib/web_ldap/Makefile create mode 100644 contrib/web_ldap/README create mode 100644 contrib/web_ldap/maint_form.h create mode 100644 contrib/web_ldap/process_form.h create mode 100644 contrib/web_ldap/util.c create mode 100644 contrib/web_ldap/web_ldap.c create mode 100644 contrib/web_ldap/web_ldap.cfg create mode 100644 contrib/web_ldap/web_ldap.html create mode 100644 contrib/web_ldap/web_ldap.log.sample create mode 100644 contrib/web_ldap/web_ldap_usage.html create mode 100644 contrib/web_ldap/web_ldap_usage.txt diff --git a/contrib/web_ldap/COPYRIGHT b/contrib/web_ldap/COPYRIGHT new file mode 100644 index 0000000000..29a1eafa62 --- /dev/null +++ b/contrib/web_ldap/COPYRIGHT @@ -0,0 +1,25 @@ +Copyright 1998, Jens Moller, All rights reserved. +This software is not subject to any license of the COLOMAR +Group. + +Permission is granted to anyone to use this software for any purpose on +any computer system, and to alter it and redistribute it, subject +to the following restrictions: + +1. The author is not responsible for the consequences of use of this + software, no matter how awful, even if they arise from flaws in it. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. Since few users ever read sources, + credits should appear in the documentation. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. Since few users + ever read sources, credits should appear in the documentation. + +4. This notice may not be removed or altered. + +Redistribution and use in source and binary forms are permitted +without restriction or fee of any kind as long as this notice +is preserved. + diff --git a/contrib/web_ldap/Makefile b/contrib/web_ldap/Makefile new file mode 100644 index 0000000000..900c133a72 --- /dev/null +++ b/contrib/web_ldap/Makefile @@ -0,0 +1,28 @@ +# +# This file used under Irix (SGI) - please modify for your needs +# +CC = cc -signed + +#For Optimization +CFLAGS= -O2 +#For debugging +#CFLAGS= -g + +# +# Create Executables +# +web_ldap: web_ldap.o util.o + $(CC) -o web_ldap web_ldap.o util.o \ + libldap.a liblber.a + +# +# Create Objects +# +web_ldap.o: web_ldap.c + $(CC) -c web_ldap.c + +util.o: util.c + $(CC) -c util.c +# +# all done +# diff --git a/contrib/web_ldap/README b/contrib/web_ldap/README new file mode 100644 index 0000000000..6efe36bd8d --- /dev/null +++ b/contrib/web_ldap/README @@ -0,0 +1,17 @@ +The web_ldap package contains the following files: + + COPYRIGHT - Your rights to use this software + Makefile - Build file + README - This file + maint_form.h - HTML form processing + process_form.h - HTML form processing + util.c - HTML form processingg + web_ldap.c - Form/LDAP processing + web_ldap.cfg - configuration File + web_ldap.html - HTML Form + web_ldap.log.sample - Sample Log file + web_ldap_usage.txt - Instructions for use + web_ldap_usage.html - Instructions for use in HTML + +Please reveiw the web_ldap.txt or web_ldap_usage.html +file to understand how to utilize this software. diff --git a/contrib/web_ldap/maint_form.h b/contrib/web_ldap/maint_form.h new file mode 100644 index 0000000000..525783be0c --- /dev/null +++ b/contrib/web_ldap/maint_form.h @@ -0,0 +1,114 @@ +/* maint_form.h */ + +#ifndef __MAINT_FORM_H +#define __MAINT_FORM_H + +#define max number of passed fields. +#define MAX_ENTRIES 400 /* way bigger than needed. */ + +/* define the maximum length of a single config line */ +#define MAX_LINE_LEN 256 + +typedef struct { + char *name; + char *val; +} entry; + +/* prototypes */ +char *makeword(char *line, + char stop); + +char *fmakeword(FILE *f, + char stop, + int *len); + +char x2c(char *what); + +void unescape_url(char *url); + +void plustospace(char *str); + +int strcompare(char* a, + char* b); + +int getvalue(entry* list, + char* key, + char** value); + +int append_to_list(entry* list, + char* key, + char* value); + +void remove_leading_blanks(char* str); + +void remove_trailing_blanks(char* str); + +void pad_with_char(char* buffer, + int length, + char padchar); + +char* lower_case_string(char* inputbuf); + +char* upper_case_string(char* inputbuf); + +void strip_CR(char* buffer); + +void show_form_data(entry* entries); + +void display_html_text(char* filename); + +long unformat_cost(char* cost); + +int get_line(FILE* file, + char* returned_line); + +void print_header(char* title); + +void maint_trailer(); + +void maint_header(char* name); + +void maint_update_form(entry* list, + char* maint_filename, + char* DatabaseName); + +/* +int draw_form_fields(char* maint_filename, + CGIDB_REC* cgidb_rec); +*/ +void maint_remove_form(entry* list, + char* DatabaseName); + +void maint_add_form(entry* list, + char* maint_filename, + char* DatabaseName); + +/* +char* get_field_data(CGIDB_REC* cgidb_rec, + char* data, + char* buffer); +*/ +void maint_dump_db(entry* list, + char* maint_filename, + char* DatabaseName); +/* +void display_dump_entry(CGIDB_REC* cgidb_rec, + int cols, + char* item1, + char* item2, + char* item3, + char* item4); +*/ +void maint_upload_photo(char* MFileName); + +void maint_remove_photo(entry* list, + char* MFileName); +/* +int copy_data_to_db_field(CGIDB_REC* cgidb_rec, + char* field, + char* fieldmaxlength, + char* data); +*/ +#endif + +/* end file 'maint_form.h' */ diff --git a/contrib/web_ldap/process_form.h b/contrib/web_ldap/process_form.h new file mode 100644 index 0000000000..eeaabcc02f --- /dev/null +++ b/contrib/web_ldap/process_form.h @@ -0,0 +1,32 @@ +/* process_form.h */ + +#ifndef __PROCESS_FORM_H +#define __PROCESS_FORM_H + +#define MAX_ENTRIES 10000 + +typedef struct { + char *name; + char *val; +} entry; + +char *makeword(char *line, char stop); +char *fmakeword(FILE *f, char stop, int *len); +char x2c(char *what); +void unescape_url(char *url); +void plustospace(char *str); + +int strcompare(char* a, char* b); +int getvalue(entry* list, char* key, char** value); +void remove_leading_blanks(char* str); +void remove_trailing_blanks(char* str); +void pad_with_char(char* buffer, int length, char padchar); +char* lower_case_string(char* inputbuf); +char* upper_case_string(char* inputbuf); +void strip_CR(char* buffer); +void show_form_data(entry* entries); +void display_html_text(char* filename); +long unformat_cost(char* cost); +#endif + +/* end file 'process_form.h' */ diff --git a/contrib/web_ldap/util.c b/contrib/web_ldap/util.c new file mode 100644 index 0000000000..f120efbba7 --- /dev/null +++ b/contrib/web_ldap/util.c @@ -0,0 +1,540 @@ +/* util.c + * + * This code module originates from NCSA + * See: http://hoohoo.ncsa.uiuc.edu/cgi/ + * and: ftp://ftp.ncsa.uiuc.edu/Web/httpd/Unix/ncsa_httpd/cgi/cgi-src/ + * + * Most of the above listed programs were combined into a single + * file (this one) - everything here is public domain and free for + * use in any form.. + * + * Corrections made for SGI systems (Irix) and + * time/date functions added - R. Scott Guthrie + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "process_form.h" + +/*--------------*/ +/* strcompare */ +/*--------------*/ +/* This fixes the SGI strcmp function which aborts when passed + * a NULL in place of a NULL TERMINATED STRING. + * (The code that depended on it was ported from SUN which considered + * a NULL to be a NULL terminated string. The standard says strcmp + * action is undefined when passed a NULL. SGI abends.) + */ +int strcompare(char* a, char* b) +{ + if(a && b) + return(strcmp(a, b)); /* neither char* is NULL */ + return(1); /* different if either (or both) char* are NULL */ +} + + +/*------------*/ +/* getvalue */ +/*------------*/ +/* put a pointer to the value in 'value' for the key specified. + */ +int getvalue(entry* list, char* key, char** value) +{ + int index = 0; + + *value = NULL; /* initialize value to NULL */ + + while(list[index].name) + { + if(strcmp(list[index].name, key) == 0) + { + *value = list[index].val; + return(1); /* success */ + } + index++; + } + return(0); /* no key value found in list */ +} + + +/*------------------*/ +/* append_to_list */ +/*------------------*/ +/* Append name/value pair to end of list */ +int append_to_list(entry* list, char* key, char* value) +{ + int index = 0; + char* newname; + char* newvalue; + + /* go to end of list */ + while(list[index].name) + index++; + + if(index > MAX_ENTRIES) + return(0); /* out of room */ + + newname = (char *) malloc(sizeof(char) * (strlen(key) + 1)); + strcpy(newname, key); + list[index].name = newname; + + newvalue = (char *) malloc(sizeof(char) * (strlen(value) + 1)); + strcpy(newvalue, value); + list[index].val = newvalue; + + /* put new nulls at end. */ + index++; + list[index].name = NULL; + list[index].val = NULL; + return(1); /* success */ +} + +/*----------------------*/ +/* remove_table_entry */ +/*----------------------*/ +/* replaces table entry 'name' name field with '~' */ +int remove_table_entry(entry* list, char* name) +{ + int index = 0; + + /* search table for matching name entry */ + while(1) /* FOREVER - breaks out with return */ + { + if(list[index].name == NULL) + return(0); /* not in list */ + + if(strcmp(list[index].name, name) == 0) + { + /* found match. remove name */ + free(list[index].name); + + /* allocate space for deleted name */ + if((list[index].name = (char*)malloc(2 * sizeof(char))) == NULL) + return(0); /* malloc error */ + else + strcpy(list[index].name, "~"); /* DELETE INDICATOR */ + return(1); /* replacement successful */ + } + index++; /* try next name */ + } + return(0); /* cannot get here */ +} /* remove_table_entry */ + + +/*------------*/ +/* makeword */ +/*------------*/ +char* makeword(char *line, char stop) +{ + int x = 0,y; + char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1)); + + for(x=0;((line[x]) && (line[x] != stop));x++) + word[x] = line[x]; + + word[x] = '\0'; + if(line[x]) ++x; + y=0; + + while(line[y++] = line[x++]); + return word; +} + + +/*-------------*/ +/* fmakeword */ +/*-------------*/ +char* fmakeword(FILE *f, char stop, int *cl) +{ + int wsize; + char *word; + int ll; + + wsize = 102400; + ll=0; + word = (char *) malloc(sizeof(char) * (wsize + 1)); + + while(1) + { + word[ll] = (char)fgetc(f); + if(ll==wsize) + { + word[ll+1] = '\0'; + wsize+=102400; + word = (char *)realloc(word,sizeof(char)*(wsize+1)); + } + --(*cl); + + if((word[ll] == stop) || (feof(f)) || (!(*cl))) + { + if(word[ll] != stop) ll++; + word[ll] = '\0'; + return word; + } + ++ll; + } + return(NULL); +} + + +/*-------*/ +/* x2c */ +/*-------*/ +char x2c(char *what) +{ + register char digit; + + digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0')); + digit *= 16; + digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0')); + return(digit); +} + +/*----------------*/ +/* unescape_url */ +/*----------------*/ +void unescape_url(char *url) +{ + register int x,y; + + for(x=0,y=0;url[y];++x,++y) + { + if((url[x] = url[y]) == '%') + { + url[x] = x2c(&url[y+1]); + y+=2; + } + } + url[x] = '\0'; +} + + +/*---------------*/ +/* plustospace */ +/*---------------*/ +void plustospace(char *str) +{ + register int x; + + for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' '; +} + + +/*-------------------------*/ +/* remove_leading_blanks */ +/*-------------------------*/ +void remove_leading_blanks(char* str) +{ + int i; + while(str[0] == ' ') + { + i = 1; + do + { + str[i-1] = str[i]; + } while(str[i++]); + } +} /* end 'remove_leading_blanks()' */ + + +/*-------------------------*/ +/* remove_trailing_blanks */ +/*-------------------------*/ +void remove_trailing_blanks(char* str) +{ + while(str[strlen(str) - 1] == ' ') + str[strlen(str) - 1] = '\0'; +} /* end 'remove_trailing_blanks()' */ + + +/*-----------------*/ +/* pad_with_char */ +/*-----------------*/ +void pad_with_char(char* buffer, int length, char padchar) +{ + /* if the 'buffer' is >= then 'length', return. + * Pad the 'buffer' with 'padchar' until = 'length' + */ + int pos; + while((pos = strlen(buffer)) < length) + { + buffer[pos] = padchar; + buffer[pos+1] = '\0'; + } +} /* end pad_with_char */ + + +/*---------------------*/ +/* lower_case_string */ +/*---------------------*/ +char* lower_case_string(char* inputbuf) +{ + int pos = 0; + + while(inputbuf[pos]) + { + inputbuf[pos] = (char)tolower(inputbuf[pos]); + pos++; + } + return(inputbuf); +} /* lower_case_string */ + + +/*---------------------*/ +/* upper_case_string */ +/*---------------------*/ +char* upper_case_string(char* inputbuf) +{ + int pos = 0; + + while(inputbuf[pos]) + { + inputbuf[pos] = (char)toupper(inputbuf[pos]); + pos++; + } + return(inputbuf); +} /* upper_case_string */ + + +/*------------*/ +/* strip_CR */ +/*------------*/ +void strip_CR(char* buffer) +{ + char* bufferptr; + char* newptr; + + bufferptr = buffer; + newptr = buffer; + + while(*bufferptr) + { + if(*bufferptr != '\r') + { + *newptr = *bufferptr; + newptr++; + } + bufferptr++; + } + *newptr = '\0'; + + return; +} + +/*------------------*/ +/* show_form_data */ +/*------------------*/ +/* THIS ROUTINE IS USED FOR DEBUGGING and will not be called in production */ +void show_form_data(entry* entries) +{ + int x = 0; + + printf("

Form Data

"); + printf("The following Name Value pairs currently exist:

%c",10); + printf("

    %c",10);
    +
    +  while(entries[x].name)
    +  {
    +    printf("
  • %s = [%s]%c",entries[x].name, + entries[x].val,10); + x++; + } + printf("
%c",10); +} + +/*------------------------*/ +/* maint_show_form_data */ +/*------------------------*/ +/* THIS ROUTINE IS USED FOR DEBUGGING and will not be called in production */ +void maint_show_form_data(entry* entries) +{ + int x = 0; + + printf("Content-type: text/html\n\n"); + printf("

Form Data

"); + printf("The following Name Value pairs currently exist:

%c",10); + printf("

    %c",10);
    +
    +  while(entries[x].name)
    +  {
    +    printf("
  • %s = [%s]%c",entries[x].name, + entries[x].val,10); + x++; + } + printf("
%c",10); +} + +/*---------------------*/ +/* display_html_text */ +/*---------------------*/ +/* display the text found in the indicated file */ +void display_html_text(char* filename) +{ + FILE *fp; + char buffer[256]; + + if((fp = fopen(filename, "r")) == NULL) + { + printf("%s%s%s", + "

(OOPS... We are unable to open file ", + filename, + " for reading)

\n"); + } + while(fgets(buffer, 256, fp) != NULL) + { + if(buffer[strlen(buffer) - 1] == '\n') + buffer[strlen(buffer) - 1] = '\0'; + printf("%s\n", buffer); + } + fclose(fp); + return ; +} /* display_html_text */ + + +/*-----------------*/ +/* unformat_cost */ +/*-----------------*/ +/* this routine converts a string value and + * converts it to an integer. + */ +long unformat_cost(char* cost) +{ + char buf[100]; + int buf_siz = 0; + + char* spos = cost; + char* dpos = buf; + + /* Make sure a string was passed */ + if(!spos) + return(0L); + + /* while in the string */ + while(*spos) + { + if(*spos == '.') + break; + if(isdigit(*spos)) + *dpos++ = *spos; + spos++; + if(buf_siz++ == 98) /* make sure we don't overrun buf */ + break; + } + *spos = '\n'; + return(atol(buf)); +} + +/*---------------*/ +/* digits_only */ +/*---------------*/ +int digits_only(char* str) +{ + char* pos; + + pos = str; + while(*pos) + { + if(!isdigit(*pos)) + return(0); /* non-digit found */ + pos++; + } + return(1); +} + +/*-------------*/ +/* util_year */ +/*-------------*/ +/* return current year -> 0 thru 99 */ +int util_year() +{ + time_t t; + struct tm *tptr; + int ret_val; + time(&t); + tptr = localtime(&t); + ret_val = tptr->tm_year; + return(ret_val); +} + +/*--------------*/ +/* util_month */ +/*--------------*/ +/* return Month of current year -> 1 thru 12 */ +int util_month() +{ + time_t t; + struct tm *tptr; + int ret_val; + time(&t); + tptr = localtime(&t); + ret_val = tptr->tm_mon; + return(ret_val + 1); +} + +/*------------*/ +/* util_day */ +/*------------*/ +/* return day of Month -> 1 thru 31 */ +int util_day() +{ + time_t t; + struct tm *tptr; + int ret_val; + time(&t); + tptr = localtime(&t); + ret_val = tptr->tm_mday; + return(ret_val); +} + +/*-------------*/ +/* util_hour */ +/*-------------*/ +/* return hour of day -> 0 thru 23 */ +int util_hour() +{ + time_t t; + struct tm *tptr; + int ret_val; + time(&t); + tptr = localtime(&t); + ret_val = tptr->tm_hour; + return(ret_val); +} + +/*---------------*/ +/* util_minute */ +/*---------------*/ +/* return minute of day -> 0 thru 59 */ +int util_minute() +{ + time_t t; + struct tm *tptr; + int ret_val; + time(&t); + tptr = localtime(&t); + ret_val = tptr->tm_min; + return(ret_val); +} + +/*---------------*/ +/* util_second */ +/*---------------*/ +/* return second of day -> 0 thru 59 */ +int util_second() +{ + time_t t; + struct tm *tptr; + int ret_val; + time(&t); + tptr = localtime(&t); + ret_val = tptr->tm_sec; + return(ret_val); +} + +/* end file 'util.c' */ diff --git a/contrib/web_ldap/web_ldap.c b/contrib/web_ldap/web_ldap.c new file mode 100644 index 0000000000..f08cd6b9e0 --- /dev/null +++ b/contrib/web_ldap/web_ldap.c @@ -0,0 +1,612 @@ +/* web_ldap.c + * Form Processing Web application that returns html based + * LDAP data with definitions from a configuration file. + * + * Jens Moller - Dec 11, 1998 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "maint_form.h" /* for HTML Form manipulations */ + +/* default values */ +#define LDAP_PORT 389 +#define SERVER "ldap.bigfoot.com" +#define CONFIG "web_ldap.cfg" + +#define MAX_ATTRIB 100 +#define MAX_CHARS 256 +#define version "v 1.1" + +entry entries[MAX_ENTRIES]; + +typedef struct { + char servername[MAX_CHARS]; + char query[MAX_CHARS]; + char searchbase[MAX_CHARS]; + char htmlfile[MAX_CHARS]; + int ldap_port_num; + int num_of_attrib; + int debug; /* if zero, no debug text displayed */ +} LDAP_INFO; + +typedef struct { + char title[40]; +} ATTRIB_TITLE; + +/* function Prototypes */ +void process_cfg(char *config, + LDAP_INFO *ldap_data, + char *attribute_array[], + ATTRIB_TITLE *disp_attrib); + +int strscn(char *istring, + char *tstring); + +void upcase_string(char *array, + char *uparray); + +int find_comma(char *array); + +int find_colon(char *array); + +void squeeze_blanks(char *array); + +/* Pass in nothing and use the default config file, or + * pass in the config file to use */ + +main(int argc, char ** argv) { + LDAP *ld; + LDAPMessage *res, *e; + int i, j, cl, x, how_many; + char *a, *dn, *value; + BerElement *ptr; + char **vals; + char *read_attrs[MAX_ATTRIB]; /* up to MAX_ATTRIB attribs returned */ + struct berval **bvals; + char attrs_name[MAX_CHARS]; + char config_file[MAX_CHARS]; + char temp[MAX_CHARS]; + char passed_in[MAX_CHARS]; + LDAP_INFO ldap_data; + ATTRIB_TITLE attribute[MAX_ATTRIB]; + time_t now; + FILE *logfp; + + + /* html initialization */ + printf("Content-type: text/html\n\n"); + printf("\n\nWeb Ldap Results\n"); + printf("\n"); + printf("\n"); + printf("

Web LDAP Results

\n"); + + /* initialize ldap_data structure */ + memset(ldap_data.servername,0,MAX_CHARS); + memset(ldap_data.query,0,MAX_CHARS); + memset(ldap_data.searchbase,0,MAX_CHARS); + memset(ldap_data.htmlfile,0,MAX_CHARS); + ldap_data.ldap_port_num = 0; + ldap_data.num_of_attrib = 0; + ldap_data.debug = 0; + + memset(passed_in,0,MAX_CHARS); + + if (argc > 1) { /* interactive mode */ + + /* To use in this fashion when run from a Unix command line: + * + * > web_ldap DEF "cn=j*moller" + * > web_ldap DEF cn=jens moller + * + * NOTE: The quotes are required if a special + * character is a part of the LDAP request such + * as the asterix (*) in the above example. + */ + + /* Parameters passed in are + * + * argv[0] = Program Name (argc = 1) + * argv[1] = Config File Name (argc = 2) + * argv[2] = Ldap Request (argc => 3) + */ + + /* do we use a different config file ? */ + strcpy(config_file, CONFIG); + + if (argc == 2){ + if ((strcmp(argv[1],"DEF")) == 0) { + strcpy(config_file, CONFIG); + } + else { + strcpy(config_file, argv[1]); + } + } + + /* is there an LDAP request? + * if so, it may take up to 3 argv[x] values */ + + if (argc >= 3) { + if (argc == 3) { + strcpy(temp, argv[2]); + } + + if (argc == 4) { + strcpy(temp, argv[2]); + strcat(temp, " "); + strcat(temp, argv[3]); + } + + if (argc == 5) { + strcpy(temp, argv[2]); + strcat(temp, " "); + strcat(temp, argv[3]); + strcat(temp, " "); + strcat(temp, argv[4]); + } + + j = 0; + for (i=0; i++ Error - This script should be referenced with a METHOD of POST.\n"); + exit(1); + } + if (strcompare(getenv("CONTENT_TYPE"),"application/x-www-form-urlencoded")) + { + printf("

++ Error - This script can only be used to decode form results. \n"); + exit(1); + } + cl = atoi(getenv("CONTENT_LENGTH")); + + for(x=0; cl && (!feof(stdin));x++) + { + entries[x].val = fmakeword(stdin,'&',&cl); + plustospace(entries[x].val); + unescape_url(entries[x].val); + entries[x].name = makeword(entries[x].val,'='); + how_many = x; /* keep track of how many we got */ + +#ifdef DEBUG_TEXT + printf("entries[%d].name=%s - ",x,entries[x].name); + printf("entries[%d].val =%s
\n",x,entries[x].val); +#endif + } + + entries[x].name = NULL; /* entry after last valid one */ + entries[x].val = NULL; /* is set to NULL */ + + if(!getvalue(entries, "FORM", &value)) + { + printf("%s%s%s", "This script expected a 'FORM' value returned ", + "and did not get one. Make sure the HTML used for this ", + "script is correct."); + exit(1); + } + + /* Looking for: + * LDAP_REQUEST - actual LDAP request, ie 'cn=j*moller' + * CONFIG = Configuration file + */ + + strcpy(config_file, CONFIG); + + if(getvalue(entries, "LDAP_REQUEST", &value)) { + strcpy(passed_in,value); + } + + if(getvalue(entries, "CONFIG", &value)) { + if ((strcmp("DEF",value)) == 0) { + strcpy(config_file, CONFIG); + } + else { + strcpy(config_file, value); + } + } + + } + + /* zero out the attribute pointers/data area */ + for (i = 0; i < MAX_ATTRIB; i++) { + read_attrs[i] = NULL; + memset(attribute[i].title,0,40); + } + + /* read in the config file */ + process_cfg(config_file, &ldap_data, read_attrs, attribute); + + if (passed_in[0] != 0) { + strcpy(ldap_data.query,passed_in); + } + + if (ldap_data.debug != 0) { + if ((logfp = fopen("web_ldap.log","w")) == 0) { + printf("\n"); + printf("

Unable to open requested log file: web_ldap.log

\n"); + printf("\n"); + } + else { + time(&now); + sprintf(temp,"==> web_ldap request made at: %s\n",ctime(&now)); + fputs(temp,logfp); + if (argc > 1) { + sprintf(temp," Interactive Unix Command Line Request:\n\n"); + } + else { + sprintf(temp," Browser/Form Request:\n\n"); + } + fputs(temp,logfp); + sprintf(temp," Server Name: %s\n", ldap_data.servername); + fputs(temp,logfp); + sprintf(temp," Query: %s\n", ldap_data.query); + fputs(temp,logfp); + sprintf(temp," Passed In: %s\n", passed_in); + fputs(temp,logfp); + sprintf(temp," Searchbase: %s\n",ldap_data.searchbase); + fputs(temp,logfp); + if (ldap_data.htmlfile[0] != 0) { + sprintf(temp," HTML File: %s\n",ldap_data.htmlfile); + } + else { + sprintf(temp," HTML File: Non Provided - Use Default Processing\n"); + } + fputs(temp,logfp); + sprintf(temp," LDAP Port: %d\n",ldap_data.ldap_port_num); + fputs(temp,logfp); + sprintf(temp," Number of Attributes: %d\n",ldap_data.num_of_attrib); + fputs(temp,logfp); + if (ldap_data.num_of_attrib > 0) { + for (i = 0; i < ldap_data.num_of_attrib; i++) { + sprintf(temp," - %s\n",read_attrs[i]); + fputs(temp,logfp); + } + } + + sprintf(temp,"\n==< Process Arguments: %d >==\n\n argv[0]: %s\n", + argc, argv[0]); + fputs(temp,logfp); + if (argc >= 2) { + sprintf(temp," argv[1]: %s\n",argv[1]); + fputs(temp,logfp); + } + if (argc >= 3) { + sprintf(temp," argv[2]: %s\n",argv[2]); + fputs(temp,logfp); + } + if (argc >= 4) { + sprintf(temp," argv[3]: %s\n",argv[3]); + fputs(temp,logfp); + } + if (argc >= 5) { + sprintf(temp," argv[4]: %s\n",argv[4]); + fputs(temp,logfp); + } + fflush(logfp); + fclose(logfp); + } + } + + if (ldap_data.debug != 0) { + if ((logfp = fopen("web_ldap.log","a")) == 0) { + } + else { + time(&now); + sprintf(temp,"\n==< Results >==\n\n"); + fputs(temp,logfp); + sprintf(temp,"** performing ldap_open at %s\n", ctime(&now)); + fputs(temp,logfp); + fflush(logfp); + fclose(logfp); + } + } + if ( (ld = ldap_open(ldap_data.servername, ldap_data.ldap_port_num) ) == NULL) + { + printf("ldap_open error\n"); + if (ldap_data.debug != 0) { + if ((logfp = fopen("web_ldap.log","a")) == 0) { + } + else { + sprintf(temp,"++ ldap_open error\n"); + fputs(temp,logfp); + fflush(logfp); + fclose(logfp); + } + } + printf("\n\n"); + exit(1); + } + + /*authenticate as nobody */ + if (ldap_data.debug != 0) { + if ((logfp = fopen("web_ldap.log","a")) == 0) { + } + else { + time(&now); + sprintf(temp,"** performing ldap_bind_s at %s\n",ctime(&now)); + fputs(temp,logfp); + fflush(logfp); + fclose(logfp); + } + } + if(ldap_bind_s(ld, "", "", LDAP_AUTH_SIMPLE) != 0) + { + printf(""); + ldap_perror (ld, "ldap_simple_bind_s"); + printf("\n"); + + if (ldap_data.debug != 0) { + if ((logfp = fopen("web_ldap.log","a")) == 0) { + } + else { + sprintf(temp,"++ ldap_bind_s error\n"); + fputs(temp,logfp); + fflush(logfp); + fclose(logfp); + } + } + printf("\n\n"); + exit(1); + } + + printf("Directory Lookup Results\n

\n");
+   printf("

\n

\n");
+   
+   /* Get data */
+   if (ldap_data.debug != 0) {
+      if ((logfp = fopen("web_ldap.log","a")) == 0) {
+      }
+      else {
+	 time(&now);
+	 sprintf(temp,"** performing ldap_search_s at %s\n",ctime(&now));
+	 fputs(temp,logfp);
+	 fflush(logfp);
+	 fclose(logfp);
+      }
+   }
+   if(ldap_search_s(ld, ldap_data.searchbase, LDAP_SCOPE_SUBTREE,
+		    ldap_data.query, read_attrs, 0, &res)
+      != LDAP_SUCCESS)
+     {
+	ldap_perror(ld, "ldap_search_s");
+     }
+   
+   for (e=ldap_first_entry(ld, res); e != NULL; e=ldap_next_entry(ld, e))
+     {
+	dn = ldap_get_dn(ld, e);
+	
+	if (ldap_data.debug != 0) {	
+	   if ((logfp = fopen("web_ldap.log","a")) == 0) {
+	   }
+	   else {
+	      sprintf(temp," dn=%s\n", dn);
+	      fputs(temp,logfp);
+	      fflush(logfp);
+	      fclose(logfp);
+	   }
+	}
+	
+	/*print each attribute */
+	for (a = ldap_first_attribute(ld, e, &ptr);
+	     a != NULL;
+	     a = ldap_next_attribute(ld, e, ptr) )
+	  {
+	     strcpy(attrs_name, a);
+	     /* print attribute name */
+	     printf("%s: ", attrs_name);
+	     
+	     /*print each value */
+	     
+	     vals = ldap_get_values(ld, e, a);
+	     
+	     for(i=0; vals[i] != NULL; i++)
+	       /* print value of attribute */
+	       printf("%s\n", vals[i],strlen(vals[i]));
+	   
+	     ldap_value_free(vals);
+	  } /*end for*/
+	free(a);
+	free(dn);
+	printf("

\n"); + } + /*free the search results */ + ldap_msgfree (res); + + printf("

\n"); + + ldap_unbind(ld); + + if (ldap_data.debug != 0) { + if ((logfp = fopen("web_ldap.log","a")) == 0) { + } + else { + time(&now); + sprintf(temp,"\nFinished gathering results at %s\n",ctime(&now)); + fputs(temp,logfp); + sprintf(temp,"==< Done >==\n"); + fputs(temp,logfp); + fflush(logfp); + fclose(logfp); + } + } + printf("\n\n"); +} + +/* Process the user passed in configuration file */ +void process_cfg(char *config, + LDAP_INFO *ldap_data, + char *attribute_array[], + ATTRIB_TITLE *disp_attrib) { + + char file_data[1024]; + char upfile_data[1024]; + char temp[1024]; + int lcomma, lcolon, attrib_pos; + FILE * fp; + + strcpy(ldap_data->servername,SERVER); + ldap_data->ldap_port_num = LDAP_PORT; + strcpy(ldap_data->query,"cn=jens*moller"); + + /* config file needs to be in the cgi-bin directory */ + if ((fp = fopen(config,"r")) == 0) { + return; + } + + attrib_pos = 0; + + for (;;) { /* read until eof */ + fgets (file_data,1024,fp); + if (feof(fp)) break; + if (file_data[0] != '#') { /* skip commented lines */ + upcase_string(file_data,upfile_data); + + /* get the server specific data */ + if (strscn(upfile_data,"SERVER:") == 0) { + lcolon = find_colon(file_data) + 1; + lcomma = find_comma(file_data); + if (lcomma > 0) { + memset(ldap_data->servername,0,MAX_CHARS); + strncpy(ldap_data->servername,&file_data[lcolon], + lcomma - lcolon); + ldap_data->ldap_port_num = atoi(&file_data[lcomma + 1]); + } + else { + strcpy(ldap_data->servername,&file_data[lcolon]); + } + squeeze_blanks(ldap_data->servername); + } + else if (strscn(upfile_data,"SEARCHBASE:") == 0) { + lcolon = find_colon(file_data) + 1; + strcpy(ldap_data->searchbase,&file_data[lcolon]); + squeeze_blanks(ldap_data->searchbase); + } + else if (strscn(upfile_data,"HTMLFILE:") == 0) { + lcolon = find_colon(file_data) + 1; + strcpy(ldap_data->htmlfile,&file_data[lcolon]); + } + else if (strscn(upfile_data,"DEBUG:") == 0) { + lcolon = find_colon(file_data) + 1; + ldap_data->debug = atoi(&file_data[lcolon]); + } + + /* get the attribute list */ + else if ((file_data[0] != ' ') && (file_data[0] != 0)) { + memset(temp,0,1024); + /* data appears as a comma delimited list, where: + * + * attrib_name (char),display_length (int) + * + * (default length = 20 if display_length undefined) + * + * is how each record is defined */ + lcomma = find_comma(file_data); + if (lcomma < 0) { + strcpy(temp,file_data); + squeeze_blanks(temp); + } + else { + strncpy(temp,file_data,lcomma); + squeeze_blanks(temp); + } + attribute_array[attrib_pos] = malloc(strlen(temp)); + strcpy(attribute_array[attrib_pos],temp); + attrib_pos++; + ldap_data->num_of_attrib = attrib_pos; + } + } + } +} + +/* find character substring matches */ +int strscn(char * istring, + char * tstring) { + int i, status, icmp, len; + status = -1; + len = (strlen(istring) + 1) - strlen(tstring); + if (len < 1) len = 1; + for (i=0;i + +Web LDAP Access + + +

Web LDAP Access

+ +
+ +

+Please fill in the LDAP request you desire. You may use +wildcards (*) in this fashion: +

    +Common Name Examples

    +

  • cn=jens moller +
  • cn=*moller +
  • cn=j* moller +

    +Surname Examples

    +

  • sn=moller +
  • sn=*moller +
+

+You may specify a configuration file if you have created a +new one, otherwise, leave it set to "DEF". +


+ +
+ LDAP Request: 
+  
+  Config File: 
+
+ + + + +

+

+
+This is a freeware prototype application that includes the +source code. Please study it if you need to understand how it +works. It currenly only does simple LDAP Directory reads, however, +an interactive application has to start somewhere. +

+Authored by: Jens Moller. + + + + diff --git a/contrib/web_ldap/web_ldap.log.sample b/contrib/web_ldap/web_ldap.log.sample new file mode 100644 index 0000000000..b269c89b60 --- /dev/null +++ b/contrib/web_ldap/web_ldap.log.sample @@ -0,0 +1,34 @@ +==> web_ldap request made at: Thu Dec 10 12:17:02 1998 + + Interactive Unix Command Line Request: + + Server Name: ldap.bigfoot.com + Query: cn=jens*moller + Passed In: + Searchbase: + LDAP Port: 389 + Number of Attributes: 0 + +--- Process Arguments: 2 ---- + + argv[0]: web_ldap + argv[1]: DEF + +==< Results >== + +** performing ldap_open at Thu Dec 10 12:17:02 1998 + +** performing ldap_bind_s at Thu Dec 10 12:17:02 1998 + +** performing ldap_search_s at Thu Dec 10 12:17:02 1998 + + dn=cn="JENS MOLLER",mail=jmoller@con5097.cs.mci.com,c=US,o=con5097.cs.mci.com + dn=cn="JENS MOLLER",mail=100321.3153@compuserve.com,c=US,o=compuserve.com + dn=cn="jens moller",mail=jens1lund2moller@hotmail.com,c=US,o=hotmail.com + dn=cn="Jens Moller",mail=jensklethmoller@hotmail.com,c=US,o=hotmail.com + dn=cn="jens moller",mail=jamoller@hotmail.com,c=US,o=hotmail.com + dn=cn="Jens Mollerup",mail=jmollerup@aki.ku.dk,c=US,o=aki.ku.dk + +Finished gathering results at Thu Dec 10 12:17:02 1998 + +==< Done >== diff --git a/contrib/web_ldap/web_ldap_usage.html b/contrib/web_ldap/web_ldap_usage.html new file mode 100644 index 0000000000..202e9ff615 --- /dev/null +++ b/contrib/web_ldap/web_ldap_usage.html @@ -0,0 +1,355 @@ + +web_ldap_usage + + +

web_ldap V 1.1

+ +The files provided in the file set for 'web_ldap' +were developed under the GNU General Public License (GPL). +Under the GPL, the source code is freely-distributed and available +to the general public. There is no warranty on the software, +and it does not come with support, however, I would appreciate +it if you emailed me any bug-fixes you create +(jens@colomar.com). +

+All code here is generic Ansi C, allowing most Unix compilers +to generate the required object files and executable images. +It was tested against an Apache HTTPD server and uses no +special HTML functionality that does not appear within V 3.x +versions of Netscapes or Microsofts Web Browsers. The goal was +to create a starting point example to help people build +effective interactive HTML based LDAP clients. + +

Introduction:

+ +The 'web_ldap' package is a complete LDAP application that +provides a functional Web Server Based client. The intent +is to give you a working example that you can expand upon +for your own needs. It does not solve a specific problem +for you, rather it solves a general problem by giving +you a functional starting point from where to begin your +development efforts. It runs under Unix. +

+The application consists of a number of C programs, header +files, an HTML file with form entry, a configuration file +and a sample makefile. You will need the LDAP SDK for your +specific Unix System (both the UofM libraries and Netscape +libraries - which are also free - have been tested). +

+The tool allows You to specify that actions taken +be logged to a file. This provides you a method by which +you can build out larger applications and see what is happening. +

+The application can be run interactively (without use of +a Web Browser) but was intended for use as an HTML LDAP Web +page application. +

+One thing to consider when running a program of this nature +is that there are 2 totally different sets of environments +involved. The program is written assuming very little in +the way of file/directory organization. As such it looks for +files either in the directory it was run from, or where ever +you have configured your Web Server to look for things. +

+The C CGI program will attempt to open a default configuration +file called 'web_ldap.cfg'. If you set the debug mode on +in the configuration file, it will also attempt to create +a log file called 'web_ldap.log' in the same directory as +the 'web_ldap.cfg' files appears in. +

+The 2 environments are 'Interactive' and 'Web Server'. +

+When you execute the application from a command line such as: +

      
+     > web_ldap DEF cn=jens moller
+
+All actions take place in the same directory that the web_ldap +program resides in. Most people would typically build an +application of this nature in one of their own directorys and +this would give them Read/Write access to all of the files +associated with the program. Any file restrictions or capabilities +that you have will be enabled as part of your session. +

+This is quite different than when you ask a Web Server to +execute the program for you. The Web Server is typically +using the user 'nobody'. This is not you, its a separate +application user and it may not have access to the same +files that you have nor the same process capabilities. +

+When your program executes from a Web Browser, you will +see something like: +

+    http://my.system.com/cgi-bin/web_ldap
+    
+
+displayed by the Web Browser as the URL that its executing. +The Web Server is executing the program on your behalf. +File protections normally cause initial problems, possibly +because the Web Browser doesn't own the files or doesn't +have execute access. For your initial testing, please set these +files to full access - ie. 'chmod 777 web_ldap*' - You can +adjust the file protections once you get everything working. +If you get errors - start with this simple change. + +

Building the application:

+ +Requires Ansi C (your standard OS compiler or GCC should +work fine). +

+The make file contains: +

+web_ldap: web_ldap.o
+        $(CC) -o web_ldap web_ldap.o util.o \
+	libldap.a liblber.a
+		
+
+web_ldap.o: web_ldap.c
+        $(CC) -c web_ldap.c
+
+util.o: util.c
+        $(CC) -c util.c
+
+
+ +

Configuration:

+ +Its a very simple tool that allows you to make LDAP requests +to any existing LDAP Directory Server. By default, it +attempts to connect to 'ldap.bigfoot.com', which is a +commercial LDAP server on the Internet - usually available +from anywhere. +

+To specify a different LDAP server, you could either modify +the program to default elsewhere, or you could modify the +existing 'web_ldap.cfg' file, or create another one with +a different name. +

+NOTE: A '#' in the first column of any line +in the configuration file is considered a comment. + +

+The configuration file allows you specify: +

+  server:
+
+This is the servername. For example: +
+  server:ldap.bigfoot.com,389
+
+connects you up to port 389 on the ldap server 'ldap.bigfoot.com'. +You can specify one of your own servers here if you desire. +

+Next you will see: +

+  searchbase:
+
+This is where within a tree you want to start looking. For +'ldap.bigfoot.com', you would leave this blank and it will +look in all the trees. For many companies a specific tree +structure will be defined, and you will want to specify the +highest point in the tree structure that defines the area that +you are interested in. For example, if you have a tree that +starts at 'c=US', and branches at 'o=ABC, c=US' and +'o=XYZ, c=US', you could specify: +
+  searchbase:c=US
+
+and search both 'o=ABC, c=US' and 'o=XYZ, c=US', or +if you only wanted to search against 'o=ABC, c=US', +you could specify: +
+  searchbase:o=ABC, c=US
+
+If you want to turn on a simple Debug mode, you can specify any number +other than zero for 'debug:'. For example: +
+  debug:1
+
+turns on the Debug logging mode, and +
+  debug:0
+
+turns it off. Debug logging simply creates a file called +'web_ldap.log' in the same directory that the web_ldap +executable is located. It flushes everything after each +event, so if it gets stuck anywhere, you will be able +to see it. It also time-stamps most of the results, so you +can get an idea where things are running faster and/or +slower for different queries. +

+The remainder of the configuration file is where you list +the attributes that you are interested in displaying. +

+You could list parameters (up to 100) like: +

+  cn
+  givenname
+  sn
+
+and that is all it will return. If you don't specify +anything, it returns everything it finds. if you +specify an attribute that the directory has never +heard of (ie. its not a member of any object class +anyone has defined), that attribute will simply be +ignored. If you misspell an attribute name and wonder +why it never gets listed in the results - this might be +why. If you specify an attribute that some users have and +others don't, only ones with that attribute will list +a value for it. +

+Directory data can be multi-valued. This means that any +attribute could have multiple values. This application will +list all the values it finds for any given attribute. + + + + +If running this interactively (from a Unix shell prompt), +all the files can reside in any of your home directories. +I suggest that you test the application in your home +directory first. +

+If running this application from a Web Server, you need +to find out where the Web Server keeps its cgi applications +and where it keeps its html applications. This varies +from operating system to operating system and Web Server +to Web Server. +

+Once you have located the cgi-bin (or equivalent) directory, +put these 2 files there: +

+  web_ldap
+  web_ldap.cfg
+
+then make sure that these files are accessible to the Web +Server by executing the Unix shell command: +
+  > chmod 777 web_ldap*
+
+Now find the HTML source directory. Copy +
+  web_ldap.html
+
+to this directory. Make sure that this file is accessible to the Web +Server by executing the Unix shell command: +
+  > chmod 777 web_ldap*
+
+ +

Running the application:

+ +Test it in your own directory by entering: +
+  > web_ldap DEF
+
+This should connect to 'ldap.bigfoot.com' and try to find a number +of entries (it does when I try it). You will notice that it +outputs results in the form of an HTML file - this is what it +is supposed to do. If you leave out the 'DEF', you will get the +error: +
+<p>++ Error - This script should be referenced with a METHOD of POST.
+
+as a part of your result with no LDAP data returned. +

+Interactively, the program assumes that you will always pass it at least +the name of the Configuration file ('DEF' tells it to use the default +configuration file). If there is no configuration file, it still will +find 'ldap.bigfoot.com'. +

+Once you have it working there, try the version in the HTML directory. +To do so, enter your WEB Servers URL, the cgi-bin directory reference +and then the application name, all separated by slashes. For example, +if your Web Server URL is 'http://my.server.com', then you will want +to specify the URL: +

+  http://my.server.com/cgi-bin/web_ldap
+
+NOTE: You can only run cgi scripts out of a directory that the Web Server +allows. It is unlikely that you can execute Web Server CGI applications +from your own directory. +

+This will provide a simple Web Based form. It will have 2 user entry +fields. The first allows you to enter an LDAP request. The second +allows you to specify a configuration file (it defaults to 'DEF'). +

+Enter a simple LDAP request, such as the ones shown and see if you +get back a response. You should if connected to 'ldap.bigfoot.com'. + + +

Now that you have it working:

+ +Feel free to adapt this program to fit your needs. You will need +to have the 'dn' in order to do updates. It is recovered within +the program, so you can save it for use once you retrieve it +(it is listed in the web_ldap.log file of you enable debug mode). +

+This program does not update anything. The goal was to create a very +simple and expandable LDAP client and provide the complete source +code for doing it. To this goal, it is successful. From here +you should be able to experiment with the interfaces and create +new functionality to suit your given needs. +

+This was tested against the UofM V 3.3 LDAP Libraries and the Netscape +V 1.x and V 3.x SDK under both Irix 6.2 (Silicon Graphics) and +Solaris 2.6 (Sun). I don't have other hardware or OS's to test +against here. + + +

Usage Information:

+ +If you want to find out what attributes are being used, you can enable +the application to tell you all that it finds. Do this by simply +not defining any attributes within the configuration file. It will +list all the attributes it finds. You could create a special configuration +file specifically for this purpose. +

+If you are getting fatal errors from your Web Server when you attempt to +execute a command, please try the same command using interactive mode. Look +to see if the HTML being generated makes sense or not. If the HTML +looks good, run it again interactively and pipe the results to a file, then +attempt to submit the resulting file as the URL. If it works, it is +likely that the environment you run is different than the one the Web +server is using - Unix file protections frequently are a cause of these +problems. If you can't determine what is different, discuss the problem +with your Unix system administrator - is is likely a resource problem. +If you add code that causes problems, but you still get a result, try the +application in interactive mode and verify the HTML being generated. Any +additional HTML code you add may need to to have proper termination syntax +(tables are very touchy about this), and you may need to further enhance +your changes to compensate. +

+When creating new applications, please test your +results on both Netscape's Web Browser and Internet +Explorer. Nothing is more irritating to end users than getting different +results based on their Web Browser selection. +

+The Unix Command line will not allow you to pass some characters into +an application unless you surround the characters or command with quotes. +Some common examples of executing web_ldap interactively are: +

+  > web_ldap DEF "cn=j*moller"
+	
+  > web_ldap DEF cn=jens moller
+
+The command with the '*' in it requires quotes around it. Also note +that the application only allows the LDAP command to use up to 3 argv +values. This is as a limitation of the current parsing within the program +of argc/argv parameters. You could alter the program, or simply put +quotes around the LDAP request. Enable the debug mode within the +configuration file if you feel that the application is losing +arguments to see what its operating against. When operated by the Web Server, +and passing in FORM data - you won't have this limitation, and you don't +need quotes. +

+You can pass hidden fields from the Web Form into the web_ldap program. +An example is shown with the name of 'FORM' having a value of '300'. +You can create additional hidden fields, named anything you want them +to be, with any value you want. These can be used to define existing +options (such as which configuration file to use), or other options +that your modified web_ldap.c program may want to have passed to it. +

+


+Jens Moller - Jens@colomar.com - +COLOMAR Group diff --git a/contrib/web_ldap/web_ldap_usage.txt b/contrib/web_ldap/web_ldap_usage.txt new file mode 100644 index 0000000000..d002a58c54 --- /dev/null +++ b/contrib/web_ldap/web_ldap_usage.txt @@ -0,0 +1,346 @@ +web_ldap V 1.0 + +The files provided in the file set for 'web_ldap' +were developed under the GNU General Public License (GPL). +Under the GPL, the source code is freely-distributed and available +to the general public. There is no warranty on the software, +and it does not come with support, however, I would appreciate +it if you emailed me any bug-fixes you create (jens@colomar.com). + +All code here is generic Ansi C, allowing most Unix compilers +to generate the required object files and executable images. +It was tested against an Apache HTTPD server and uses no +special HTML functionality that does not appear within V 3.x +versions of Netscapes or Microsofts Web Browsers. The goal was +to create a starting point example to help people build +effective interactive HTML based LDAP clients. + +Introduction: + +The 'web_ldap' package is a complete LDAP application that +provides a functional Web Server Based client. The intent +is to give you a working example that you can expand upon +for your own needs. It does not solve a specific problem +for you, rather it solves a general problem by giving +you a functional starting point from where to begin your +development efforts. It runs under Unix. + +The application consists of a number of C programs, header +files, an HTML file with form entry, a configuration file +and a sample makefile. You will need the LDAP SDK for your +specific Unix System (both the UofM libraries and Netscape +libraries - which are also free - have been tested). + +The tool allows You to specify that actions taken +be logged to a file. This provides you a method by which +you can build out larger applications and see what is happening. + +The application can be run interactively (without use of +a Web Browser) but was intended for use as an HTML LDAP Web +page application. + +One thing to consider when running a program of this nature +is that there are 2 totally different sets of environments +involved. The program is written assuming very little in +the way of file/directory organization. As such it looks for +files either in the directory it was run from, or where ever +you have configured your Web Server to look for things. + +The C CGI program will attempt to open a default configuration +file called 'web_ldap.cfg'. If you set the debug mode on +in the configuration file, it will also attempt to create +a log file called 'web_ldap.log' in the same directory as +the 'web_ldap.cfg' files appears in. + +The 2 environments are 'Interactive' and 'Web Server'. + +When you execute the application from a command line such as: + + > web_ldap DEF cn=jens moller + +All actions take place in the same directory that the web_ldap +program resides in. Most people would typically build an +application of this nature in one of their own directorys and +this would give them Read/Write access to all of the files +associated with the program. Any file restrictions or capabilities +that you have will be enabled as part of your session. + +This is quite different than when you ask a Web Server to +execute the program for you. The Web Server is typically +using the user 'nobody'. This is not you, its a separate +application user and it may not have access to the same +files that you have nor the same process capabilities. + +When your program executes from a Web Browser, you will +see something like: + + http://my.system.com/cgi-bin/web_ldap + +displayed by the Web Browser as the URL that its executing. +The Web Server is executing the program on your behalf. +File protections normally cause initial problems, possibly +because the Web Browser doesn't own the files or doesn't +have execute access. For your initial testing, please set these +files to full access - ie. 'chmod 777 web_ldap*' - You can +adjust the file protections once you get everything working. +If you get errors - start with this simple change. + + +Building the application: + +Requires Ansi C (your standard OS compiler or GCC should +work fine). + +The make file contains: + +web_ldap: web_ldap.o + $(CC) -o web_ldap web_ldap.o util.o \ + libldap.a liblber.a + + +web_ldap.o: web_ldap.c + $(CC) -c web_ldap.c + +util.o: util.c + $(CC) -c util.c + + + +Configuration: + +Its a very simple tool that allows you to make LDAP requests +to any existing LDAP Directory Server. By default, it +attempts to connect to 'ldap.bigfoot.com', which is a +commercial LDAP server on the Internet - usually available +from anywhere. + +To specify a different LDAP server, you could either modify +the program to default elsewhere, or you could modify the +existing 'web_ldap.cfg' file, or create another one with +a different name. + +NOTE: A '#' in the first column of any line +in the configuration file is considered a comment. + +The configuration file allows you specify: + + server: + +This is the servername. For example: + + server:ldap.bigfoot.com,389 + +connects you up to port 389 on the ldap server 'ldap.bigfoot.com'. +You can specify one of your own servers here if you desire. + +Next you will see: + + searchbase: + +This is where within a tree you want to start looking. For +'ldap.bigfoot.com', you would leave this blank and it will +look in all the trees. For many companies a specific tree +structure will be defined, and you will want to specify the +highest point in the tree structure that defines the area that +you are interested in. For example, if you have a tree that +starts at 'c=US', and branches at 'o=ABC, c=US' and +'o=XYZ, c=US', you could specify: + + searchbase:c=US + +and search both 'o=ABC, c=US' and 'o=XYZ, c=US', or +if you only wanted to search against 'o=ABC, c=US', +you could specify: + + searchbase:o=ABC, c=US + +If you want to turn on a simple Debug mode, you can specify any number +other than zero for 'debug:'. For example: + + debug:1 + +turns on the Debug logging mode, and + + debug:0 + +turns it off. Debug logging simply creates a file called +'web_ldap.log' in the same directory that the web_ldap +executable is located. It flushes everything after each +event, so if it gets stuck anywhere, you will be able +to see it. It also time-stamps most of the results, so you +can get an idea where things are running faster and/or +slower for different queries. + +The remainder of the configuration file is where you list +the attributes that you are interested in displaying. + +You could list parameters (up to 100) like: + + cn + givenname + sn + +and that is all it will return. If you don't specify +anything, it returns everything it finds. if you +specify an attribute that the directory has never +heard of (ie. its not a member of any object class +anyone has defined), that attribute will simply be +ignored. If you misspell an attribute name and wonder +why it never gets listed in the results - this might be +why. If you specify an attribute that some users have and +others don't, only ones with that attribute will list +a value for it. + +Directory data can be multi-valued. This means that any +attribute could have multiple values. This application will +list all the values it finds for any given attribute. + + +Where to put the files: + +If running this interactively (from a Unix shell prompt), +all the files can reside in any of your home directories. +I suggest that you test the application in your home +directory first. + +If running this application from a Web Server, you need +to find out where the Web Server keeps its cgi applications +and where it keeps its html applications. This varies +from operating system to operating system and Web Server +to Web Server. + +Once you have located the cgi-bin (or equivalent) directory, +put these 2 files there: + + web_ldap + web_ldap.cfg + +then make sure that these files are accessible to the Web +Server by executing the Unix shell command: + + > chmod 777 web_ldap* + +Now find the HTML source directory. Copy + + web_ldap.html + +to this directory. Make sure that this file is accessible to the Web +Server by executing the Unix shell command: + + > chmod 777 web_ldap* + + +Running the application: + +Test it in your own directory by entering: + + > web_ldap DEF + +This should connect to 'ldap.bigfoot.com' and try to find a number +of entries (it does when I try it). You will notice that it +outputs results in the form of an HTML file - this is what it +is supposed to do. If you leave out the 'DEF', you will get the +error: + +

++ Error - This script should be referenced with a METHOD of POST. + +as a part of your result with no LDAP data returned. + +Interactively, the program assumes that you will always pass it at least +the name of the Configuration file ('DEF' tells it to use the default +configuration file). If there is no configuration file, it still will +find 'ldap.bigfoot.com'. + +Once you have it working there, try the version in the HTML directory. +To do so, enter your WEB Servers URL, the cgi-bin directory reference +and then the application name, all separated by slashes. For example, +if your Web Server URL is 'http://my.server.com', then you will want +to specify the URL: + + http://my.server.com/cgi-bin/web_ldap + +NOTE: You can only run cgi scripts out of a directory that the Web Server +allows. It is unlikely that you can execute Web Server CGI applications +from your own directory. + +This will provide a simple Web Based form. It will have 2 user entry +fields. The first allows you to enter an LDAP request. The second +allows you to specify a configuration file (it defaults to 'DEF'). + +Enter a simple LDAP request, such as the ones shown and see if you +get back a response. You should if connected to 'ldap.bigfoot.com'. + + +Now that you have it working: + +Feel free to adapt this program to fit your needs. You will need +to have the 'dn' in order to do updates. It is recovered within +the program, so you can save it for use once you retrieve it +(it is listed in the web_ldap.log file of you enable debug mode). + +This program does not update anything. The goal was to create a very +simple and expandable LDAP client and provide the complete source +code for doing it. To this goal, it is successful. From here +you should be able to experiment with the interfaces and create +new functionality to suit your given needs. + +This was tested against the UofM V 3.3 LDAP Libraries and the Netscape +V 1.x and V 3.x SDK under both Irix 6.2 (Silicon Graphics) and +Solaris 2.6 (Sun). I don't have other hardware or OS's to test +against here. + + +Usage Information: + +If you want to find out what attributes are being used, you can enable +the application to tell you all that it finds. Do this by simply +not defining any attributes within the configuration file. It will +list all the attributes it finds. You could create a special configuration +file specifically for this purpose. + +If you are getting fatal errors from your Web Server when you attempt to +execute a command, please try the same command using interactive mode. Look +to see if the HTML being generated makes sense or not. If the HTML +looks good, run it again interactively and pipe the results to a file, then +attempt to submit the resulting file as the URL. If it works, it is +likely that the environment you run is different than the one the Web +server is using - Unix file protections frequently are a cause of these +problems. If you can't determine what is different, discuss the problem +with your Unix system administrator - is is likely a resource problem. +If you add code that causes problems, but you still get a result, try the +application in interactive mode and verify the HTML being generated. Any +additional HTML code you add may need to to have proper termination syntax +(tables are very touchy about this), and you may need to further enhance +your changes to compensate. + +Please test your results on both Netscape's Web Browser and Internet +Explorer. Nothing is more irritating to end users than getting different +results based on their Web Browser selection. + +The Unix Command line will not allow you to pass some characters into +an application unless you surround the characters or command with quotes. +Some common examples of executing web_ldap interactively are: + + > web_ldap DEF "cn=j*moller" + + > web_ldap DEF cn=jens moller + +The command with the '*' in it requires quotes around it. Also note +that the application only allows the LDAP command to use up to 3 argv +values. This is as a limitation of the current parsing within the program +of argc/argv parameters. You could alter the program, or simply put +quotes around the LDAP request. Enable the debug mode within the +configuration file if you feel that the application is losing +arguments to see what its operating against. When operated by the Web Server, +and passing in FORM data - you won't have this limitation, and you don't +need quotes. + +You can pass hidden fields from the Web Form into the web_ldap program. +An example is shown with the name of 'FORM' having a value of '300'. +You can create additional hidden fields, named anything you want them +to be, with any value you want. These can be used to define existing +options (such as which configuration file to use), or other options +that your modified web_ldap.c program may want to have passed to it. + + +Jens Moller - Jens@colomar.com - COLOMAR Group -- 2.39.5