Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

lcmaps_posix.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001 EU DataGrid.                                                                             
00003  * For license conditions see http://www.eu-datagrid.org/license.html                                          
00004  *
00005  * Copyright (c) 2001, 2002 by 
00006  *     Martijn Steenbakkers <martijn@nikhef.nl>,
00007  *     David Groep <davidg@nikhef.nl>,
00008  *     NIKHEF Amsterdam, the Netherlands
00009  */
00010 
00093 /*****************************************************************************
00094                             Include header files
00095 ******************************************************************************/
00096 #include <stdio.h>
00097 #include <stdlib.h>
00098 #include <string.h>
00099 #include <pwd.h>
00100 #include <grp.h>
00101 #include <ctype.h>
00102 
00103 #include "lcmaps_config.h"
00104 #include "lcmaps_modules.h"
00105 #include "lcmaps_arguments.h"
00106 #include "lcmaps_cred_data.h"
00107 /******************************************************************************
00108                                 Definitions
00109 ******************************************************************************/
00110 
00111 #define MAX_UNDEFINED ((int)(-1))
00112 
00113 #ifndef NGROUPS
00114     #ifdef NGROUPS_MAX
00115         #define NGROUPS NGROUPS_MAX
00116     #else
00117         #define NGROUPS 32 
00118     #endif
00119 #endif
00120 
00121 /* 
00122  * MAX_NGROUPS has also been used. I couldn't see in the source if it was
00123  * a self made define in the code or that it was OS specific.
00124  */
00125 
00126 #ifndef MAX_LOG_BUFFER_SIZE
00127     #define MAX_LOG_BUFFER_SIZE 500
00128 #endif
00129 
00130 /******************************************************************************
00131                           Module specific prototypes
00132 ******************************************************************************/
00133 
00134 static int log_cred (
00135     char  *dn, 
00136     uid_t *uid, 
00137     int    cntUid, 
00138     gid_t *priGid, 
00139     int    cntPriGid, 
00140     gid_t *secGid, 
00141     int    cntSecGid
00142 );
00143 
00144 
00145 /******************************************************************************
00146                        Define module specific variables
00147 ******************************************************************************/
00148 
00149 static int maxuid  = MAX_UNDEFINED;
00150 static int maxpgid = MAX_UNDEFINED;
00151 static int maxsgid = MAX_UNDEFINED;
00152 
00153 
00154 
00155 /******************************************************************************
00156 Function:   log_cred
00157 Description:
00158     Makes a log of the Enforceable credential data
00159 Parameters:
00160     *dn        : Distinghuished Name
00161     *uid       : list of uid_t
00162     cntUid     : amount of uids (ussually only one)
00163     *priGid    : list of primary gid_t
00164     cntPriGid  : amount of primary gids (usually only one)
00165     *secGid    : list of secondary gid_t
00166     cntSecGid  : amount of secondary gids (0 to (NGROUPS || 32))
00167 
00168 Returns:
00169     0: succes
00170     1: failure
00171 ******************************************************************************/
00172 static int log_cred (char  *dn,
00173                      uid_t *uid,
00174                      int    cntUid,
00175                      gid_t *priGid,
00176                      int    cntPriGid,
00177                      gid_t *secGid,
00178                      int    cntSecGid)
00179 {
00180     char * logstr = "\tlcmaps_plugin_posix_enf-log_cred()";
00181 
00182     struct passwd *  user_info = NULL;
00183     struct group  *  grp_info = NULL;
00184   
00185     char *           logbuf;
00186     char *           strname;
00187     int              i;
00188     int              ngroups;
00189     gid_t *          list;
00190 
00191     int              logbufcnt = 0;
00192 
00193     // Log Enforced Credential Data
00194     logbuf = malloc(MAX_LOG_BUFFER_SIZE * sizeof(char));
00195 
00196     strcpy (logbuf, "uid=");
00197     logbufcnt += strlen(logbuf);
00198     for (i = 0; i < cntUid; i++)
00199     {
00200         user_info = getpwuid(getuid());
00201 
00202         if (user_info != NULL)
00203             logbufcnt += strlen(strname = strdup(user_info->pw_name));
00204         else
00205             logbufcnt += strlen(strname = strdup("n\\a"));
00206  
00207         if (i == 0)
00208             sprintf(logbuf, "%s%d(%s)",  logbuf, getuid(), strname);
00209         else
00210             sprintf(logbuf, "%s,%d(%s)", logbuf, getuid(), strname);
00211  
00212         free(strname);
00213         strname = NULL;
00214     }
00215 
00216     strcat(logbuf, ":pgid=");
00217     for (i = 0; i < cntPriGid; i++)
00218     {
00219         grp_info = getgrgid(getgid());
00220 
00221         if (grp_info != NULL)
00222             logbufcnt += strlen (strname = strdup (grp_info->gr_name));
00223         else
00224             logbufcnt += strlen (strname = strdup ("n\\a"));
00225 
00226         if (i == 0)
00227             sprintf(logbuf, "%s%d(%s)",  logbuf, getgid(), strname);
00228         else
00229             sprintf(logbuf, "%s,%d(%s)", logbuf, getgid(), strname);
00230 
00231         free(strname);
00232         strname = NULL;
00233     }
00234 
00235     if ((ngroups=getgroups(0, NULL)) > 0)
00236     {
00237         list = (gid_t *) malloc(ngroups * sizeof(gid_t));
00238         if (getgroups(ngroups, list) > 0)
00239         {
00240             strcat(logbuf, ":sgid=");
00241             for (i = 0; i < ngroups; i++)
00242             {
00243                 grp_info = getgrgid(list[i]);
00244                 strname = (char *) malloc (sizeof(char) * 30);
00245 
00246                 if (grp_info != NULL)
00247                     strname = strdup (grp_info->gr_name);
00248                 else
00249                     strname = strdup ("n\\a");
00250 
00251                 if (i == 0)
00252                     sprintf(logbuf, "%s%d(%s)",  logbuf, (secGid[i]), strname);
00253                 else
00254                     sprintf(logbuf, "%s,%d(%s)", logbuf, (secGid[i]), strname);
00255 
00256                 free(strname);
00257                 strname = NULL;
00258                 grp_info = NULL;
00259             }
00260         }
00261     }
00262 
00263     lcmaps_log_time(0, "%s: %s\n", logstr, logbuf);
00264 
00265     // End Log Credential Data 
00266 
00267     free(logbuf);
00268     return 0;
00269 }
00270 
00271 
00272 
00273 /******************************************************************************
00274 Function:   plugin_initialize
00275 Description:
00276     Initialize plugin
00277 Parameters:
00278     argc, argv
00279     argv[0]: the name of the plugin
00280 Returns:
00281     LCMAPS_MOD_SUCCESS : succes
00282     LCMAPS_MOD_FAIL    : failure
00283     LCMAPS_MOD_NOFILE  : db file not found (will halt LCMAPS initialization)
00284 ******************************************************************************/
00285 int plugin_initialize(
00286         int argc,
00287         char ** argv
00288 )
00289 {
00290     int i, j;
00291     char * logstr = "\tlcmaps_plugin_posix_enf-plugin_initialize()";  
00292 
00293  
00294     lcmaps_log_debug(1,"%s: passed arguments:\n", logstr);
00295     for (i=0; i < argc; i++)
00296     {
00297        lcmaps_log_debug(2,"%s: arg %d is %s\n", logstr, i, argv[i]);
00298     }
00299 
00300     /*
00301      * Parse arguments, argv[0] = name of plugin, so start with i = 1
00302      */
00303     for (i = 1; i < argc; i++)
00304     {
00305         // setting maxuid parameter from init plugin arguments
00306         if ( (((strcmp(argv[i], "-maxuid") == 0) ||
00307              (strcmp(argv[i], "-MAXUID") == 0)) &&
00308              (maxuid == MAX_UNDEFINED))
00309              && (i + 1 < argc) )
00310         {
00311             if ((argv[i + 1] != NULL) && (strlen(argv[i + 1]) > 0))
00312             {
00313                  lcmaps_log_debug(2,"%s: Checking if argument behind \"-maxuid\" is a number\n", logstr);
00314                  for (j = 0; j < strlen(argv[i + 1]); j++)
00315                  { 
00316                      if (!isdigit((argv[i + 1])[j]))
00317                      {
00318                          lcmaps_log(0,"%s\tError: maybe found some digits, but there is at least one char corrupting this parameter: %s\n", logstr, argv[i + 1]);
00319                          maxuid = -1;
00320                          goto fail_posix;
00321                      }
00322                  }
00323                  maxuid = atoi(argv[i + 1]);
00324             }
00325             else
00326             {
00327                 lcmaps_log(0,"%s: no argument found for %s (failure)\n", logstr, argv[i]);
00328                 goto fail_posix;
00329             }
00330             i++;
00331         }        
00332 
00333         // setting maxpgid parameter from init plugin arguments
00334         else if ( (((strcmp(argv[i], "-maxpgid") == 0) ||
00335              (strcmp(argv[i], "-MAXPGID") == 0)) &&
00336              (maxpgid == MAX_UNDEFINED))
00337              && (i + 1 < argc) )
00338         {
00339             if ((argv[i + 1] != NULL) && (strlen(argv[i + 1]) > 0))
00340             {
00341                  lcmaps_log_debug(2,"%s: Checking if argument behind \"-maxpgid\" is a number\n", logstr);
00342                  for (j = 0; j < strlen(argv[i + 1]); j++)
00343                  {
00344                      if (!isdigit((argv[i + 1])[j]))
00345                      {
00346                          lcmaps_log(0,"%s\tError: maybe found some digits, but there is at least one char corrupting this parameter: %s\n", logstr, argv[i + 1]);
00347                          maxpgid = -1;
00348                          goto fail_posix;
00349                      }
00350                  }
00351                  maxpgid = atoi(argv[i + 1]);
00352             }
00353             else
00354             {
00355                 lcmaps_log(0,"%s: no argument found for %s (failure)\n", logstr, argv[i]);
00356                 goto fail_posix;
00357             }
00358             i++;
00359         }
00360 
00361         // setting maxsgid parameter from init plugin arguments
00362         else if  ( (((strcmp(argv[i], "-maxsgid") == 0) ||
00363              (strcmp(argv[i], "-MAXSGID") == 0)) &&
00364              (maxsgid == MAX_UNDEFINED))
00365              && (i + 1 < argc) )
00366         {
00367             if ((argv[i + 1] != NULL) && (strlen(argv[i + 1]) > 0))
00368             {
00369                  lcmaps_log_debug(2,"%s: Checking if argument behind \"-maxsgid\" is a number\n", logstr);
00370                  for (j = 0; j < strlen(argv[i + 1]); j++)
00371                  {
00372                      if (!isdigit((argv[i + 1])[j]))
00373                      {
00374                          lcmaps_log(0,"%s\tError: maybe found some digits, but there is atleast one char corrupting this parameter: %s\n", logstr, argv[i + 1]);
00375                          maxsgid = -1;
00376                          goto fail_posix;
00377                      }
00378                  }
00379                  maxsgid = atoi(argv[i + 1]);
00380             }
00381             else
00382             {
00383                 lcmaps_log(0,"%s: no argument found for %s (failure)\n", logstr, argv[i]);
00384                 goto fail_posix;
00385             }
00386             i++;
00387         }
00388     }
00389 
00390     if (maxsgid > NGROUPS)
00391     {
00392         lcmaps_log(0,"%s\tError: The prefered set maximum of %d Secondary Gid's exceeds the system maximum of NGROUPS witch is set to %d on this system\n", logstr, maxsgid, NGROUPS);
00393         goto fail_posix;
00394     }
00395     else if (maxsgid == MAX_UNDEFINED)
00396     {
00397         lcmaps_log(0,"%s\tAuto set maximum Secondary Gid's to system maximum of NGROUPS witch is set to %d on this system\n", logstr, NGROUPS);
00398     }
00399 
00400 
00401     lcmaps_log_debug(2,"%s: Summary init maxuid  : %d\n", logstr, maxuid);
00402     lcmaps_log_debug(2,"%s: Summary init maxpgid : %d\n", logstr, maxpgid);
00403     lcmaps_log_debug(2,"%s: Summary init maxsgid : %d\n", logstr, maxsgid);
00404 
00405     return LCMAPS_MOD_SUCCESS;
00406 
00407 
00408  fail_posix:
00409     return LCMAPS_MOD_FAIL; 
00410 } 
00411 
00412 /******************************************************************************
00413 Function:   plugin_introspect
00414 Description:
00415     return list of required arguments
00416 Parameters:
00417 
00418 Returns:
00419     LCMAPS_MOD_SUCCESS : succes
00420     LCMAPS_MOD_FAIL    : failure
00421 ******************************************************************************/
00422 int plugin_introspect(
00423         int * argc,
00424         lcmaps_argument_t ** argv
00425 )
00426 {
00427     char * logstr = "\tlcmaps_plugin_posix_enf-plugin_introspect()";  
00428 
00429     static lcmaps_argument_t argList[] = {
00430         {NULL           ,       NULL            , -1,   NULL}
00431     };
00432 
00433     lcmaps_log_debug(1,"%s: introspecting\n", logstr);
00434 
00435     *argv = argList;
00436     *argc = lcmaps_cntArgs(argList);
00437     lcmaps_log_debug(1,"%s: address first argument: 0x%x\n", logstr, argList);
00438 
00439     return LCMAPS_MOD_SUCCESS;
00440 }
00441 
00442 
00443 /******************************************************************************
00444 Function:   plugin_run
00445 Description:
00446     Gather credentials for LCMAPS
00447 Parameters:
00448     argc: number of arguments
00449     argv: list of arguments
00450 Returns:
00451     LCMAPS_MOD_SUCCESS: authorization succeeded
00452     LCMAPS_MOD_FAIL   : authorization failed
00453 ******************************************************************************/
00454 int plugin_run(
00455         int argc,
00456         lcmaps_argument_t * argv
00457 )
00458 {
00459     char * logstr = "\tlcmaps_plugin_posix_enf-plugin_run()";  
00460     int                 i, t; 
00461     gid_t *             list        = NULL;
00462     int                 ngroups     = 0;
00463  
00464     char  *             dn          = NULL;
00465     uid_t *             uid         = NULL;
00466     int                 cntUid;
00467     gid_t *             priGid      = NULL;
00468     int                 cntPriGid;
00469     gid_t *             secGid      = NULL;
00470     int                 cntSecGid;
00471     struct passwd *     root_info   = NULL;
00472 
00473     /*
00474      * The beginning
00475      */
00476     lcmaps_log_debug(1,"%s\n", logstr);
00477 
00478     uid    = getCredentialData(UID,     &cntUid);
00479     priGid = getCredentialData(PRI_GID, &cntPriGid);
00480     secGid = getCredentialData(SEC_GID, &cntSecGid);
00481     lcmaps_log_debug(2,"%s: number of uids: %d, priGids: %d, secGids: %d\n", logstr, cntUid,cntPriGid,cntSecGid);
00482     
00483     // Check amount of uid's, pri-gid's and sec-gid's with the set maximum
00484     if (maxuid != MAX_UNDEFINED)
00485     {
00486         lcmaps_log_debug(2,"%s: max number of uids: %d\n", logstr, maxuid);
00487         if (cntUid > maxuid)
00488         {
00489             lcmaps_log(0, "%s:\tError: The set amount of uid's gathered exceeds the maximum of %d uid('s) by %d\n", logstr, maxuid, (cntUid - maxuid));
00490             goto fail_posix;
00491         }
00492     }
00493     if (maxpgid != MAX_UNDEFINED)
00494     {
00495         lcmaps_log_debug(2,"%s: max number of primary gid('s): %d\n", logstr, maxpgid);
00496         if (cntPriGid > maxpgid)
00497         {
00498             lcmaps_log(0, "%s:\tError: The set amount of primary gid's gathered exceeds the maximum of %d primary gid('s) by %d\n", logstr, maxpgid, (cntPriGid - maxpgid));
00499             goto fail_posix;
00500         }
00501     }
00502     if (maxsgid != MAX_UNDEFINED)
00503     {
00504         lcmaps_log_debug(2,"%s: max number of secondary gid's: %d\n", logstr, maxsgid);
00505         if (cntSecGid > maxsgid)
00506         {
00507             lcmaps_log(0, "%s:\tError: The set amount of secondary gid's gathered exceeds the maximum of %d secunadary gid's by %d\n", logstr, maxsgid, (cntSecGid - maxsgid));
00508             goto fail_posix;
00509         }
00510     }
00511 
00512 
00513     // Je moet ROOT zijn
00514     if (getuid() != 0)
00515     {
00516         lcmaps_log(0, "%s: The service did not initialize with Root! -> %d\n", logstr, getuid());
00517         goto fail_posix;
00518     }
00519 
00520     // Only done to get name of root (normally "root")
00521     if ((root_info=getpwuid(0)) == NULL)
00522     {
00523         lcmaps_log(0, "%s: cannot get passwd info for root\n", logstr);
00524         if (errno==ENOMEM)
00525             lcmaps_log(0, "%s: %s\n", logstr, strerror(errno));
00526         goto fail_posix;
00527     }
00528     lcmaps_log_debug(3,"%s: Name of root: %s\n", logstr, root_info->pw_name);
00529     lcmaps_log_debug(3,"%s: Je GID was             -> %d\n", logstr, getgid());
00530     lcmaps_log_debug(3,"%s: Je effective GID  was  -> %d\n", logstr, getegid());
00531 
00532     // Set new primary group ID
00533     if (cntPriGid > 0)
00534     {
00535         if (setregid(priGid[0], priGid[0]) != 0)
00536         {
00537             lcmaps_log(0, "%s: cannot setregid()\n", logstr);
00538             lcmaps_log(0, "%s: %s\n",                logstr, strerror(errno));
00539         }
00540     }
00541     else
00542     {
00543         lcmaps_log(0, "%s: No primary group IDs found, need at least 1 !\n", logstr);
00544         goto fail_posix;
00545     }
00546         
00547     lcmaps_log_debug(3,"%s: Je GID is nu           -> %d\n", logstr, getgid());
00548     lcmaps_log_debug(3,"%s: Je effective GID is nu -> %d\n", logstr, getegid());
00549 
00550     // Initialize group access list for root
00551     if (initgroups(root_info->pw_name, root_info->pw_gid)!=0)
00552     {
00553         lcmaps_log(0, "%s: error in initgroups() call\n", logstr);
00554         lcmaps_log(0, "%s: %s\n", logstr, strerror(errno));
00555         goto fail_posix;
00556     }
00557 
00558     // Get the number of secondary group IDs for root
00559     if ((ngroups=getgroups(0, NULL)) < 0)
00560     {
00561         lcmaps_log(0, "%s: error in getgroups() call\n", logstr);
00562         lcmaps_log(0, "%s: %s\n", logstr, strerror(errno));
00563         goto fail_posix;
00564     }
00565     lcmaps_log_debug(3,"%s: found %d sec group IDs initially\n", logstr, ngroups);
00566     list = (gid_t *) malloc(ngroups * sizeof(gid_t));
00567 
00568     // Get the secondary group IDs for root
00569     if (getgroups(ngroups, list) < 0)
00570     {
00571         lcmaps_log(0, "%s: error in getgroups() call\n", logstr);
00572         lcmaps_log(0, "%s: %s\n", logstr, strerror(errno));
00573         goto fail_posix;
00574     }
00575     for (t = 0; t < ngroups; t++)
00576     {
00577         lcmaps_log_debug(3,"%s: Je Sec. Gids waren     -> %d\n", logstr, list[t]);
00578     }
00579     if (list) free(list);
00580     list=(gid_t *) NULL;
00581 
00582     // Set the new secondary group IDs
00583     if (setgroups(cntSecGid, secGid)!=0)
00584     {
00585         switch (errno)
00586         {
00587             case EFAULT :
00588                 {
00589                     lcmaps_log_debug(1, "%s: Not that fatal but serious error\n", logstr);
00590                     lcmaps_log(0, "%s: %s\n", logstr, strerror(errno));
00591                     goto fail_posix;
00592                     break;
00593                 }
00594             case EPERM :
00595                 {
00596                     lcmaps_log_debug(1, "%s: You are not ROOT\n", logstr);
00597                     lcmaps_log(0, "%s: %s\n", logstr, strerror(errno));
00598                     goto fail_posix;
00599                     break;
00600                 }
00601             case EINVAL :
00602                 {
00603                     for (i = 0; i < cntSecGid; i++)
00604                     {
00605                         lcmaps_log_debug(1,"%s: > i = %d met %d\n", logstr, i, secGid[i]);
00606                     }
00607                     lcmaps_log_debug(1, "%s: Invalid GID list\n", logstr);
00608                     lcmaps_log(0, "%s: %s\n", logstr, strerror(errno));
00609                     goto fail_posix;
00610                     break;
00611                 }
00612             default :
00613                 {
00614                     lcmaps_log_debug(1, "%s: Unspecified error in setgroups()\n", logstr);
00615                     goto fail_posix;
00616                 }
00617         }
00618     }
00619     // Get the new number of secondary group IDs
00620     if ((ngroups=getgroups(0, NULL)) < 0)
00621     {
00622         lcmaps_log(0, "%s: error in getgroups() call\n", logstr);
00623         lcmaps_log(0, "%s: %s\n", logstr, strerror(errno));
00624         goto fail_posix;
00625     }
00626     lcmaps_log_debug(1,"%s: found %d sec gids after setgroups(), cntSecGid=%d\n", logstr, ngroups,cntSecGid);
00627     list = (gid_t *) malloc(ngroups * sizeof(gid_t));
00628 
00629     // Get the new secondary group IDs
00630     if (getgroups(ngroups, list) < 0)
00631     {
00632         lcmaps_log(0, "%s: error in getgroups() call\n", logstr);
00633         lcmaps_log(0, "%s: %s\n", logstr, strerror(errno));
00634         goto fail_posix;
00635     }
00636     for (t = 0; t < ngroups; t++)
00637     {
00638         lcmaps_log_debug(2,"%s: Je Sec. Gid s zijn nu  -> %d\n", logstr, list[t]);
00639     }
00640 
00641     lcmaps_log_debug(2,"%s: Je was user            -> %d\n", logstr, getuid());
00642 
00643     // Set the new user ID
00644     if (cntUid > 0)
00645     {
00646         if (setreuid(uid[0], uid[0]) != 0)
00647         {
00648             lcmaps_log(0, "%s: cannot setreuid()\n", logstr);
00649             lcmaps_log(0, "%s: %s\n", logstr, strerror(errno));
00650         }
00651     }
00652     else
00653     {
00654         lcmaps_log(0, "%s: No user IDs found, need at least 1 !\n", logstr);
00655         goto fail_posix;
00656     }
00657 
00658     lcmaps_log_debug(2,"%s: Je bent nu geworden    -> %d\n", logstr, getuid());
00659     lcmaps_log_debug(1,"%s: Je UID            is   -> %d\n", logstr, geteuid());
00660     lcmaps_log_debug(1,"%s: Je effective UID  is   -> %d\n", logstr, geteuid());
00661 
00662 
00663     /* We should set the appropriate environment variables here (see globus gatekeeper)
00664      * (or before all setuid/setgid calls ?)
00665      */
00666 
00667 
00668     // Do Not End This POSIX Enforment with ROOT privileges
00669     if ((getuid() == 0) || (getgid() == 0))
00670     {
00671         goto fail_posix;
00672     }
00673 
00674 
00675     // Log Enforced Credential Data
00676     log_cred(dn, uid, cntUid, priGid, cntPriGid, secGid, cntSecGid);
00677 
00678 
00679     /* succes */
00680  success_posix:
00681     if (list) free(list);
00682     lcmaps_log_time(0,"%s: posix_enf plugin succeeded\n", logstr);
00683     return LCMAPS_MOD_SUCCESS;
00684 
00685  fail_posix:
00686     if (list) free(list);
00687     lcmaps_log_time(0,"%s: posix_enf plugin failed\n", logstr);
00688     return LCMAPS_MOD_FAIL;
00689 }
00690 
00691 /******************************************************************************
00692 Function:   plugin_terminate
00693 Description:
00694     Terminate plugin
00695 Parameters:
00696 
00697 Returns:
00698     LCMAPS_MOD_SUCCESS : succes
00699     LCMAPS_MOD_FAIL    : failure
00700 ******************************************************************************/
00701 int plugin_terminate()
00702 {
00703     char * logstr = "\tlcmaps_plugin_posix_enf-plugin_introspect()";
00704 
00705     lcmaps_log_debug(1,"%s: terminating\n", logstr);
00706     
00707     return LCMAPS_MOD_SUCCESS;
00708 }
00709 
00710 /******************************************************************************
00711 CVS Information:
00712     $Source: /cvs/fabric_mgt/gridification/lcmaps/modules/posix_enf/lcmaps_posix.c,v $
00713     $Date: 2003/08/12 13:04:16 $
00714     $Revision: 1.20 $
00715     $Author: martijn $
00716 ******************************************************************************/

Generated at Tue Sep 23 15:48:08 2003 for edg-lcmaps by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001