STATUS gcn_rem_auth( char *mech, char *host, i4 len, PTR token, i4 *size, PTR buff ) { GCS_REM_PARM parm; STATUS status; GCS_MECH mech_id; if ( (mech_id = gcs_mech_id( mech )) == GCS_NO_MECH ) { *size = 0; return( E_GC1004_SEC_MECH_UNKNOWN ); } parm.host = host; parm.length = len; parm.token = token; parm.size = *size; parm.buffer = buff; if ( (status = IIgcs_call( GCS_OP_REM_AUTH, mech_id, (PTR)&parm)) != OK ) *size = 0; else *size = parm.size; return( status ); }
i4 gcn_user_auth( i4 length, PTR buffer ) { GCS_USR_PARM parm; STATUS status; parm.buffer = (PTR)buffer; parm.length = length; length = 0; status = IIgcs_call( GCS_OP_USR_AUTH, GCS_NO_MECH, (PTR)&parm ); if ( status == OK ) length = parm.length; else if ( IIGCn_static.trace >= 1 ) TRdisplay( "gcn_user_auth: GCS user auth failure: 0x%x\n", status ); return( length ); }
i4 gcn_server_auth(char *server, char *user, char *alias, i4 length, PTR buffer) { GCS_SRV_PARM parm; STATUS status; /* ** A server auth is not absolutely required. Without a ** server auth, GCA will just produce a user auth for the ** connection instead. Failure to obtain a server key ** is therefore a 'soft' error. */ if ( ! (parm.key = gcn_get_server( server )) ) return( 0 ); parm.user = user; parm.alias = alias; parm.server = server; parm.length = length; parm.buffer = (PTR)buffer; if ((status = IIgcs_call(GCS_OP_SRV_AUTH, GCS_NO_MECH, (PTR)&parm)) != OK) { /* ** While not a critical error (see note above), ** we should have been able to produce a server ** auth since we have a server key. */ if ( IIGCn_static.trace >= 1 ) TRdisplay( "gcn_server_auth: GCS server (%s) auth failure: 0x%x\n", server, status ); return( 0 ); } return( parm.length ); }
VOID gca_terminate( GCA_SVC_PARMS *svc_parms ) { GCA_CB *gca_cb = (GCA_CB *)svc_parms->gca_cb; char id_buff[16]; /* ** Increment the term counter and perform global ** shutdown if all initializers have terminated. ** ** The current request must be completed during ** global shutdown so that ACB resources can be ** freed. If global shutdown is not being done, ** the request must still be completed to ensure ** a consistent state. */ if ( IIGCa_global.gca_initiate > ++IIGCa_global.gca_terminate ) gca_complete( svc_parms ); else { i4 assoc_id; /* ** Shutdown any remaining associations. */ for( assoc_id = gca_next_acb( -1 ); assoc_id >= 0; assoc_id = gca_next_acb( assoc_id ) ) { /* ** Skip ACB flagged for deletion since it has ** already been shutdown. */ GCA_ACB *acb = gca_find_acb( assoc_id ); if ( acb && ! acb->flags.delete_acb ) { GCA_DA_PARMS da_parms; STATUS status; /* ** TODO: Fix GC CL interface for register/llsten. ** ** If this association is an active listen, this ** call will fail. With the current interface ** there is nothing we can do. A GC control ** block is needed for registration, created ** by GCregister() and used in GClisten(), which ** can then be passed to a deregister routine ** capable of aborting a listen and cleaning up ** the register resources. ** ** Currently, the CL must do register/listen ** cleanup during GCterminate(), which can't be ** called prior to these calls here. */ da_parms.gca_association_id = assoc_id; IIGCa_cb_call( (PTR *)&gca_cb, GCA_DISASSOC, (GCA_PARMLIST *)&da_parms, GCA_SYNC_FLAG, NULL, -1L, &status ); } } /* ** Call GCterminate to perform system-dependent cleanup */ GCterminate( &svc_parms->gc_parms ); /* ** Cleanup ACB global resources. ** ** There may be an ACB associated with the current ** request. If so, it is the registration ACB and ** should be shutdown and flagged for deletion. We ** need to perform request completion at this point ** so that the ACB resources can be freed. */ gca_complete( svc_parms ); /* ** Release any remaining ACB. Normally, there should ** only be an active listen ACB at this point. */ for( assoc_id = gca_next_acb( -1 ); assoc_id >= 0; assoc_id = gca_next_acb( assoc_id ) ) { GCA_ACB *acb = gca_find_acb( assoc_id ); if ( acb ) gca_del_acb( acb->assoc_id ); } /* ** Now, release the remaining ACB resources. */ gca_free_acbs(); MUr_semaphore( &IIGCa_global.gca_acb_semaphore ); #ifdef GCF_EMBEDDED_GCN /* ** Shutdown the embedded Name Server interface */ if ( IIGCa_global.gca_embedded_gcn ) gca_ns_term(); #endif /* GCF_EMBEDDED_GCN */ /* ** Shutdown security. */ IIgcs_call( GCS_OP_TERM, GCS_NO_MECH, NULL ); IIGCa_global.gca_initialized = FALSE; } /* ** Tell MO that the control block is no longer active. */ STprintf( id_buff, "%d", gca_cb->gca_cb_id ); MOdetach( GCA_MIB_CLIENT, id_buff ); /* ** Free resources. */ MUr_semaphore( &gca_cb->gca_reg_semaphore ); /* ** Clear the initialization flag so the ** control block will be freed in gca_call(). */ gca_cb->gca_initialized = FALSE; return; }
STATUS gcn_use_auth( GCN_RESOLVE_CB *grcb, i4 prot ) { STATUS status; u_i1 ticket[ GCN_L_TICKET ]; GCS_REM_PARM rem; i4 ticket_len = 0; /* ** Try to get a usable ticket. */ status = gcn_use_rticket( grcb->username, grcb->vnode, grcb->pwd, ticket, &ticket_len ); if ( status != OK ) return( status ); /* ** Generate a remote authentication if supported ** by client and remote Name Server. Otherwise, ** the ticket is encapsulated in password. Client ** support is determined by the protocol level, ** while the ticket indicates Name Server support. */ if ( prot >= GCA_PROTOCOL_LEVEL_63 && ticket[ 0 ] == GCN_TICK_MAG && ticket[ 1 ] >= GCN_V1_TICK_MAG ) { /* ** Allocate 256 bytes buffer to hold RA. */ grcb->auth = MEreqmem( 0, GCN_AUTH_MAX_LEN, FALSE, &status ); if ( grcb->auth ) { rem.token = (PTR)ticket; rem.length = ticket_len; rem.size = GCN_AUTH_MAX_LEN; rem.buffer = grcb->auth; /* ** Call GCS to build RA for Server Name Server. */ status = IIgcs_call( GCS_OP_IP_AUTH, GCS_MECH_INGRES, (PTR)&rem ); if ( status == OK ) { grcb->usr = grcb->username; grcb->pwd = ""; grcb->flags &= ~GCN_RSLV_PWD_ENC; grcb->auth_len = rem.size; return( OK ); } /* ** Restore state and fall-through to password encapsulation. */ MEfree( grcb->auth ); grcb->auth = NULL; grcb->auth_len = 0; } } /* ** Convert ticket into a password which can be detected as ** a ticket by the remote NS. The installation password ** (which may have been in grcb->pwdbuf) has been saved, ** so use the password buffer to hold the formatted ticket. */ if ( grcb->pwdptr && grcb->pwdptr != grcb->pwdbuf ) MEfree( (PTR)grcb->pwdptr ); grcb->pwdptr = grcb->pwdbuf; MEcopy( GCN_AUTH_TICKET_MAG, GCN_L_AUTH_TICKET_MAG, grcb->pwdptr ); CItotext( ticket, ticket_len, grcb->pwdptr + GCN_L_AUTH_TICKET_MAG ); /* ** Send the ticket as the connection password. */ grcb->usr = grcb->username; grcb->pwd = grcb->pwdptr; grcb->flags &= ~GCN_RSLV_PWD_ENC; return( OK ); }