/* * C wrapper functions for VMS persona services (6.2 or higher). The * persona_authenticate routine validates the username against the SYSUAF * using the password. * * typedef long persona; * * int persona_authenticate ( char *user, char *pwd, persona *pers ); * int persona_create ( char *user, persona *pers ); * int persona_assume ( persona * ); * int persona_revert ( ); * int persona_delete ( persona * ); * * Author: David Jones * Date: 31-May-1998 */ #include /* VMS ipersonate services */ #include /* VMS string descriptors */ #include /* VMS user auth. info. */ #include #include #include #include #include #include #include int SYS$PERSONA_CREATE(), SYS$PERSONA_ASSUME(), SYS$PERSONA_DELETE(); int SYS$HASH_PASSWORD(), SYS$GETUAI(), SYS$SCAN_INTRUSION(); #define PRV$M_SECURITY 64 #ifdef VAXC globalref int secsrv$_intruder; #else extern int secsrv$_intruder; #endif #include "persona.h" /* verify prototypes */ typedef struct { short length, code; char *buffer; int *ret_len; } item_list; int persona_create ( char *username, persona *new_persona ) { char compare_string[36]; int status, i, match; struct dsc$descriptor username_dx; /* * Upcase the string. */ for ( i = 0; i < sizeof(compare_string)-1; i++ ) { if ( !username[i] ) break; compare_string[i] = toupper(username[i]); } compare_string[i] = '\0'; /* * Build string descriptor and make system service call. */ username_dx.dsc$a_pointer = compare_string; username_dx.dsc$w_length = i; status = SYS$PERSONA_CREATE ( new_persona, &username_dx, 0); return status; } /************************************************************************/ int persona_assume ( persona *target_persona ) { int status, flags; flags = IMP$M_ASSUME_SECURITY; status = SYS$PERSONA_ASSUME ( target_persona, flags ); return status; } /************************************************************************/ int persona_delete ( persona *target_persona ) { int status; status = SYS$PERSONA_DELETE ( target_persona ); return status; } /***************************************************************************/ int persona_revert ( ) { int status; static persona original_persona; original_persona = 1; return persona_assume ( &original_persona ); } /***************************************************************************/ /* Scan intrustion database, return 0 if login should be denied, or original * login status (success or failure) if no matching intrusion data. */ static int scan_intrusion ( int login_status, int username_valid, struct dsc$descriptor_s *username ) { int status, flags, len; static $DESCRIPTOR(default_user,"INVALID"); $DESCRIPTOR(remote_node_dx, ""); struct dsc$descriptor_s *source_user; /* * Check that process has SECURITY privilege, do null operation if not. */ /* if ( (PRV$M_SECURITY&cur_privs[1]) == 0 ) return login_status; */ /* * Determine source user string to use for scan, use "INVALID" if * username not valid. */ source_user = &default_user; if ( username_valid ) source_user = username; /* * Build descriptors and call system service to do intrusion DB scan. */ remote_node_dx.dsc$w_length = 10; remote_node_dx.dsc$a_pointer = "WEB_SCRIPT"; flags = (username_valid) ? CIA$M_REAL_USERNAME : 0; status = SYS$SCAN_INTRUSION ( login_status, username, JPI$K_REMOTE, 0, &remote_node_dx, source_user, 0, 0, 0, 0, flags ); /* * Fail request if intruder detected, otherwise return original * login status. */ if ( status == (int) &secsrv$_intruder ) return 0; return (1&login_status); } /***************************************************************************/ int persona_authenticate ( char *user, char *pwd, persona *new_persona ) { item_list item[10]; int i, flags, alg, salt, status; long uic, hash[2], test_hash[2]; struct dsc$descriptor_s user_dx, pwd_dx; char username[40], password[32]; /* * make descriptors, upcase username and password. */ user_dx.dsc$b_dtype = user_dx.dsc$b_class = 0; for ( i = 0; i < sizeof(username); i++ ) { if ( !user[i] ) break; username[i] = toupper(user[i]); } user_dx.dsc$w_length = i; user_dx.dsc$a_pointer = username; pwd_dx.dsc$b_dtype = pwd_dx.dsc$b_class = 0; for ( i = 0; i < sizeof(password); i++ ) { if ( !pwd[i] ) break; password[i] = toupper(pwd[i]); } pwd_dx.dsc$w_length = i; pwd_dx.dsc$a_pointer = password; /* * Lookup user information needed to test password. */ item[0].code = UAI$_FLAGS; item[0].length = sizeof(flags); item[0].buffer = (char *) &flags; item[0].ret_len = (int *) 0; item[1].code = UAI$_PWD; item[1].length = 8; item[1].buffer = (char *) hash; item[1].ret_len = (int *) 0; hash[0] = 0; hash[1] = 0; item[2].code = UAI$_SALT; item[2].length = 2; item[2].buffer = (char *) &salt; item[2].ret_len = (int *) 0; salt = 0; item[3].code = UAI$_UIC; item[3].length = sizeof(int); item[3].buffer = (char *) &uic; item[3].ret_len = (int *) 0; item[4].code = UAI$_ENCRYPT; item[4].length = 1; item[4].buffer = (char *) &alg; item[4].ret_len = (int *) 0; alg = 0; item[5].code = 0; item[5].length = 0; /* terminate list */ status = SYS$GETUAI ( 0, 0, &user_dx, item, 0, 0, 0 ); if ( (status&1) == 0 ) return status; /* * Hash password and compare. */ status = SYS$HASH_PASSWORD ( &pwd_dx, alg, salt, &user_dx, test_hash ); if ( (status&1) == 0 ) return status; if ( ((flags&UAI$M_DISACNT) == 0) && (hash[0] == test_hash[0]) && (hash[1]==test_hash[1]) ) { /* * make sure not in intrusion database. */ status = scan_intrusion ( 1, 1, &user_dx ); /* * Password validated. */ status = persona_assume ( new_persona ); } else { /* * Add record to intrusion database. */ scan_intrusion ( 0, 1, &user_dx ); status = SS$_INVLOGIN; } return status; } #ifdef TEST_PROG int main ( int argc, char **argv ) { int status; persona target; if ( argc < 3 ) { printf("usage: persona user pwd\n"); exit(1); } status = persona_create ( argv[1], &target ); printf("Status of persona_create: %d, handle: %x\n", status, target ); if ( (status&1) == 0 ) return status; status = persona_authenticate ( argv[1], argv[2], &target ); printf("Status of persona_auth: %d\n", status ); persona_revert(); return status; } #endif