Document revision date: 15 July 2002 | |
![]() |
![]() ![]() ![]() ![]() |
![]() |
Previous | Contents | Index |
The following code illustrates what you might do within an application to ensure that the same user was still at the terminal. An example of reauthentication would be a check-writing application that requires reauthentication for any check over a certain value.
LOCAL STATUS, ACME_STATUS_BLOCK : VECTOR [4,LONG], NON_DIALOGUE_ITMLST : ALIAS_ON_AXP $ITMLST_DECL (ITEMS=1); ! ! Populate that item list ! $ITMLST_INIT(ITMLST = NON_DIALOGUE_ITMLST, ! ! What Password was given to this routine ? ! (ITMCOD = ACME$_PASSWORD_1, BUFSIZ = .INPUT_STRING [DSC$W_LENGTH], BUFADR = .INPUT_STRING [DSC$A_POINTER] ) ); ! ! Now call the System Service ! STATUS = $ACMW (EFN=EFN$C_ENF, FUNC=ACME$_FC_AUTHENTICATE_PRINCIPAL +ACME$M_DEFAULT_PRINCIPAL, ITMLST=NON_DIALOGUE_ITMLST, ACMSB=ACME_STATUS_BLOCK ); |
The following example is a slight variant on the example in Section 33.5.1:
LOCAL STATUS, OLD_PERSONA, NEW_PERSONA, ACME_STATUS_BLOCK : VECTOR [4,LONG], NON_DIALOGUE_ITMLST : ALIAS_ON_AXP $ITMLST_DECL (ITEMS=3); ! ! Populate that item list ! $ITMLST_INIT(ITMLST = NON_DIALOGUE_ITMLST, ! ! What is the Principal Name ! (ITMCOD = ACME$_PRINCIPAL_NAME_IN, BUFSIZ = %CHARCOUNT('JENKINS'), BUFADR = UPLIT BYTE('JENKINS')), ! ! What Password was given to this routine ? ! (ITMCOD = ACME$_PASSWORD_1, BUFSIZ = .INPUT_STRING [DSC$W_LENGTH], BUFADR = .INPUT_STRING [DSC$A_POINTER] ) ), ! ! Where do we want the new Persona ID ? ! (ITMCOD = ACME$_PERSONA_HANDLE_OUT, BUFADR = NEW_PERSONA ) ); ! ! Now call the System Service ! STATUS = $ACMW (EFN=EFN$C_ENF, FUNC=ACME$_FC_AUTHENTICATE_PRINCIPAL +ACME$M_ACQUIRE_CREDENTIALS, ITMLST=NON_DIALOGUE_ITMLST, ACMSB=ACME_STATUS_BLOCK ); CHECK_STATUS ( .STATUS ); CHECK_ACME_STATUS ( ACME_STATUS_BLOCK ); ! ! Now assume the new Persona ! STATUS = $PERSONA_ASSUME (PERSONA=NEW_PERSONA, FLAGS=0, previous=OLD_PERSONA); ! |
This example does not use item code ACME$_PERSONA_HANDLE_IN.
That is for manipulating the characteristics of an existing
persona, which is not the objective of this example.
33.5.6 Using CREPRC on Behalf of a User
After authentication, you can use the SYS$ACM[W] system service to create a process on behalf of the user, with process quotas set according the values in SYSUAF, as in the following example:
LOCAL STATUS, OLD_PERSONA, NEW_PERSONA, PIDADR, CREPRC_QUOTA : VECTOR [255,BYTE], ! hopefully long enough ACME_STATUS_BLOCK : VECTOR [4,LONG], NON_DIALOGUE_ITMLST : ALIAS_ON_AXP $ITMLST_DECL (ITEMS=4); ! ! Populate that item list ! $ITMLST_INIT(ITMLST = NON_DIALOGUE_ITMLST, ! ! What is the Principal Name ! (ITMCOD = ACME$_PRINCIPAL_NAME_IN, BUFSIZ = %CHARCOUNT('JENKINS'), BUFADR = UPLIT BYTE('JENKINS')), ! ! What Password was given to this routine ? ! (ITMCOD = ACME$_PASSWORD_1, BUFSIZ = .INPUT_STRING [DSC$W_LENGTH], BUFADR = .INPUT_STRING [DSC$A_POINTER] ) ), ! ! Where do we want the new persona ID? ! (ITMCOD = ACME$_PERSONA_HANDLE_OUT, BUFADR = NEW_PERSONA), ! ! Where do we want quota requirements stored ? ! (ITMCOD = ACMEVMS$_CREPRC_QUOTA, BUFSIZ = %ALLOCATION(CREPRC_QUOTA), BUFADR = CREPRC_QUOTA ) ); ! ! Now call the System Service ! STATUS = $ACMW (EFN=EFN$C_ENF, FUNC=ACME$_FC_AUTHENTICATE_PRINCIPAL, ITMLST=NON_DIALOGUE_ITMLST, ACMSB=ACME_STATUS_BLOCK ); CHECK_STATUS ( .STATUS ); CHECK_ACME_STATUS ( ACME_STATUS_BLOCK ); ! ! That routine just detected any buffer too short error ! ! Temporarily assume the new Persona ! STATUS = $PERSONA_ASSUME (PERSONA=NEW_PERSONA, FLAGS=0, previous=OLD_PERSONA); CHECK_STATUS ( .STATUS ); ! ! Now create the process under that persona ! STATUS = $CREPRC (PIDADR=PIDADR, IMAGE=$DESCRIPTOR('SYS$SYSTEM:LOGINOUT'), INPUT=$DESCRIPTOR('TXA3:'), OUTPUT=$DESCRIPTOR('TXA3:'), ERROR=$DESCRIPTOR('TXA3:'), QUOTA=CREPRC_QUOTA, STSFLG=PRC$M_NOUAF+PRC$M_INHERIT_PERSONA); CHECK_STATUS ( .STATUS ); ! ! Revert to our old Persona ! STATUS = $PERSONA_ASSUME (PERSONA=OLD_PERSONA); CHECK_STATUS ( .STATUS ); ! ! Delete the new persona from this process ! STATUS = $PERSONA_DELETE (PERSONA=NEW_PERSONA ); CHECK_STATUS ( .STATUS ); ! |
The PRC$M_NOUAF flag prevents LOGINOUT from modifying process quotas,
while the PRC$M_INHERIT_PERSONA prevents LOGINOUT from modifying the
process persona,
allowing use of the persona (and persona extensions) of the parent
process. The main purpose of LOGINOUT in this case becomes setting up
the DCL environment.
33.6 Authentication Examples
This section provides two complete examples of using the SYS$ACM[W] system service. In addition to these examples, a utility program called ACMEUTIL is available for issuing authentication and change-password SYS$ACM system service calls and examining the results in both dialogue and nondialogue mode.
You interact with the ACMEUTIL utility using the DCL interface. For example, to issue a dialogue request for authentication, use the following syntax:
$acme auth/dial=(input,noecho) |
See the comments in ACMEUTIL_SETUP.COM for additional information on ACMEUTIL DCL syntax and capabilities.
ACMEUTIL is located in the SYS$EXAMPLES directory and is built by
running the ACMEUTIL.COM procedure. To define the DCL verb ACMEUTIL,
run the ACMEUTIL_SETUP.COM procedure.
33.6.1 Example Using Nondialogue Mode (C)
This theoretical example supports a hardware badge reader and provides all necessary authentication information with a single call to the SYS$ACM[W] system service. The simple linear programming style used here would also be appropriate for a situation in which that authentication information is received from a network connection using a fixed protocol that does not allow queries back to the originator.
Line | Activity | Special Notes |
---|---|---|
45 | Declare local storage | This subroutine avoids static storage. |
105 | Determine MAXBUF | MAXBUF limits hardware interaction. |
105 | Determine MAXBUF | MAXBUF limits hardware interaction. |
158 | Prepare a SYS$ACM item list | We will add data as we go. |
210 | Prepare to use the badge reader | Subsequent steps use it. |
233 | Compare DNA | Invoking a hardware function. |
264 | Read the principal name | Data from the badge reader. |
298 | Read the primary password | Data from the badge reader. |
324 | Read the secondary password | Data from the badge reader. |
357 | Free the badge reader | We do not know when image will exit. |
372 | Call SYS$ACMW | Here is where we authenticate. |
389 | Return status to our caller | We choose to provide no details. |
1 #pragma module ACM_BADGE "V1.0" 2 /* 3 ** ACM_BADGE.C 4 */ 5 #define __NEW_STARLET 1 6 7 #include <string> // NULL and memset 8 #include <starlet.h> // for calling SYS$ACM 9 #include <iledef.h> // Item Lists 10 #include <iodef.h> // for calling $QIO 11 #include <iosbdef.h> // IO status blocks 12 #include <stsdef> // decoding status code fields 13 #include <efndef> // For event flag number definitions 14 #include <descrip.h> // for descriptor definitions 15 #include <utcblkdef.h> // required for acmedef.h 16 #include <acmedef.h> // ACME codes 17 #include <syidef.h> // GETSYI codes 18 19 /* 20 ** ACM_BADGE 21 ** 22 ** This subroutine obtains a user name and password from a 23 ** hardware badge reader and passes them in a nondialogue call to 24 ** SYS$ACM for evaluation. It returns success or failure status 25 ** to its caller. 26 ** 27 ** Obviously the hardware badge reader construction must be secure 28 ** enough to never divulge the password without validating a DNA 29 ** sample from the person who places the badge in the reader, 30 ** and that is why this is just a code sample in SYS$EXAMPLES: 31 ** rather than something that comes with a real hardware product. 32 ** 33 ** Arguments: 34 ** 35 ** None. 36 ** 37 ** Return values: 38 ** 39 ** ACME$_NORMAL - authentic 40 ** ACME$_AUTHFAILURE - not authentic 41 ** anything else - processing failure 42 */ 43 int ACM_BADGE() 44 { 45 int RetStatus; 46 int DasStatus; 47 char devnam[5]="BRA0:"; 48 struct dsc$descriptor_s devnam_desc = { 0, // length 49 DSC$K_DTYPE_T, // type 50 DSC$K_CLASS_S, // class 51 0}; // buf address 52 IOSB iosb; 53 ACMESB acmsb; 54 unsigned short int badge_reader_channel; 55 int logon_type = ACME$K_NETWORK; 56 int maxbuf; 57 int read_size; 58 59 /* 60 ** We will call SYS$ACM with multiple entries in an item list. 61 */ 62 enum acm_items 63 { 64 acm_logon_type, 65 acm_principal_name_in, 66 acm_password_1, 67 acm_password_2, 68 acm_terminator 69 }; 70 ILE3 acm_itmlst[acm_terminator+1]; 71 enum getsyi_items 72 { 73 getsyi_maxbuf, 74 getsyi_terminator 75 }; 76 ILE3 getsyi_itmlst[getsyi_terminator+1]; 77 78 /* 79 ** Our badge reader might provide very long input items, 80 ** because a user does not have to type them. Internally 81 ** the items will be carried in Unicode format, so the 82 ** length limit imposed by the 16-bit length field is 83 ** 1/4 of what one might first expect. 84 ** 85 ** Internal limits on the size of a single SYS$ACM request 86 ** actually constrain the total of all items to this size, 87 ** but we cannot predict how imbalanced the item lengths 88 ** will be, so we make all buffers be this maximum size. 89 ** 90 ** Depending on the value of system parameter MAXBUF, this 91 ** subroutine may try to read as many as buffer_size bytes 92 ** from the badge reader, so the Buffered IO Byte Limit 93 ** quota should be as large as buffer_size if the badge 94 ** reader is not a Direct IO device. 95 */ 96 enum sizes 97 { 98 buffer_size = 65535/4 99 }; 100 char principal_name_in[buffer_size]; 101 char password_1[buffer_size]; 102 char password_2[buffer_size]; 103 104 105 /* 106 ** Get the SYS$GETSYI item list ready. First zero it out, then fill it in. 107 */ 108 memset ( // clear out memory 109 getsyi_itmlst, // - Address to write to 110 0, // - Character to fill 111 sizeof (getsyi_itmlst)); // - size to fill 112 113 /* 114 ** System Parameter MAXBUF constrains the size of Buffered IO 115 ** 116 ** Buffer maxbuf will be filled in by SYS$GETSYI. 117 */ 118 getsyi_itmlst[getsyi_maxbuf].ile3$w_code = SYI$_MAXBUF; 119 getsyi_itmlst[getsyi_maxbuf].ile3$w_length = sizeof (maxbuf); 120 getsyi_itmlst[getsyi_maxbuf].ile3$ps_bufaddr = &maxbuf; 121 getsyi_itmlst[getsyi_maxbuf].ile3$ps_retlen_addr = NULL; 122 123 /* 124 ** End the item list with a terminator 125 */ 126 getsyi_itmlst[getsyi_terminator].ile3$w_code = 0; 127 getsyi_itmlst[getsyi_terminator].ile3$w_length = 0; 128 getsyi_itmlst[getsyi_terminator].ile3$ps_bufaddr = NULL; 129 getsyi_itmlst[getsyi_terminator].ile3$ps_retlen_addr = NULL; 130 131 RetStatus = sys$getsyiw ( 132 EFN$C_ENF, /* no event flag */ 133 NULL, /* CSID address */ 134 NULL, /* Node Name */ 135 &getsyi_itmlst, /* Item List */ 136 &iosb, /* IO Status block */ 137 NULL, /* AST routine */ 138 0 ); /* AST Parameter */ 139 if (RetStatus & STS$M_SUCCESS) 140 { 141 /* 142 ** We use the smaller of maxbuf or the buffer size 143 */ 144 if (maxbuf < buffer_size) 145 { 146 read_size = maxbuf; 147 } 148 else 149 { 150 read_size = buffer_size; 151 } 152 } 153 else 154 { 155 return RetStatus; 156 } 157 158 /* 159 ** Get the SYS$ACM item list ready. First zero it out, then fill it in. 160 */ 161 memset ( // clear out memory 162 acm_itmlst, // - Address to write to 163 0, // - Character to fill 164 sizeof (acm_itmlst)); // - size to fill 165 166 /* 167 ** Buffer logon_type contains a constant ACME$K_NETWORK. 168 ** 169 ** Using an interactive Logon Type would subject us to password 170 ** change requests, which are not viable in nondialogue mode (or 171 ** from our hypothetical badge reader, for that matter). 172 */ 173 acm_itmlst[acm_logon_type].ile3$w_code = ACME$_LOGON_TYPE; 174 acm_itmlst[acm_logon_type].ile3$w_length = sizeof (logon_type); 175 acm_itmlst[acm_logon_type].ile3$ps_bufaddr = &logon_type; 176 acm_itmlst[acm_logon_type].ile3$ps_retlen_addr = NULL; 177 178 /* 179 ** Buffer principal_name_in will be filled in from the badge reader. 180 */ 181 acm_itmlst[acm_principal_name_in].ile3$w_code = ACME$_PRINCIPAL_NAME_IN; 182 acm_itmlst[acm_principal_name_in].ile3$w_length = maxbuf; 183 acm_itmlst[acm_principal_name_in].ile3$ps_bufaddr = &principal_name_in; 184 acm_itmlst[acm_principal_name_in].ile3$ps_retlen_addr = NULL; 185 186 /* 187 ** Buffer password_1 will be filled in from the badge reader. 188 */ 189 acm_itmlst[acm_password_1].ile3$w_code = ACME$_PASSWORD_1; 190 acm_itmlst[acm_password_1].ile3$w_length = maxbuf; 191 acm_itmlst[acm_password_1].ile3$ps_bufaddr = &password_1; 192 acm_itmlst[acm_password_1].ile3$ps_retlen_addr = NULL; 193 194 /* 195 ** Buffer password_2 will be filled in from the badge reader. 196 */ 197 acm_itmlst[acm_password_2].ile3$w_code = ACME$_PASSWORD_2; 198 acm_itmlst[acm_password_2].ile3$w_length = maxbuf; 199 acm_itmlst[acm_password_2].ile3$ps_bufaddr = &password_2; 200 acm_itmlst[acm_password_2].ile3$ps_retlen_addr = NULL; 201 202 /* 203 ** End the item list with a terminator 204 */ 205 acm_itmlst[acm_terminator].ile3$w_code = 0; 206 acm_itmlst[acm_terminator].ile3$w_length = 0; 207 acm_itmlst[acm_terminator].ile3$ps_bufaddr = NULL; 208 acm_itmlst[acm_terminator].ile3$ps_retlen_addr = NULL; 209 210 /* 211 ** Assign a channel to the Badge Reader. 212 */ 213 214 devnam_desc.dsc$w_length = sizeof(devnam); 215 devnam_desc.dsc$a_pointer = &devnam[0]; 216 RetStatus = sys$assign ( 217 &devnam_desc, /* Device Name */ 218 &badge_reader_channel, /* channel to badge reader */ 219 0, /* access mode */ 220 0 ); /* Mailbox Name */ 221 if (!(RetStatus & STS$M_SUCCESS)) 222 { 223 return RetStatus; 224 } 225 226 /* 227 ** Exit from this one pass loop to deassign the channel and return. 228 */ 229 230 do 231 { 232 233 /* 234 ** Have the reader compare DNA. 235 ** 236 ** A failed DNA comparison from the hardware is reported 237 ** to the user the same as any other authentication failure, 238 ** withholding details regarding what went wrong. 239 */ 240 241 RetStatus = sys$qiow ( 242 EFN$C_ENF, /* no event flag */ 243 badge_reader_channel, /* channel to badge reader */ 244 IO$_ACCESS, /* IO function code */ 245 &iosb, /* IO Status block */ 246 NULL, /* AST routine */ 247 0, /* AST Parameter */ 248 0, /* p1 */ 249 0, /* p2 */ 250 0, /* p3 */ 251 0, /* p4 */ 252 0, /* p5 */ 253 0 ); /* p6 */ 254 if (RetStatus & STS$M_SUCCESS) 255 { 256 RetStatus = iosb.iosb$w_status; 257 } 258 if (!(RetStatus & STS$M_SUCCESS)) 259 { 260 RetStatus = ACME$_AUTHFAILURE; /* hide the exact cause */ 261 continue; /* exit from the do loop */ 262 } 263 264 /* 265 ** Read the Principal Name. 266 */ 267 268 RetStatus = sys$qiow ( 269 EFN$C_ENF, /* no event flag */ 270 badge_reader_channel, /* channel to badge reader */ 271 IO$_READVBLK, /* IO function code */ 272 &iosb, /* IO Status block */ 273 NULL, /* AST routine */ 274 0, /* AST Parameter */ 275 &principal_name_in, /* Buffer address */ 276 read_size, /* Buffer length */ 277 0, /* p3 */ 278 0, /* p4 */ 279 0, /* p5 */ 280 0 ); /* p6 */ 281 if (RetStatus & STS$M_SUCCESS) 282 { 283 RetStatus = iosb.iosb$w_status; 284 } 285 if (RetStatus & STS$M_SUCCESS) 286 { 287 acm_itmlst[acm_principal_name_in].ile3$w_length = iosb.iosb$w_bcnt; 288 } 289 else 290 { 291 continue; /* exit from the do loop */ 292 } 293 294 /* 295 ** Read the Primary Password. 296 */ 297 298 RetStatus = sys$qiow ( 299 EFN$C_ENF, /* no event flag */ 300 badge_reader_channel, /* channel to badge reader */ 301 IO$_READVBLK, /* IO function code */ 302 &iosb, /* IO Status block */ 303 NULL, /* AST routine */ 304 0, /* AST Parameter */ 305 &password_1, /* Buffer address */ 306 read_size, /* Buffer length */ 307 0, /* p3 */ 308 0, /* p4 */ 309 0, /* p5 */ 310 0 ); /* p6 */ 311 if (RetStatus & STS$M_SUCCESS) 312 { 313 RetStatus = iosb.iosb$w_status; 314 } 315 if (RetStatus & STS$M_SUCCESS) 316 { 317 acm_itmlst[acm_password_1].ile3$w_length = iosb.iosb$w_bcnt; 318 } 319 else 320 { 321 continue; /* exit from the do loop */ 322 } 323 324 /* 325 ** Read the Secondary Password. 326 */ 327 328 RetStatus = sys$qiow ( 329 EFN$C_ENF, /* no event flag */ 330 badge_reader_channel, /* channel to badge reader */ 331 IO$_READVBLK, /* IO function code */ 332 &iosb, /* IO Status block */ 333 NULL, /* AST routine */ 334 0, /* AST Parameter */ 335 &password_2, /* Buffer address */ 336 read_size, /* Buffer length */ 337 0, /* p3 */ 338 0, /* p4 */ 339 0, /* p5 */ 340 0 ); /* p6 */ 341 if (RetStatus & STS$M_SUCCESS) 342 { 343 RetStatus = iosb.iosb$w_status; 344 } 345 if (RetStatus & STS$M_SUCCESS) 346 { 347 acm_itmlst[acm_password_2].ile3$w_length = iosb.iosb$w_bcnt; 348 } 349 else 350 { 351 continue; /* exit from the do loop */ 352 } 353 354 } 355 while (1 == 2); 356 357 /* 358 ** Deassign the channel to the Badge Reader. 359 */ 360 361 DasStatus = sys$dassgn ( 362 badge_reader_channel ); /* channel to badge reader */ 363 if (RetStatus & STS$M_SUCCESS) 364 { 365 RetStatus = DasStatus; 366 } 367 if (!(RetStatus & STS$M_SUCCESS)) 368 { 369 return RetStatus; 370 } 371 372 /* 373 ** Attempt authentication. 374 */ 375 376 RetStatus = sys$acmw ( 377 EFN$C_ENF, /* no event flag */ 378 ACME$_FC_AUTHENTICATE_PRINCIPAL, /* ACM function code */ 379 NULL, /* pointer to Context pointer */ 380 &acm_itmlst, /* Item List */ 381 &acmsb, /* ACM Status block */ 382 NULL, /* AST routine */ 383 0 ); /* AST Parameter */ 384 if (RetStatus & STS$M_SUCCESS) 385 { 386 RetStatus = acmsb.acmesb$l_status; 387 } 388 389 return RetStatus; // return with ACM status 390 } |
Previous | Next | Contents | Index |
![]() ![]() ![]() ![]() |
privacy and legal statement | ||
5841PRO_089.HTML |