Skip to content
Snippets Groups Projects
Commit b063f5e8 authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Initial import of web_ldap written and contributed

by Jens Moller <Jens.Moller@mci.com>.
parent 9bd0b8f7
No related branches found
No related tags found
No related merge requests found
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.
#
# 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
#
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.
/* 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' */
/* 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' */
/* 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 <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#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("<HR><H1>Form Data</H1>");
printf("The following Name Value pairs currently exist:<p>%c",10);
printf("<ul><pre>%c",10);
while(entries[x].name)
{
printf("<li> <code>%s = [%s]</code>%c",entries[x].name,
entries[x].val,10);
x++;
}
printf("</pre></ul>%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("<HR><H1>Form Data</H1>");
printf("The following Name Value pairs currently exist:<p>%c",10);
printf("<ul><pre>%c",10);
while(entries[x].name)
{
printf("<li> <code>%s = [%s]</code>%c",entries[x].name,
entries[x].val,10);
x++;
}
printf("</pre></ul>%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",
"<p><b>(OOPS... We are unable to open file ",
filename,
" for reading)</b><p>\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' */
/* 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 <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <lber.h>
#include <ldap.h>
#include <ldif.h>
#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("<html>\n<head>\n<title>Web Ldap Results</title>\n");
printf("</head>\n");
printf("<body text=\"#000000\" bgcolor=\"#FFFFFF\">\n");
printf("<h2>Web LDAP Results</h2>\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<strlen(temp);i++) {
if ((temp[i] != '"') &&
(temp[i] != '\\')){
passed_in[j] = temp[i];
j++;
}
}
}
}
else { /* Non Interactive Mode - read from a form */
if (strcompare(getenv("REQUEST_METHOD"),"POST"))
{
printf("<p>++ 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("<p>++ 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<br>\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("<font color=red size=5>\n");
printf("<p>Unable to open requested log file: web_ldap.log<p>\n");
printf("</font>\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("<font color=red><b>ldap_open error</b></font>\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("</body>\n</html>\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("<font color=red><b>");
ldap_perror (ld, "ldap_simple_bind_s");
printf("</b></font>\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("</body>\n</html>\n");
exit(1);
}
printf("<b>Directory Lookup Results</b>\n<pre>\n");
printf("<hr><p>\n<pre>\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("<p>\n");
}
/*free the search results */
ldap_msgfree (res);
printf("</pre>\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("</body>\n</html>\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<len ;i++) {
icmp = memcmp(&istring[i],tstring,strlen(tstring));
if (icmp == 0) {
status = i;
break;
}
}
return status;
}
/* convert the array to uparray, where uparray contains upper
* case characters */
void upcase_string(char *array,
char *uparray) {
int i;
for (i=0; i < strlen(array); i++) {
uparray[i] = toupper(array[i]);
uparray[i + 1] = 0;
}
return;
}
/* return the position of the first comma - ',' - from within a string */
int find_comma(char *array){
int i;
for (i = 0; i < strlen(array); i++) {
if (array[i] == ',') return(i);
}
return -1;
}
/* return the position of the first colon - '.' - from within a string */
int find_colon(char *array){
int i;
for (i = 0; i < strlen(array); i++) {
if (array[i] == ':') return(i);
}
return -1;
}
/* Remove unneeded blanks from a character array. Don't leave
* any at the end & throw away any newline characters */
void squeeze_blanks(char *array){
int i, pos, blank;
char temp[1024];
memset(temp,0,1024);
pos = 0; /* location within temp array */
blank = 0; /* # of blanks written in a row */
for (i = 0; i < strlen(array); i++) {
if (array[i] != ' ') {
temp[pos] = array[i];
blank = 0;
pos++;
}
else if ((blank == 0) &&
(array[i] == ' ') &&
(pos != 0)) {
temp[pos] = array[i];
blank += 1;
pos++;
}
}
strcpy(array,temp);
if (array[strlen(array) - 1] <= ' ')
array[strlen(array) - 1] = 0;
}
#
# web_ldap.cfg
#
#
# Servers to access:
#
# server:dns_name,port_number - default = ldap.bigfoot.com,389
server:ldap.bigfoot.com,389
#
# searchbase:?? Sample: 'o=Xyz, c=US', default - blank (nothing).
searchbase:
#
# debug: Debug Mode; 0 = off, any other integer = on
debug:1
#
# columns list across based on the order in the
# attribute list.
#
# NOTE: Unknown Attributes will be ignored - so list any
# that you want. To find out what attributes a server
# has for a given entry, leave the attribute list blank.
#
# attribute list - default = all returned of nothing defined
#
#cn
#email
# done
<html>
<head>
<title>Web LDAP Access</title>
</head>
<body text="#000000"
bgcolor="#FFFFCC">
<h2>Web LDAP Access</h2>
<!-- Form Action Statement -->
<form action="/cgi-bin/web_ldap" method="POST">
<input type=hidden name="FORM" value="300">
<p>
Please fill in the LDAP request you desire. You may use
wildcards (*) in this fashion:
<ul>
<b>Common Name Examples</b><p>
<li>cn=jens moller
<li>cn=*moller
<li>cn=j* moller
<p>
<b>Surname Examples</b><p>
<li>sn=moller
<li>sn=*moller
</ul>
<p>
You may specify a configuration file if you have created a
new one, otherwise, leave it set to "DEF".
<hr>
<pre>
LDAP Request: <input type="text" size="40" name="LDAP_REQUEST">
Config File: <input type="text" size="40" value="DEF" name="CONFIG">
</pre>
<input type="submit" name="button" value="Generate Results">
<input type="reset" value="Reset">
</ul>
<p>
</form>
<hr>
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.
<p>
Authored by: <a href="mailto:Jens@colomar.com">Jens Moller</a>.
</body>
</html>
==> 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 >==
<html>
<title>web_ldap_usage</title>
<body text="#000000"
bgcolor="#FFFFFF">
<h2>web_ldap V 1.1</h2>
<i>
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
(<a href="mailto:jens@colomar.com">jens@colomar.com</a>).
<p>
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.
</i>
<h3>Introduction:</h3>
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.
<p>
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).
<p>
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.
<p>
The application can be run interactively (without use of
a Web Browser) but was intended for use as an HTML LDAP Web
page application.
<p>
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.
<p>
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.
<p>
The 2 environments are 'Interactive' and 'Web Server'.
<p>
When you execute the application from a command line such as:
<pre>
&gt; web_ldap DEF cn=jens moller
</pre>
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.
<p>
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.
<p>
When your program executes from a Web Browser, you will
see something like:
<pre>
http://my.system.com/cgi-bin/web_ldap
</pre>
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.
<h3>Building the application:</h3>
Requires Ansi C (your standard OS compiler or GCC should
work fine).
<p>
The make file contains:
<pre>
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
</pre>
<h3>Configuration:</h3>
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.
<p>
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.
<p><i>
NOTE: A '#' in the first column of any line
in the configuration file is considered a comment.
</i>
<p>
The configuration file allows you specify:
<pre>
server:
</pre>
This is the servername. For example:
<pre>
server:ldap.bigfoot.com,389
</pre>
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.
<p>
Next you will see:
<pre>
searchbase:
</pre>
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:
<pre>
searchbase:c=US
</pre>
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:
<pre>
searchbase:o=ABC, c=US
</pre>
If you want to turn on a simple Debug mode, you can specify any number
other than zero for 'debug:'. For example:
<pre>
debug:1
</pre>
turns on the Debug logging mode, and
<pre>
debug:0
</pre>
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.
<p>
The remainder of the configuration file is where you list
the attributes that you are interested in displaying.
<p>
You could list parameters (up to 100) like:
<pre>
cn
givenname
sn
</pre>
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.
<p>
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.
<h3?Where to put the files:</h3>
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.
<p>
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.
<p>
Once you have located the cgi-bin (or equivalent) directory,
put these 2 files there:
<pre>
web_ldap
web_ldap.cfg
</pre>
then make sure that these files are accessible to the Web
Server by executing the Unix shell command:
<pre>
&gt; chmod 777 web_ldap*
</pre>
Now find the HTML source directory. Copy
<pre>
web_ldap.html
</pre>
to this directory. Make sure that this file is accessible to the Web
Server by executing the Unix shell command:
<pre>
&gt; chmod 777 web_ldap*
</pre>
<h3>Running the application:</h3>
Test it in your own directory by entering:
<pre>
&gt; web_ldap DEF
</pre>
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:
<pre>
&lt;p&gt;++ Error - This script should be referenced with a METHOD of POST.
</pre>
as a part of your result with no LDAP data returned.
<p>
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'.
<p>
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:
<pre>
http://my.server.com/cgi-bin/web_ldap
</pre>
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.
<p>
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').
<p>
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'.
<h3>Now that you have it working:</h3>
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).
<p>
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.
<p>
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.
<h3>Usage Information:</h3>
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.
<p>
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.
<p>
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.
<p>
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:
<pre>
&gt; web_ldap DEF "cn=j*moller"
&gt; web_ldap DEF cn=jens moller
</pre>
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.
<p>
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.
<p>
<hr>
Jens Moller - Jens@colomar.com -
<a href="http://www.colomar.com">COLOMAR Group</a>
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:
<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.
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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment