gridsite.h
Go to the documentation of this file.
00001 /*
00002    Copyright (c) 2002-10, Andrew McNab, University of Manchester
00003    All rights reserved.
00004 
00005    Redistribution and use in source and binary forms, with or
00006    without modification, are permitted provided that the following
00007    conditions are met:
00008 
00009      o Redistributions of source code must retain the above
00010        copyright notice, this list of conditions and the following
00011        disclaimer. 
00012      o Redistributions in binary form must reproduce the above
00013        copyright notice, this list of conditions and the following
00014        disclaimer in the documentation and/or other materials
00015        provided with the distribution. 
00016 
00017    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
00018    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
00019    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00020    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00021    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
00022    BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00024    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00025    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00026    ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00028    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029    POSSIBILITY OF SUCH DAMAGE.
00030 */
00031 
00032 /*---------------------------------------------------------------*
00033  * For more about GridSite: http://www.gridsite.org/             *
00034  *---------------------------------------------------------------*/
00035 
00036 #ifndef GRST_VERSION
00037 #define GRST_VERSION 010500
00038 
00039 #ifdef __cplusplus
00040 extern "C" {
00041 #endif
00042 
00043 #ifndef GRST_NO_OPENSSL
00044 
00045 #ifndef HEADER_SSL_H
00046 #include <openssl/ssl.h>
00047 #endif
00048 
00049 #ifndef HEADER_CRYPTO_H
00050 #include <openssl/crypto.h>
00051 #endif
00052 
00053 #endif
00054 
00055 #ifndef _TIME_H
00056 #include <time.h>
00057 #endif
00058 
00059 #ifndef _STDIO_H
00060 #include <stdio.h>
00061 #endif
00062 
00063 #ifndef _STDINT_H
00064 #include <stdint.h>
00065 #endif
00066 
00067 #ifndef FALSE
00068 #define FALSE (0)
00069 #endif
00070 #ifndef TRUE
00071 #define TRUE (!FALSE)
00072 #endif
00073 
00074 // Everything ok (= OpenSSL X509_V_OK)
00075 #define GRST_RET_OK             0
00076 
00077 // Failed for unspecified reason
00078 #define GRST_RET_FAILED         1000
00079 
00080 // Failed to find certificate in some cert store / directory
00081 #define GRST_RET_CERT_NOT_FOUND 1001
00082 
00083 // Bad signature
00084 #define GRST_RET_BAD_SIGNATURE  1002
00085 
00086 // No such file or directory
00087 #define GRST_RET_NO_SUCH_FILE   1003
00088 
00089 /* We use && now rather than if so this macro can be used inside if...else
00090    but that means the function must return an int rather than be void */
00091 #define GRSTerrorLog(GRSTerrorLevel, ...) ((GRSTerrorLogFunc != NULL) && ((GRSTerrorLogFunc)(__FILE__, __LINE__, GRSTerrorLevel, __VA_ARGS__)))
00092 
00093 extern int (*GRSTerrorLogFunc)(char *, int, int, char *, ...);
00094 
00095 /* these levels are the same as Unix syslog() and Apache ap_log_error() */
00096 
00097 #define GRST_LOG_EMERG   0
00098 #define GRST_LOG_ALERT   1
00099 #define GRST_LOG_CRIT    2
00100 #define GRST_LOG_ERR     3
00101 #define GRST_LOG_WARNING 4
00102 #define GRST_LOG_NOTICE  5
00103 #define GRST_LOG_INFO    6
00104 #define GRST_LOG_DEBUG   7
00105 
00106 #define GRST_MAX_TIME_T  INT32_MAX
00107 
00108 typedef struct { char                      *auri;
00109                  int                        delegation;
00110                  int                        nist_loa;
00111                  time_t                     notbefore;
00112                  time_t                     notafter;
00113                  void                      *next;     } GRSTgaclCred;
00114 
00115 /* used by pre-AURI GRSTgaclCred structs */ 
00116 __attribute__ ((deprecated))
00117 typedef struct { char                      *name;
00118                  char                      *value;
00119                  void                      *next;  } GRSTgaclNamevalue;
00120 
00121 typedef int                GRSTgaclAction;
00122 typedef unsigned int       GRSTgaclPerm;
00123  
00124 typedef struct { GRSTgaclCred   *firstcred;
00125                  GRSTgaclPerm    allowed;
00126                  GRSTgaclPerm    denied;
00127                  void           *next;    } GRSTgaclEntry;
00128  
00129 typedef struct { GRSTgaclEntry *firstentry; } GRSTgaclAcl;
00130  
00131 typedef struct { GRSTgaclCred *firstcred; char *dnlists; } GRSTgaclUser;
00132 
00133 #define GRST_PERM_NONE   0
00134 #define GRST_PERM_READ   1
00135 #define GRST_PERM_EXEC   2
00136 #define GRST_PERM_LIST   4
00137 #define GRST_PERM_WRITE  8
00138 #define GRST_PERM_ADMIN 16
00139 #define GRST_PERM_ALL   31
00140 
00141 /* DO NOT USE PermIsNone!! */
00142 #define GRSTgaclPermIsNone(perm)    ((perm) == 0)
00143 
00144 #define GRSTgaclPermHasNone(perm)    ((perm) == 0)
00145 #define GRSTgaclPermHasRead(perm)  (((perm) & GRST_PERM_READ ) != 0)
00146 #define GRSTgaclPermHasExec(perm)  (((perm) & GRST_PERM_EXEC ) != 0)
00147 #define GRSTgaclPermHasList(perm)  (((perm) & GRST_PERM_LIST ) != 0)
00148 #define GRSTgaclPermHasWrite(perm) (((perm) & GRST_PERM_WRITE) != 0)
00149 #define GRSTgaclPermHasAdmin(perm) (((perm) & GRST_PERM_ADMIN) != 0)
00150 
00151 #define GRST_ACTION_ALLOW 0
00152 #define GRST_ACTION_DENY  1
00153 
00154 #define GRST_HIST_PREFIX  ".grsthist"
00155 #define GRST_ACL_FILE     ".gacl"
00156 #define GRST_DN_LISTS     "/etc/grid-security/dn-lists"
00157 #define GRST_RECURS_LIMIT 9
00158 
00159 #define GRST_PROXYCERTINFO_OLD_OID      "1.3.6.1.4.1.3536.1.222"
00160 #define GRST_PROXYCERTINFO_OID          "1.3.6.1.5.5.7.1.14"
00161 #define GRST_VOMS_OID           "1.3.6.1.4.1.8005.100.100.5"
00162 #define GRST_VOMS_DIR           "/etc/grid-security/vomsdir"
00163 #define GRST_KEYUSAGE_OID       "2.5.29.15"
00164 
00165 #define GRST_ASN1_MAXCOORDLEN   50
00166 #define GRST_ASN1_MAXTAGS       500
00167 
00168 struct GRSTasn1TagList { char treecoords[GRST_ASN1_MAXCOORDLEN+1];
00169                          int  start;
00170                          int  headerlength;
00171                          int  length;
00172                          int  tag; } ;
00173 
00174 #define GRST_X509_SERIAL_DIGITS 49
00175 
00176 typedef struct { int    type;           /* CA, user, proxy, VOMS, ... */
00177                  int    errors;         /* unchecked, bad sig, bad time */
00178                  char   *issuer;        /* Cert CA DN, EEC of PC, or VOMS DN */
00179                  char   *dn;            /* Cert DN, or VOMS AC holder DN */
00180                  char   *value;         /* VOMS FQAN or NULL */
00181                  time_t notbefore;
00182                  time_t notafter;
00183                  int    delegation;     /* relative to END of any chain */
00184                  char   serial[GRST_X509_SERIAL_DIGITS+1];
00185                  char   *ocsp;          /* accessLocation field */
00186                  void   *raw;           /* X509 or VOMS Extension object */
00187                  void   *next; } GRSTx509Cert;
00188 
00189 #define GRST_CERT_BAD_FORMAT 1
00190 #define GRST_CERT_BAD_CHAIN  2
00191 #define GRST_CERT_BAD_SIG    4
00192 #define GRST_CERT_BAD_TIME   8
00193 #define GRST_CERT_BAD_OCSP  16
00194 
00195 #define GRST_CERT_TYPE_CA    1
00196 #define GRST_CERT_TYPE_EEC   2
00197 #define GRST_CERT_TYPE_PROXY 3
00198 #define GRST_CERT_TYPE_VOMS  4
00199 
00200 /* a chain of certs, starting from the first CA */
00201 typedef struct { GRSTx509Cert *firstcert; } GRSTx509Chain;
00202 
00203 #ifndef GRST_NO_OPENSSL
00204 int GRSTx509CertLoad(GRSTx509Cert *, X509 *);
00205 int GRSTx509ChainLoadCheck(GRSTx509Chain **, STACK_OF(X509) *, X509 *, char *, char *);
00206 #endif
00207 int GRSTx509ChainFree(GRSTx509Chain *);
00208 
00209 #define GRST_HTTP_PORT          777
00210 #define GRST_HTTPS_PORT         488
00211 #define GRST_HTCP_PORT          777
00212 #define GRST_GSIFTP_PORT        2811
00213                          
00214 #define GRSThtcpNOPop 0
00215 #define GRSThtcpTSTop 1
00216 
00217 typedef struct { unsigned char length_msb;
00218                  unsigned char length_lsb;
00219                  char text[1]; } GRSThtcpCountstr;
00220 
00221 #define GRSThtcpCountstrLen(string) (256*((string)->length_msb) + (string)->length_lsb)
00222 
00223 typedef struct { unsigned char total_length_msb;
00224                  unsigned char total_length_lsb;
00225                  unsigned char version_msb;
00226                  unsigned char version_lsb;
00227                  unsigned char data_length_msb;
00228                  unsigned char data_length_lsb;
00229                  unsigned int  response : 4;
00230                  unsigned int  opcode   : 4;
00231                  unsigned int  rr       : 1;                 
00232                  unsigned int  f1       : 1;
00233                  unsigned int  reserved : 6;
00234                  unsigned int  trans_id;        /* must be 4 bytes */
00235                  GRSThtcpCountstr *method;
00236                  GRSThtcpCountstr *uri;
00237                  GRSThtcpCountstr *version;
00238                  GRSThtcpCountstr *req_hdrs;
00239                  GRSThtcpCountstr *resp_hdrs;
00240                  GRSThtcpCountstr *entity_hdrs;
00241                  GRSThtcpCountstr *cache_hdrs;   } GRSThtcpMessage;
00242 
00243 int GRSTgaclInit(void);
00244 
00245 __attribute__ ((deprecated))
00246 GRSTgaclCred *GRSTgaclCredNew(char *);
00247 
00248 GRSTgaclCred *GRSTgaclCredCreate(char *, char *);
00249 
00250 __attribute__ ((deprecated))
00251 int     GRSTgaclCredAddValue(GRSTgaclCred *, char *, char *);
00252 
00253 #define GRSTgaclCredGetAuri(cred) ((cred)->auri)
00254 
00255 #define GRSTgaclCredSetNotBefore(cred, time) ((cred)->notbefore = (time))
00256 #define GRSTgaclCredGetNotBefore(cred) ((cred)->notbefore)
00257 
00258 #define GRSTgaclCredSetNotAfter(cred, time) ((cred)->notafter = (time))
00259 #define GRSTgaclCredGetNotAfter(cred) ((cred)->notafter)
00260 
00261 #define GRSTgaclCredSetDelegation(cred, level) ((cred)->delegation = (level))
00262 #define GRSTgaclCredGetDelegation(cred) ((cred)->delegation)
00263 
00264 #define GRSTgaclCredSetNistLoa(cred, level) ((cred)->nist_loa = (level))
00265 #define GRSTgaclCredGetNistLoa(cred) ((cred)->nist_loa)
00266 
00267 /* #define GACLfreeCred(x)              GRSTgaclCredFree((x)) */
00268 int        GRSTgaclCredFree(GRSTgaclCred *);
00269 
00270 /*  #define GACLaddCred(x,y)    GRSTgaclEntryAddCred((x),(y)) */
00271 int        GRSTgaclEntryAddCred(GRSTgaclEntry *, GRSTgaclCred *);
00272 
00273 /*  #define GACLdelCred(x,y)    GRSTgaclEntryDelCred((x),(y)) */
00274 int        GRSTgaclEntryDelCred(GRSTgaclEntry *, GRSTgaclCred *);
00275 
00276 /*  #define GACLprintCred(x,y)  GRSTgaclCredPrint((x),(y)) */
00277 int        GRSTgaclCredCredPrint(GRSTgaclCred *, FILE *);
00278 
00279 int        GRSTgaclCredCmpAuri(GRSTgaclCred *, GRSTgaclCred *);
00280 
00281 /*  #define GACLnewEntry(x)             GRSTgaclEntryNew((x)) */
00282 GRSTgaclEntry *GRSTgaclEntryNew(void);
00283 
00284 /*  #define GACLfreeEntry(x)    GRSTgaclEntryFree((x)) */
00285 int        GRSTgaclEntryFree(GRSTgaclEntry *);
00286 
00287 /*  #define GACLaddEntry(x,y)   GRSTgaclAclAddEntry((x),(y)) */
00288 int        GRSTgaclAclAddEntry(GRSTgaclAcl *, GRSTgaclEntry *);
00289 
00290 /*  #define GACLprintEntry(x,y) GRSTgaclEntryPrint((x),(y)) */
00291 int        GRSTgaclEntryPrint(GRSTgaclEntry *, FILE *);
00292 
00293 
00294 /*  #define GACLprintPerm(x,y)  GRSTgaclPermPrint((x),(y)) */
00295 int        GRSTgaclPermPrint(GRSTgaclPerm, FILE *);
00296 
00297 /*  #define GACLallowPerm(x,y)  GRSTgaclEntryAllowPerm((x),(y)) */
00298 int        GRSTgaclEntryAllowPerm(GRSTgaclEntry *, GRSTgaclPerm);
00299 
00300 /*  #define GACLunallowPerm(x,y)        GRSTgaclEntryUnallowPerm((x),(y)) */
00301 int        GRSTgaclEntryUnallowPerm(GRSTgaclEntry *, GRSTgaclPerm);
00302 
00303 /*  #define GACLdenyPerm(x,y)   GRSTgaclEntryDenyPerm((x),(y)) */
00304 int        GRSTgaclEntryDenyPerm(GRSTgaclEntry *, GRSTgaclPerm);
00305 
00306 /*  #define GACLundenyPerm(x,y) GRSTgaclEntryUndenyPerm((x),(y)) */
00307 int        GRSTgaclEntryUndenyPerm(GRSTgaclEntry *, GRSTgaclPerm);
00308 
00309 /*  #define GACLpermToChar(x)   GRSTgaclPermToChar((x)) */
00310 char      *GRSTgaclPermToChar(GRSTgaclPerm);
00311 
00312 /*  #define GACLcharToPerm(x)   GRSTgaclPermFromChar((x)) */
00313 GRSTgaclPerm   GRSTgaclPermFromChar(char *);
00314 
00315 /*  #define GACLnewAcl(x)               GRSTgaclAclNew((x)) */
00316 GRSTgaclAcl   *GRSTgaclAclNew(void);
00317 
00318 /*  #define GACLfreeAcl(x)              GRSTgaclAclFree((x)) */
00319 int        GRSTgaclAclFree(GRSTgaclAcl *);
00320 
00321 /*  #define GACLprintAcl(x,y)   GRSTgaclAclPrint((x),(y)) */
00322 int        GRSTgaclAclPrint(GRSTgaclAcl *, FILE *);
00323 
00324 /*  #define GACLsaveAcl(x,y)    GRSTgaclAclSave((y),(x)) */
00325 int        GRSTgaclAclSave(GRSTgaclAcl *, char *);
00326 
00327 /*  #define GACLloadAcl(x)              GRSTgaclFileLoadAcl((x)) */
00328 GRSTgaclAcl   *GRSTgaclAclLoadFile(char *);
00329 
00330 /*  #define GACLfindAclForFile(x)       GRSTgaclFileFindAclname((x)) */
00331 char      *GRSTgaclFileFindAclname(char *);
00332 
00333 /*  #define GACLloadAclForFile(x)       GRSTgaclFileLoadAcl((x)) */
00334 GRSTgaclAcl   *GRSTgaclAclLoadforFile(char *);
00335 
00336 /*  #define GACLisAclFile(x)    GRSTgaclFileIsAcl((x)) */
00337 int        GRSTgaclFileIsAcl(char *);
00338 
00339 
00340 /*  #define GACLnewUser(x)              GRSTgaclUserNew((x)) */
00341 GRSTgaclUser *GRSTgaclUserNew(GRSTgaclCred *);
00342 
00343 /*  #define GACLfreeUser(x)             GRSTgaclUserFree((x)) */
00344 int       GRSTgaclUserFree(GRSTgaclUser *);
00345 
00346 /*  #define GACLuserAddCred(x,y)        GRSTgaclUserAddCred((x),(y)) */
00347 int       GRSTgaclUserAddCred(GRSTgaclUser *, GRSTgaclCred *);
00348 
00349 /*  #define GACLuserHasCred(x,y)        GRSTgaclUserHasCred((x),(y)) */
00350 int       GRSTgaclUserHasCred(GRSTgaclUser *, GRSTgaclCred *);
00351 
00352 __attribute__ ((deprecated))
00353 int       GRSTgaclUserSetDNlists(GRSTgaclUser *, char *);
00354 
00355 int       GRSTgaclUserLoadDNlists(GRSTgaclUser *, char *);
00356 
00357 /*  #define GACLuserFindCredType(x,y) GRSTgaclUserFindCredtype((x),(y)) */
00358 GRSTgaclCred *GRSTgaclUserFindCredtype(GRSTgaclUser *, char *);
00359 
00360 __attribute__ ((deprecated))
00361 int GRSTgaclDNlistHasUser(char *, GRSTgaclUser *);
00362 
00363 int GRSTgaclUserHasAURI(GRSTgaclUser *, char *);
00364 
00365 /*  #define GACLtestUserAcl(x,y)        GRSTgaclAclTestUser((x),(y)) */
00366 GRSTgaclPerm   GRSTgaclAclTestUser(GRSTgaclAcl *, GRSTgaclUser *);
00367 
00368 /*  #define GACLtestExclAcl(x,y)        GRSTgaclAclTestexclUser((x),(y)) */
00369 GRSTgaclPerm   GRSTgaclAclTestexclUser(GRSTgaclAcl *, GRSTgaclUser *);
00370 
00371 char      *GRSThttpUrlDecode(char *);
00372 
00373 /*  #define GACLurlEncode(x)    GRSThttpUrlEncode((x)) */
00374 char      *GRSThttpUrlEncode(char *);
00375 
00376 /*  #define GACLmildUrlEncode(x)        GRSThttpMildUrlEncode((x)) */
00377 char      *GRSThttpUrlMildencode(char *);
00378 
00379 int GRSTx509NameCmp(char *, char *);
00380 
00381 #ifndef GRST_NO_OPENSSL
00382 int GRSTx509KnownCriticalExts(X509 *);
00383 
00384 int GRSTx509IsCA(X509 *);
00385 int GRSTx509CheckChain(int *, X509_STORE_CTX *);
00386 int GRSTx509VerifyCallback(int, X509_STORE_CTX *);
00387 
00388 __attribute__ ((deprecated))
00389 int GRSTx509GetVomsCreds(int *, int, size_t, char *, X509 *, STACK_OF(X509) *, char *);
00390 
00391 __attribute__ ((deprecated))
00392 GRSTgaclCred *GRSTx509CompactToCred(char *);
00393 
00394 __attribute__ ((deprecated))
00395 int GRSTx509CompactCreds(int *, int, size_t, char *, STACK_OF(X509) *, char *, X509 *);
00396 #endif 
00397 
00398 char *GRSTx509CachedProxyFind(char *, char *, char *);
00399 char *GRSTx509FindProxyFileName(void);
00400 int GRSTx509MakeProxyCert(char **, FILE *, char *, char *, char *, int);
00401 char *GRSTx509CachedProxyKeyFind(char *, char *, char *);
00402 int GRSTx509ProxyDestroy(char *, char *, char *);
00403 int GRSTx509ProxyGetTimes(char *, char *, char *, time_t *, time_t *);
00404 int GRSTx509CreateProxyRequest(char **, char **, char *);
00405 int GRSTx509MakeProxyRequest(char **, char *, char *, char *);
00406 
00407 char *GRSTx509MakeDelegationID(void);
00408 
00409 #ifndef GRST_NO_OPENSSL
00410 int GRSTx509StringToChain(STACK_OF(X509) **, char *);
00411 char *GRSTx509MakeProxyFileName(char *, STACK_OF(X509) *);
00412 #endif
00413 
00414 int GRSTx509CacheProxy(char *, char *, char *, char *);
00415 
00416 #define GRST_HEADFILE   "gridsitehead.txt"
00417 #define GRST_FOOTFILE   "gridsitefoot.txt"
00418 #define GRST_ADMIN_FILE "gridsite-admin.cgi"
00419 
00420 typedef struct { char *text;
00421                  void *next; } GRSThttpCharsList;
00422 
00423 typedef struct { size_t             size;
00424                  GRSThttpCharsList *first;
00425                  GRSThttpCharsList *last;  } GRSThttpBody;
00426 
00427 void  GRSThttpBodyInit(GRSThttpBody *); 
00428 void  GRSThttpPrintf(GRSThttpBody *, char *, ...);
00429 int   GRSThttpCopy(GRSThttpBody *, char *);
00430 void  GRSThttpWriteOut(GRSThttpBody *);
00431 int   GRSThttpPrintHeaderFooter(GRSThttpBody *, char *, char *);
00432 int   GRSThttpPrintHeader(GRSThttpBody *, char *);
00433 int   GRSThttpPrintFooter(GRSThttpBody *, char *);
00434 char *GRSThttpGetCGI(char *);
00435 
00436 time_t GRSTasn1TimeToTimeT(char *, size_t);
00437 int    GRSTasn1SearchTaglist(struct GRSTasn1TagList taglist[], int, char *);
00438 #ifndef GRST_NO_OPENSSL
00439 int    GRSTasn1ParseDump(BIO *, unsigned char *, long,
00440                          struct GRSTasn1TagList taglist[], int, int *);
00441 #endif
00442 int    GRSTasn1GetX509Name(char *, int, char *, char *,
00443                            struct GRSTasn1TagList taglist[], int);
00444 
00445 int    GRSThtcpNOPrequestMake(char **, int *, unsigned int);
00446 int    GRSThtcpNOPresponseMake(char **, int *, unsigned int);
00447 int    GRSThtcpTSTrequestMake(char **, int *, unsigned int, char *, char *, char *);
00448 int    GRSThtcpTSTresponseMake(char **, int *, unsigned int, char *, char *, char *);
00449 int    GRSThtcpMessageParse(GRSThtcpMessage *, char *, int);
00450 
00451 #ifndef GRST_PASSCODE_JS
00452 //#define __GRST_PASSCODE_JS__
00453 #define GRST_PASSCODE_JS "<script type=\"text/javascript\" language=\"Javascript\"><!--\nfunction changeValue(formName){        if( document.forms[formName].passcode.value==\"\" ) document.forms[formName].passcode.value=getCookie(\"GRIDHTTP_PASSCODE\");       return true;   } \nfunction getCookie(c_name){ if (document.cookie.length>0)  {  c_start=document.cookie.indexOf(c_name + \"=\");  if (c_start!=-1)    {    c_start=c_start + c_name.length+1;    c_end=document.cookie.indexOf(\";\",c_start);    if (c_end==-1) c_end=document.cookie.length;    return unescape(document.cookie.substring(c_start,c_end)); }} return \"\"; } \n -->\n</script>"
00454 #endif
00455 
00456 #ifdef __cplusplus
00457 } // extern "C"
00458 #endif
00459 
00460 #endif // GRST_VERSION
00461