#pragma module RAD_EXT_AUTH2ORA "RAD_EXT_AUTH2ORA-1-X" /* **++ ** FACILITY: RADIUS-VMS ** ** MODULE DESCRIPTION: ** ** External module for performing authentication for RADIUS-VMS server, ** it is used as an standard RADIUS-VMS authentication. ** AUTHORS: ** ** Copyright © Ruslan R. Laishev 2000 ** ** CREATION DATE: 11-MAR-2000 ** ** DESIGN ISSUES: ** ** This module supposed to contains external user-written pocedures ** are called from RADIUS-VMS server. ** ** N.B. Since RADIUS-VMS server is a DEC Threads application, you should ** write thread safe code for the AUTHORIZE routine, using ** reenterancy or the syncronization technics. ** ** N.B. The INIT & CLEANUP routines is called when all auth-threads is not ran. ** ** N.B. RADIUS-VMS makes hardcoded references to event flags 19-22. ** ** To build this module (ALPHA): ** ** $CC/PREFFIX=ALL RAD_EXT_AUTH2ORA.C/REENTRANCY=MULTITHREAD - ** /INCLUDE=([],ORA_RDBMS,ORA_OCI_DEMO)/NOWARN ** ** $CREATE RAD_EXT_AUTH2ORA.OPT ** SYMBOL_VECTOR=(INIT=PROCEDURE,AUTHORIZE=PROCEDURE,CLEANUP=PROCEDURE) ** ** ** $@ORA_RDBMS:lnocic RAD_EXT_AUTH2ORA RAD_EXT_AUTH2ORA,RAD_EXT_AUTH2ORA.OPT/OPT i ** ** To build this module (VAX): ** $CC/PREFFIX=ALL RAD_EXT_AUTH2ORA.C - ** /INCLUDE=([],ORA_RDBMS,ORA_OCI_DEMO) ** $CREATE RAD_EXT_AUTH2ORA.OPT ** UNIVERSAL=INIT,AUTHORIZE,CLEANUP ** ** ** $@ORA_RDBMS:lnocic RAD_EXT_AUTH2ORA RAD_EXT_AUTH2ORA,RAD_EXT_AUTH2ORA.OPT/OPT i ** ** DEFINE/SYSTEM/EXEC ORALOGIN "scott/tiger" ** DEFINE/SYSTEM/EXEC RADIUS_EXT_AUTH dev:[dir]RAD_EXT_AUTH2ORA.EXE ** ** ORACLE stuff see in the RAD_EXT_AUTH2ORA.ORA_SQL ** ** Add entry into a RADIUS_USERS: ** DEFAULT3 Auth-Type = Extern ** ** MODIFICATION HISTORY: ** ** 19-MAR-2001 RRL Added a Calling/Called station ID(s), ** an account was removed. Added a passing of the realm. ** {@tbs@}... **-- */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __STDC__ #include #else #include #endif /* ** ** MACRO DEFINITIONS ** */ #define INIT_SDESC(dsc, len, ptr) {(dsc).dsc$b_dtype = DSC$K_DTYPE_T;\ (dsc).dsc$b_class = DSC$K_CLASS_S; (dsc).dsc$w_length = (short) (len);\ (dsc).dsc$a_pointer = (ptr);} #define NATIVE 1 #define VERSION_7 2 /* ** CONFIGURATION PARAMETERS, ORACLE GLOBAL VARIABLES */ static Lda_Def lda; static Cda_Def cda; static unsigned char hda[256]; static pthread_mutex_t ora_lockwr; unsigned char sql_init[] = "\ begin\ :retcode := radauth.init;\ end;"; unsigned char sql_authorize[] = "\ begin\ :retcode := radauth.authorize\ (:username,:client,:sess_tmo);\ end;"; unsigned char sql_cleanup[] = "\ begin\ :retcode := radauth.cleanup;\ end;"; /* **++ ** FUNCTIONAL DESCRIPTION: ** ** Put message to standard output device (SYS$OUTPUT), decode and append ** ORACLE OCI text of error message. ** ** FORMAL PARAMETERS: ** ** status: ** ORACLE OCI status code ** ** RETURN VALUE: ** ** None. ** ** **-- */ void ora_ocimsg ( int status ) { int len; char buf[1024]; len = oerhms(&lda, status, buf, sizeof (buf)); printf("%.*s\n",len,buf); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** Initializes the context used by this module. Opening ORACLE ** session, login. ** ** If you do not need to maintain any context between calls to your ** AUTHORIZE routines, it is OK to simply ** set the context pointer to NULL. If you do this, your CLEANUP ** routine will never be called. ** ** FORMAL PARAMETERS: ** ** context: address of a pointer to the allocated context ** ** RETURN VALUE: ** ** VMS condition value ** **-- */ int INIT (void **context) { int status = 0,retcode = 0; char oralogin[128]; oralogin[0] = '/'; oralogin[1] ='\0'; if ( getenv("ORALOGIN") ) strncpy(oralogin,getenv("ORALOGIN"),sizeof(oralogin)-1); /* ** Open session to ORACLE Server */ status = olog(&lda, hda, oralogin,-1, NULL,0,0,0, OCI_LM_DEF); /* ** Open context data area (cursor) , init treda-safe mode */ status = status?status:oopen(&cda, &lda,NULL, -1, -1,NULL, -1); status = status?status:opinit(OCI_EV_TSF); /* ** RADAUTH.INIT() */ status = status?status:oparse(&cda,sql_init,-1,0,VERSION_7); status = status?status:obndrv(&cda,":retcode",-1,&retcode, sizeof(int),SQLT_INT,-1,0,0,-1,-1); status = status?status:oexec(&cda); if ( status ) { ora_ocimsg(status); return SS$_ABORT; } #if __VMS_VER >= 70000000 if ( status = pthread_mutex_init(&ora_lockwr,NULL) ) #else if ( status = pthread_mutex_init(&ora_lockwr,pthread_mutexattr_default) ) #endif { printf("%s\n",strerror(status)); return SS$_ABORT; } /* ** Preparse RADAUTH.AUTHOIRIZE() */ if ( status = oparse(&cda,sql_authorize,-1,0,VERSION_7) ) { ora_ocimsg(status); return SS$_ABORT; } return SS$_NORMAL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** Performs an authorization of user with a given username/password pair ** ** FORMAL PARAMETERS: ** ** context: address of a pointer to the allocated context ** user: address of an username character string ** userlen: length of the username ** client: address of a client name ** clientlen: length of the client name ** sess_tmo: Session-Timeout in seconds ** pass: password string ** passlen: length of the password string ** called_id: Called-Station-Id string ** called_id_len: length of the Called-Station-Id string ** calling_id: Calling-Station-Id string ** calling_id_len: length of the Calling-Station-Id string ** realm: a realm string ** realmlen: a length of the realm string ** ** RETURN VALUE: ** sess_tmo: Session-Timeout value ** 1 = login is failed ** 0 = login was successful ** **-- */ int AUTHORIZE (void **context, char *user, short userlen, char *client, short clientlen, int *sess_tmo, char *pass, short passlen, char *called_id, short called_id_len, char *calling_id, short calling_id_len, char *realm, short realmlen ) { int status = 0,retcode = 0; /* ** Wait for condition, lock mutex */ if ( status = pthread_mutex_lock(&ora_lockwr) ) { printf("lockwr:%s\n",strerror(status)); return 1; } status = status?status:obndrv(&cda,":username",-1,user,userlen,SQLT_CHR,-1,0,0,-1,-1); status = status?status:obndrv(&cda,":client",-1,client, clientlen,SQLT_CHR,-1,0,0,-1,-1); status = status?status:obndrv(&cda,":sess_tmo",-1,sess_tmo, sizeof(int),SQLT_INT,-1,0,0,-1,-1); status = status?status:obndrv(&cda,":retcode",-1,&retcode, sizeof(int),SQLT_INT,-1,0,0,-1,-1); status = status?status:oexec(&cda); pthread_mutex_unlock(&ora_lockwr); if ( status ) ora_ocimsg(status); return ( status | retcode ); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** Cleans up the context allocated in the INIT routine. Not called ** if the INIT routine set the context to NULL. ** ** FORMAL PARAMETERS: ** ** context: address of a pointer to the allocated context ** ** RETURN VALUE: ** ** VMS condition code **-- */ int CLEANUP (void **context) { int status = 0,retcode = 0; /* ** RADAUTH.CLEANUP() */ status = status?status:oparse(&cda,sql_cleanup,-1,0,VERSION_7); status = status?status:obndrv(&cda,":retcode",-1, &retcode,sizeof(int),SQLT_INT,-1,0,0,-1,-1); status = status?status:oexec(&cda); if ( status ) ora_ocimsg(status); /* ** Destroy context , and logoff */ if ( status = oclose(&cda) ) ora_ocimsg(status); if ( status = ologof(&lda) ) ora_ocimsg(status); if ( status = pthread_mutex_destroy(&ora_lockwr) ) printf("%s\n",strerror(status)); return SS$_NORMAL; } #if 0 void main (void) { int status,tmo; void *context; if ( !(1 & (status = INIT (&context))) ) sys$exit(status); status = AUTHORIZE(&context, "SysOp",5, "SuperNAS",8,&tmo); if ( context && !(1 & (status = CLEANUP (&context))) ) sys$exit(status); } #endif