From: hoffman@xdelta.zko.dec.nospam Sent: Monday, June 03, 2002 9:44 PM To: Info-VAX@Mvb.Saic.Com Subject: Re: Creating ACEs from a program In article , cstranslations@msn.com (Joe) writes: :Trying to create an ACE entry on a file from a program (and not pass a :DCL SET SEC command through LIB$SPAWN). Looking at the fine manuals :and I'm thinking some calls to $PARSE_ACL, $SET_SECURITY, and maybe :$FORMAT_ACL are in order... :Must admit I'm finding the fine manuals a bit obtuse... :Anyone out there willing to share a simple example? OpenVMS version, platform, and language? There's a Fortran example available via the http://askq.compaq.com/ search tool, here are three examples of calling security-related OpenVMS system services from C -- use of a fairly recent C compiler is assumed by the comment syntax used in some of these examples: /* ** Copyright 2002 Compaq Information Technologies Group, L.P. */ #include #include #include #include #include #include #include #include #define MAXACE 256 main( int argc, char *argv[] ) { int RetStat; $DESCRIPTOR( AceBefore, "(IDENTIFIER=[SYSTEM],ACCESS=READ)"); char AceRawBuf[MAXACE]; char AceAfterBuf[MAXACE]; struct dsc$descriptor AceRaw = {MAXACE,DSC$K_DTYPE_T,DSC$K_CLASS_S,NULL}; struct dsc$descriptor AceAfter = {MAXACE,DSC$K_DTYPE_T,DSC$K_CLASS_S,NULL}; /* // Display the source... */ lib$put_output( &AceBefore ); AceRaw.dsc$a_pointer = (void *) AceRawBuf; AceAfter.dsc$a_pointer = (void *) AceAfterBuf; /* // convert the ACE from text to binary */ RetStat = sys$parse_acl( &AceBefore, &AceRaw, NULL, NULL, NULL ); if (!$VMS_STATUS_SUCCESS( RetStat )) lib$signal( RetStat ); /* // the first byte of the raw ACE contains the total ACE length */ AceRaw.dsc$w_length = AceRawBuf[0]; /* // convert the ACE from binary to text format... */ RetStat = sys$format_acl( &AceRaw, &AceAfter.dsc$w_length, &AceAfter, NULL, NULL, NULL, NULL, NULL ); if (!$VMS_STATUS_SUCCESS( RetStat )) lib$signal( RetStat ); /* // Display the results... */ lib$put_output( &AceAfter ); return SS$_NORMAL; } -- // // Copyright 2002 Compaq Information Technologies Group, L.P. // #include #include #include #include #include #include #include #define MAXACE 256 int main(int argc, char **argv ) { int RetStat; $DESCRIPTOR( AceText, "(AUDIT=SECURITY,ACCESS=DELETE+CONTROL+SUCCESS)"); struct dsc$descriptor AceBufferDesc; char AceBuffer[MAXACE]; char *AceAuditName; AceBufferDesc.dsc$w_length = MAXACE; AceBufferDesc.dsc$b_dtype = DSC$K_DTYPE_T; AceBufferDesc.dsc$b_class = DSC$K_CLASS_S; AceBufferDesc.dsc$a_pointer = AceBuffer; RetStat = sys$parse_acl( &AceText, &AceBufferDesc, 0, 0, 0 ); if (!$VMS_STATUS_SUCCESS( RetStat )) lib$signal( RetStat ); AceAuditName = ((struct acedef *)AceBuffer)->ace$t_auditname; printf("%16.16s\n", AceAuditName ); return SS$_NORMAL; } -- // // Copyright 2002 Compaq Information Technologies Group, L.P. // // // //++ // Facility: // // Examples // // Version: V1.3 // // Abstract: // // GBLSEC.C -- global section example code // // Creates a backing storage file, and maps a global section // into process virtual address space (twice), and then shows // basic section operations. // // Author: // Stephen Hoffman // // Creation Date: 2-Jan-1990 // // Modification History: // // Stephen Hoffman remove unused "stubs" // V1.1 27-Aug-1997 // Stephen Hoffman added sys$updsecw calls. // V1.2 07-Apr-1998 // Stephen Hoffman added $set_security, $dgblsc calls. // V1.3 17-Sep-1999 // // Build Instructions: // // $ CC/DECC/PREFIX=ALL GBLSEC // $ LINK GBLSEC // $ RUN GBLSEC // // // #include #include #include #include #include #include #include #include #include #include #include #include #define P0SPACE ((void*)0x0200) #define GBLSECMAX 10 #define MAXIL 10 struct SecStructDef { int GblSec[GBLSECMAX]; }; ChurnData( char *Lbl, struct SecStructDef *Base, int WriteFlag ) { int i; int RetStat; // Now read or write some data in the specified window... printf( "Global section <%s> base is located at %p\n", Lbl, Base ); if ( WriteFlag ) { printf( "Writing data into the global section ...\n" ); for ( i = 0; i < GBLSECMAX; i++) Base->GblSec[i] = i; } else { printf( "Reading data from the global section ...\n" ); for ( i = 0; i < GBLSECMAX; i++) printf( " %s->GblSec[%d] = %d\n", Lbl, i, Base->GblSec[i] ); } return SS$_NORMAL; } main() { int RetStat; $DESCRIPTOR( SecDsc, "FACNAM_GLOBAL_SECTION_NAME" ); $DESCRIPTOR( ClsDsc, "SYSTEM_GLOBAL_SECTION" ); int i; unsigned short int Iosb[4]; void *InAdr1[2] = {P0SPACE,P0SPACE}; void *RetAdr1[2] = {NULL,NULL}; void *InAdr2[2] = {P0SPACE,P0SPACE}; void *RetAdr2[2] = {NULL,NULL}; unsigned long int OwnerUIC = geteuid(); unsigned short int ProtMask = 0x0ff00; struct ItemList3 { short int ItemLength; short int ItemCode; void *ItemBuffer; void *ItemRetLen; } SetSecIL[MAXIL]; struct SecStructDef *Sec1, *Sec2; unsigned long int GblFlags; GblFlags = (SEC$M_EXPREG | SEC$M_GBL | SEC$M_SYSGBL | SEC$M_PAGFIL); // Create, zero, and map the global section... // Then overlay a structure (Sec1) onto the global section... RetStat = sys$crmpsc( InAdr1, RetAdr1, PSL$C_USER, GblFlags | SEC$M_DZRO, &SecDsc, 0, 0, 0, 1, 0, 0, 0 ); if (!$VMS_STATUS_SUCCESS( RetStat )) lib$signal( RetStat ); Sec1 = RetAdr1[0]; // map the global section. Again. // Then overlay a structure (Sec2) onto the global section... RetStat = sys$crmpsc( InAdr2, RetAdr2, PSL$C_USER, GblFlags, &SecDsc, 0, 0, 0, 1, 0, 0, 0 ); if (!$VMS_STATUS_SUCCESS( RetStat )) lib$signal( RetStat ); Sec2 = RetAdr2[0]; // Now write some data into one "window"... And then read the // data back in from the other "window". ChurnData( "Section1", Sec1, 1 ); ChurnData( "Section1", Sec1, 0 ); ChurnData( "Section2", Sec2, 0 ); // Now flush out the contents of the section to disk... Twice... // Once for each of the two address ranges that we currently have // mapped into the global section... RetStat = sys$updsecw( RetAdr1, NULL, PSL$C_USER, 0, 0, Iosb, NULL, NULL ); if (!$VMS_STATUS_SUCCESS( RetStat )) lib$signal( RetStat ); if (!$VMS_STATUS_SUCCESS( Iosb[0] )) lib$signal( Iosb[0] ); RetStat = sys$updsecw( RetAdr2, NULL, PSL$C_USER, 0, 0, Iosb, NULL, NULL ); if (!$VMS_STATUS_SUCCESS( RetStat )) lib$signal( RetStat ); if (!$VMS_STATUS_SUCCESS( Iosb[0] )) lib$signal( Iosb[0] ); // Reset the protection and the ownership... // // The sys$set_security service works with pagefile-backed // sections, but manipulation of file-backed sections is not // permitted. (You must unmap everything, reset the security // attributes on the backing file, then remap everything.) i = 0; SetSecIL[i].ItemLength = sizeof( int ); SetSecIL[i].ItemCode = OSS$_OWNER; SetSecIL[i].ItemBuffer = &OwnerUIC; SetSecIL[i++].ItemRetLen = NULL; SetSecIL[i].ItemLength = sizeof( short int ); SetSecIL[i].ItemCode = OSS$_PROTECTION; SetSecIL[i].ItemBuffer = &ProtMask; SetSecIL[i++].ItemRetLen = NULL; SetSecIL[i].ItemLength = 0; SetSecIL[i].ItemCode = 0; SetSecIL[i].ItemBuffer = NULL; SetSecIL[i++].ItemRetLen = NULL; RetStat = sys$set_security( &ClsDsc, &SecDsc, NULL, OSS$M_RELCTX, SetSecIL, 0, 0 ); if (!$VMS_STATUS_SUCCESS( RetStat )) lib$signal( RetStat ); // And redisplay the contents of the section, as was // maintained by the backing storage file... ChurnData( "Section2", Sec2, 0 ); // Now delete the section virtual address space ranges... RetStat = sys$deltva( RetAdr1, NULL, PSL$C_USER ); if (!$VMS_STATUS_SUCCESS( RetStat )) lib$signal( RetStat ); RetStat = sys$deltva( RetAdr2, NULL, PSL$C_USER ); if (!$VMS_STATUS_SUCCESS( RetStat )) lib$signal( RetStat ); // delete the global section... (If we need to...) if ( GblFlags & SEC$M_PERM ) { RetStat = sys$dgblsc( 0, &SecDsc, 0 ); if (!$VMS_STATUS_SUCCESS( RetStat )) lib$signal( RetStat ); } return SS$_NORMAL; } ---------------------------- #include ----------------------------- For additional, please see the OpenVMS FAQ -- www.openvms.compaq.com --------------------------- pure personal opinion --------------------------- Hoff (Stephen) Hoffman OpenVMS Engineering hoffman#xdelta.zko.dec.com