Tag Archives: racf

CICS Access to RACF, Part 2

I admit that I’m a little overdue to post this follow-up to my post about accessing RACF info from a COBOL program in CICS. But when I posted it, I had no idea that was going to be the single most viewed entry on my blog site. So I’ve finally had enough people asking about the teaser with which I ended that post, promising to show how to access the list of groups to which the user is connected, that I’ve been shamed into following thr0ugh. The latest episode of “One Way Out” has ended, so it’s time to quit goofing off and meet that obligation …

Some of this will be a repeat of my original post, but I’ll quickly cover those things so new blogees won’t necessarily have to chase it down. First, to access the ACEE (the RACF control block that has so much RACF info on the user), we’ll need a pointer defined in working storage to point to the control block – something like this:

77  WS-ACEE-ADDR-POINTER USAGE IS POINTER.

And, while we are defining things in working storage, let’s set up a table to contain the groups to which our CICS user is connected:

01  GROUPS-AREA.
    05 WS-GROUPS PIC X(8 ) OCCURS 10 TIMES.

The occurs number is arbitrary. I picked 10 because that would seem to be large enough to cover the list of groups for most users, but if your shop uses groups more extensively, perhaps not. Code a bigger value, or devise a much more clever scheme … I’m not going to spend time on it because that’s not important for what I’m showing here.

We’ll also need somewhere to count the groups as we find them:

77  WS-GROUP-CNT PIC S9(4) COMP VALUE 1.

The IBM-provided record layout for the ACEE is in SYS1.MACLIB(IHQAACEE). But we are not interested in every field listed, so let’s dumb-down the record layout into a data structure in the linkage section, replacing what we are not interested in with FILLER, like this:

01 ACEE.
   05 FILLER PIC   X(021).
   05 ACEEUSRI PIC X(008).
   05 FILLER PIC   X(001).
   05 ACEEGRPN PIC X(008).
   05 FILLER PIC   X(062).
   05 ACEEUNAM-POINTER USAGE IS POINTER.
   05 FILLER PIC   X(012).
   05 ACEECGRP-POINTER USAGE IS POINTER.

There are a couple of pointers in that data structure … We saw in my original post that the first one points to an area of storage containing the user name (as defined in RACF). We’ll ignore it, as we are only interested in the second one at this time – it points to our list of groups, which we will define with the following data structure in the linkage section:

01 ACEE-GROUP-TABLE.
   05 FILLER   PIC X(008).
   05 CGRPNUM  PIC S9(4) COMP.
   05 FILLER   PIC X(022).
   05 CGRPENT  OCCURS 10 TIMES DEPENDING ON CGRPNUM.
      10 CGRPNAME PIC X(008).
      10 FILLER   PIC X(016).

CGRPNUM is going to contain the number of entries in this list. I chose to have it occur up to 10 times because that was the arbitrary value I chose in my table to contain the groups in working storage.

So much for the data definitions – let’s now go get the data! In the procedure division, we’ll need to use the CICS API that allows us to address the ACEE:

EXEC CICS ADDRESS ACEE (WS-ACEE-ADDR-POINTER)
END-EXEC.

Now that we have the address of the ACEE, we can now access that control block, and once we have it, we can access the list of groups, just by setting pointers:

SET ADDRESS OF ACEE TO WS-ACEE-ADDR-POINTER.
SET ADDRESS OF ACEE-GROUP-TABLE TO ACEECGRP-POINTER.

All that’s left to do is run the list, getting our groups:

PERFORM 200-GET-GROUP THROUGH 200-EXIT
UNTIL WS-GROUP-CNT IS GREATER THAN CGRPNUM
OR    WS-GROUP-CNT IS GREATER THAN 10.

That defines our loop (again, with my arbitrary limit of 10), so now let’s set up what gets done in the loop – move the value from the control block to our working storage table and increment to point to the next group:

200-GET-GROUP.
    MOVE CGRPNAME (WS-GROUP-CNT) TO WS-GROUPS (WS-GROUP-CNT).
    ADD 1 TO WS-GROUP-CNT.
200-EXIT.

That is it! Like on our first example, the COBOL coding is not the hard part … The only hard part is knowing where the information is – and I hope I have helped exposed that with these examples. Browse through the assembler definition of the ACEE – you may see some other information that can help you get a job done!

CICS Access to RACF

CICS doesn’t supply much  access directly to RACF info via the API. But there is a supported way to obtain a lot of RACF information about the current user. And it can be done in plain ol’ COBOL.

EXEC CICS ADDRESS ACEE will provide access to the RACF ACEE control block. (ACEE stands for Access Control Environment Element. Maybe it will come up in a trivia question some day. Probably not. The important thing to know is that it is a block of storage containing RACF information which can be addressed from application programs.) From there, it is possible to easily obtain the user’s primary RACF group and the user’s name (as it is recorded in RACF).

The layout of the ACEE control block is documented in SYS1.MACLIB(IHAACEE). Unfortunately, there is not a COBOL copybook provided, so to access this information in a COBOL program, we have to code our own storage definitions. The following are based on SYS1.MACLIB(IHAACEE):

01 ACEE.
   05 FILLER PIC    X(021).
   05 ACEEUSRI PIC  X(008).
   05 FILLER PIC    X(001).
   05 ACEEGRPN PIC  X(008).
   05 FILLER PIC    X(062).
   05 ACEEUNAM-POINTER USAGE IS  POINTER.
01  ACEE-USER-NAME.
   05 FILLER PIC    X(001).
   05 ACEEUNAM PIC  X(020).

And we need a piece of miscellaneous working storage to hold a pointer:

77  WS-ACEE-ADDR-POINTER USAGE IS  POINTER.

Now, if we execute the following, we’ll have the address of the ACEE control block in that pointer:

EXEC CICS
ADDRESS ACEE  (WS-ACEE-ADDR-POINTER)
END-EXEC.

And then the following commands will make the RACF information addressable by our storage definitions:

SET ADDRESS OF ACEE TO WS-ACEE-ADDR-POINTER.
SET ADDRESS OF ACEE-USER-NAME TO ACEEUNAM-POINTER.

Now we have the user’s RACF id in ACEEUSRI, the user’s primary RACF group in ACEEGRPN, and the user’s name in ACEEUNAM. Very simple – just a matter of knowing how to address the information.

In a future post, we’ll continue this and see how we can obtain all of the RACF groups to which the user’s RACF id is connected.