Exemple #1
0
/*{
** Name: psy_qrymod	- Process views, permits, and integrities
**
** Description:
**      This function applies the qrymod algorithm to user queries.
**	This algorithm is well-described in the specific functions
**	psyview.c, psyinteg.c, and psypermit.c.  It MUST be applied
**	in the order: views, integrities, permits.  This is because
**	permits are on base tables, not on views, and we don't want
**	the extra qualifications stuck on by the permit process to
**	affect the integrities.
**
**	Rules modifications are applied after all other query mods.
**	Rules processing (in psyrules.c) may add statement trees to rule lists
**	maintained in sess_cb.
**
** Inputs:
**      qtree                           The query tree to modify
**	sess_cb				Current session control block
**	psq_cb				Calling control block
**	num_joins			ptr to a var containing number of joins
**					in the query tree
**
** Outputs:
**      qtree                           Can be modified by views, permits,
**					and integrities
**	sess_cb				All kinds of miscellaneous stuff
**					that is too detailed to describe here
**	psq_cb
**	    .err_blk			Filled in if an error happens
**
**	*num_joins			Will be incremented if any of the views
**					involved in the query or any permits
**					applied use joins.
**
**	*resp_mask			if the qmode==PSQ_VIEW will contain
**					indicators of whether the view appears
**					to be updateable and/or grantable view 
**
**	Returns:
**	    E_DB_OK			Success
**	    E_DB_FATAL			Failure
**	Exceptions:
**	    none
**
** Side Effects:
**	    Can allocate memory
**	    Catalog I/O
**
** History:
**      09-jul-86 (jeff)
**          Adapted from 4.0 qrymod() function
**      02-sep-86 (seputis)
**          used result relation from auxiliary table since RDF ptrs are NULLed
**	18-sep-86 (daved)
**	    the result relation in the session cb is not always the
**	    same as the one found in the user range table. this is because
**	    the one in the range table is accurate only in an append statement.
**	    thus, we will now change the session cb to point to the correct
**	    result relation.
**	2-apr-87 (daved)
**	    set a pss_permit flag in the range table for each used entry.
**	    psy_permit will clear this flag. Psy_view will set this flag
**	    in all range entries that a derived from a table that still has
**	    this flag set, else it will clear this flag for new entries.
**	    We will then call psy_permit again, to catch all the new entries.
**	24-sep-87 (stec)
**	    Change error handling - call psf_error.
**	25-oct-87 (stec)
**	    Remove transaction creation, this is now done by SCF.
**	26-jan-89 (neil)
**	    Now also calls psy_rules to fill in rule tree.
**	08-mar-89 (neil)
**	    Calls psy_rules with more arguments.
**	22-jun-89 (andre)
**	    remove call to psy_protect() before call to psy_view() since
**	    psy_view() was modified to call psy_protect() before performing
**	    query modification on SQL views not belonging to the user.
**	    Additionally, &qtree will not be passed to psy_view(), since there
**	    is no apparent reason to do so (we no longer attempt to assign to
**	    the corresponding argument inside of psy_view() )
**      24-jul-89 (jennifer)
**	    For each statement, indicate that audit information is NULL.
**	08-sep-89 (andre)
**	    recieve and pass to psy_view() and psy_permit() ptr to a var
**	    containing number of joins in the query tree.
**	19-sep-90 (andre)
**	    as a result of changes in psy_view(), we no longer need to call
**	    psy_permit() from psy_qrymod().
**	13-dec-90 (ralph)
**	    Move reset of pss_audit to before psy_view invocation (b34903)
**	11-mar-91 (andre)
**	    if qmode is PSQ_VIEW, pass PSQ_RETRIEVE to psy_view(), psy_integ(),
**	    and psy_rules() + do not try to copy pss_usrrange to pss_auxrng
**	    since psy_dview() already placed the range table entries into
**	    pss_auxrng.
**	    (this is a part of fix for bug 33038)
**	07-aug-91 (andre)
**	    if qmode is PSQ_VIEW do NOT translate it to PSQ_RETRIEVE +
**	    if qmode is PSQ_VIEW do not bother calling psy_integ() and
**	    psy_rules()
**
**	    Added resp_mask to the argument list.  This mask will be used to
**	    communicate info to the caller of psy_qrymod().  psy_qrymod() itself
**	    will not contribute anything to the information, instead, it will
**	    pass it to other functions (initially only to psy_view()) which will
**	    be responsible for providing the actual information.
**	30-dec-92 (andre)
**	    when processing a view tree in the course of processing CREATE RULE
**	    on a view we do NOT want to do any permit, rule, or integrity
**	    checking
**	04-jan-93 (andre)
**	    if we are processing DELETE, INSERT, or UPDATE, and a table or a
**	    view being updated has rules defined on it, set PSS_CHECK_RULES in
**	    sess_cb->pss_resrng->pss_var_mask to remind psy_view() to call
**	    psy_rules()
**
**	    since psy_dview() is going away, and psl_cview() calls psy_qrymod()
**	    with range variables as they were entered in the grammar, we must
**	    copy the range table from pss_usrrange to pss_auxrng for define VIEW
**	    just as we do for all other QUEL statements
**
**	    In most cases psy_rules() will NO LONGER be called from
**	    psy_qrymod().  It will be called from psy_view() when processing
**	    INSERT, DELETE, or UPDATE. This change was necessary because now
**	    rules can be defined on views, and it seemed reasonable that rule
**	    checking (just like privilege checking) can be driven from
**	    psy_view().  The once exception occurs when we are processing UPDATE
**	    WHERE CURRENT OF - psy_view() will simply return when presented with
**	    this query mode, but there may be rules that apply to this
**	    statement.  Consequently, psy_rules() will be called from
**	    psy_qrymod() only when psq_qmode == PSQ_REPCURS
**	08-jan-93 (rblumer) 
**	    set flag to bypass permission checking for dummy set-input
**	    range variables.
**	30-mar-93 (rblumer) 
**	    set check_perms to false for system-generated procedures
**	    and for (internal) queries with PSS_NO_CHECKPERMS set.
**	01-apr-93 (andre)
**	    (fix for bugs 50823, 50825, and 50899)
**	    do not copy QUEL range table to aux. range table when processing
**	    REPLACE CURSOR - the entry describing the table/view over
**	    which the cursor has been defined has already been placed into
**	    pss_auxrng
**	08-apr-93 (andre)
**	    do not call psy_rules() explicitly for PSQ_REPCURS.  psy_view() will
**	    now handle PSQ_REPCURS and call psy_rules() when necessary.
**	09-apr-93 (andre)
**	    set PSS_CHECK_RULES in the pss_var_mask corresponding to the
**	    table/view being updated via a cursor
**	26-apr-93 (markg)
**	    If the server is running C2 then initialize each range
**	    entry to show that it needs to be audited.
**	5-jul-93 (robf)
**	    If server is C2 then initialize any result range table to show
**	    it needs to be audited.
**	14-sep-93 (robf)
**	    Add QUERY_SYSCAT check, disallowing direct querying of
**	    base catalogs without privilege. This is done here rather than
**	    lower down in view/permit processing since we want to allow
**	    access to views on base catalogs (e.g. standard catalogs)
**	    to go ahead. 
**	13-oct-93 (robf)
**          Add <st.h>
**	25-oct-93 (stephenb)
**	    If the server is running C2 then also initialize the result range
**	    entry to show that it needs to be audited.
**	13-dec-93 (robf)
**          When checking for query_syscat privilege, allow for extended
**	    catalogs. Some catalogs (like iistar_cdbs) have both the
**	    DMT_CATALOG and DMT_EXTENDED_CAT bits set. In this case we allow
**          access since this priv restricts base catalogs only.
**	09-feb-94 (andre)
**	    fix for bug 59595:
**		we also need to forego checking permits if we are parsing a 
**		system-generated query
**	11-jul-94 (robf)
**          Restrict direct queries to table extensions the same way
**	    as system catalogs, i.e. to those with SELECT_SYSCAT privilege.
**	    The rationale for this is that info in extensions is really
**          part of the base table, and to present an appropriately
**          protected view of the data access should be through the base
**          table, not directly at the extension.
*/
DB_STATUS
psy_qrymod(
	PST_QNODE          *qtree,
	PSS_SESBLK	   *sess_cb,
	PSQ_CB		   *psq_cb,
	PST_J_ID	   *num_joins,
	i4		   *resp_mask)
{
    PSS_RNGTAB          *resrng;
    PSS_USRRANGE	*rngtab = &sess_cb->pss_auxrng;
    PSF_MSTREAM         *mstream = &sess_cb->pss_ostream;
    DB_ERROR		*err_blk = &psq_cb->psq_error;
    i4			qmode = psq_cb->psq_mode;
    DB_STATUS		status;
    i4			i;
    i4			check_perms = TRUE;
    GLOBALREF PSF_SERVBLK *Psf_srvblk;
    i4		err_code;
    bool		can_query_syscat=FALSE;

    *resp_mask = 0L;	    /* init the response mask */

    /*
    ** avoid permit checking when processing RULE trees,
    ** or when parsing/reparsing a system-generated procedure,
    ** or when parsing a system-generated query (e.g. a query to check whether
    ** constraints hold on existing data)
    */
    if ((psq_cb->psq_mode == PSQ_RULE)
	|| (   (sess_cb->pss_dbp_flags & PSS_DBPROC)
	    && (sess_cb->pss_dbp_flags & PSS_SYSTEM_GENERATED))
	|| (psq_cb->psq_flag & PSQ_NO_CHECK_PERMS)
	|| (   (psq_cb->psq_info != (PST_INFO *) NULL)
	    && (psq_cb->psq_info->pst_execflags & PST_SYSTEM_GENERATED))
       )
    {
	check_perms = FALSE;
    }
    /*
    ** Can user directly query system catalogs ?
    ** Users with databse privilege QUERY_SYSCAT, or users with
    ** SECURITY subject privilege may directly query system cats
    */
    if(psy_ckdbpr(psq_cb, DBPR_QUERY_SYSCAT)==E_DB_OK)
	can_query_syscat=TRUE;
    else if(sess_cb->pss_ustat&DU_USECURITY)
	can_query_syscat=TRUE;
    else
	can_query_syscat=FALSE;

    /*
    ** Reset pss_audit prior to calling psy_view.
    */
    sess_cb->pss_audit = NULL;

    /*
    ** We don't want to clobber the user's view of the range table in
    ** the process of doing qrymod.  Therefore, we will copy the user's
    ** range table to the auxiliary range table, and use that instead.
    */

    /* don't need to copy range table for SQL because there are no range
    ** table entries that live longer than one statement
    **
    ** REPLACE CURSOR places description of the table/view over which it is
    ** defined into pss_auxrng
    */
    if (   sess_cb->pss_lang == DB_QUEL
	&& qmode != PSQ_REPCURS)
    {
	status = pst_rgcopy(&sess_cb->pss_usrrange, rngtab, 
	    &sess_cb->pss_resrng, err_blk);
	if (DB_FAILURE_MACRO(status))
	    return (status);
    }    
    for (i = 0; i < PST_NUMVARS; i++)
    {
	rngtab->pss_rngtab[i].pss_rgparent = -1;

	/* don't want to check permissions on
	** set-input temporary tables
	*/
	if (rngtab->pss_rngtab[i].pss_rgtype == PST_SETINPUT)
	    rngtab->pss_rngtab[i].pss_permit = FALSE;
	else
	    rngtab->pss_rngtab[i].pss_permit = check_perms;

	/*
	** See if this is a real base catalog.
	** We special case iidbcapabilities since its marked as a base 
	** catalog, but gets directly queried (and needs to be
	** accessed by frontends)
	*/
	if(rngtab->pss_rngtab[i].pss_used &&
	   rngtab->pss_rngtab[i].pss_rgno != -1 &&
	   rngtab->pss_rngtab[i].pss_tabdesc &&
	   ((
	   (rngtab->pss_rngtab[i].pss_tabdesc->tbl_2_status_mask&DMT_TEXTENSION)
	   ) || (
	   (rngtab->pss_rngtab[i].pss_tabdesc->tbl_status_mask&DMT_CATALOG) &&
	   !(rngtab->pss_rngtab[i].pss_tabdesc->tbl_status_mask&DMT_VIEW) &&
	   !(rngtab->pss_rngtab[i].pss_tabdesc->tbl_status_mask&DMT_EXTENDED_CAT) &&
	   STncasecmp((char*)&rngtab->pss_rngtab[i].pss_tabdesc->tbl_name,
			"iidbcapabilities", GL_MAXNAME)!=0
	   ))
        )
	{
		/*
		** This is a base catalog.
		*/
		if(!can_query_syscat)
		{
		    /*
		    ** Error, user can't query base catalogs.
		    */
		    if ( Psf_srvblk->psf_capabilities & PSF_C_C2SECURE )
			(VOID)psy_secaudit( 
			    FALSE,
			    sess_cb,
			    (char*)&rngtab->pss_rngtab[i].pss_tabdesc->tbl_name,
			    &rngtab->pss_rngtab[i].pss_tabdesc->tbl_owner,
			    DB_MAXNAME,
			    SXF_E_SECURITY,
			    I_SX273B_QUERY_SYSCAT,
			    (SXF_A_SELECT|SXF_A_FAIL),
			    err_blk);

		    (VOID) psf_error(E_PS035A_CANT_QUERY_SYSCAT, 
				0L, PSF_USERERR, &err_code,
			        err_blk, 1,
			        psf_trmwhite(sizeof(DB_NAME),
				  (char*)&rngtab->pss_rngtab[i].pss_tabdesc->tbl_name),
				(char*)&rngtab->pss_rngtab[i].pss_tabdesc->tbl_name);
		    return E_DB_ERROR;
		}
	}
	/*
	** If this is a C2 server set the PSS_DOAUDIT flag
	** for this entry.
	*/
	if (Psf_srvblk->psf_capabilities & PSF_C_C2SECURE)
	    rngtab->pss_rngtab[i].pss_var_mask |= PSS_DOAUDIT;
    }
    
    if (resrng = sess_cb->pss_resrng)
    {
	/* don't want to check permissions
	** on set-input temporary tables
	*/
	if (rngtab->pss_rngtab[i].pss_rgtype == PST_SETINPUT)
	    rngtab->pss_rngtab[i].pss_permit = FALSE;
	else
	    rngtab->pss_rngtab[i].pss_permit = check_perms;

	/*
	** if processing DELETE, UPDATE, INSERT, or UPDATE/REPLACE cursor, and
	** there are rules defined on the view/table being updated, set
	** PSS_CHECK_RULES in pss_var_mask
	*/
	if (   (   qmode == PSQ_APPEND
		|| qmode == PSQ_DELETE
		|| qmode == PSQ_REPLACE
		|| qmode == PSQ_REPCURS
	       )
	    && resrng->pss_tabdesc->tbl_status_mask & DMT_RULE
	   )
	{
	    resrng->pss_var_mask |= PSS_CHECK_RULES;
	}
        /*
        ** If this is a C2 server set the PSS_DOAUDIT flag
        ** for the result table.
        */
        if (Psf_srvblk->psf_capabilities & PSF_C_C2SECURE)
		rngtab->pss_rsrng.pss_var_mask |= PSS_DOAUDIT;
    }


    /* Apply view processing */
    status = psy_view(mstream, qtree, rngtab, qmode, sess_cb, err_blk,
		      num_joins, resp_mask);
    if (DB_FAILURE_MACRO(status))
    {
	return (status);
    }

    /*
    ** do not check for existing INTEGRITIES when processing trees as a
    ** part of CREATE/DEFINE VIEW or CREATE RULE processing
    */
    if (qmode != PSQ_VIEW && qmode != PSQ_RULE)
    {
	/* Apply integrity processing */
	status = psy_integ(mstream, qtree, rngtab, resrng, qmode,
	    sess_cb, &qtree, err_blk);
	if (DB_FAILURE_MACRO(status))
	{
	    return (status);
	}
    }

    return (status);
}
Exemple #2
0
/*{
** Name: scs_monitor	- Implement the SCS part of the monitor task
**
** Description:
**	This routine is called ala the regular thread processing routine.
**	It parses its input, decides what to do, and returns the output.
**
**	The commmands completely interpreted here are:
**
**		set server shut	(CS_CLOSE)
**			Disallow new connections, shutdown when
**			last current session exits.
**          
**          	remove SESSION
**          	    	New improved "safe" version, acts the same
**  	    	    	as front-end exiting and dropping GCA connection.
**	
**		kill SESSION
**			Signal CS_KILL_EVENT to a user session actively
**			running a query.
**          
**	NEW:
**		set server closed
**			Disallow new regular user sessions.
**          
**		set server open
**			Reallow new regular user sessions.  Cancel
**			any pending 'set server shut' shutdown.
**
**		show server listen
**
**		crash session SESSIONID
**
**	Commands partially handled here and partially in CSmonitor are:
**
**		stop server	(CS_KILL)
**			Kill user sessions, shutdown when they're gone.
**          
**		stop server conditional (CS_COND_CLOSE)
**			Shutdown if no sessions, which never works because
**			this session always exists.
**          
**		crash server	(CS_CRASH)
**			Take the server down immediately.
**
**	All other commands are passed to CSmonitor for handling.
**
** Inputs:
**	mode				Mode of operation
**					    CS_INPUT, _OUPUT, ...
**	scb				Sessions control block to monitor
**	*command			Text of the command
**	powerful			Is this user powerful
**	output_fcn			Function to call to perform the output.
**					This routine will be called as
**					    (*output_fcn)(newline_present,
**							    length,
**							    buffer)
**					where buffer is the length character
**					output string, and newline_present
**					indicates whether a newline needs to
**					be added to the end of the string.
**
** Outputs:
**	next_mode			As above.
**	Returns:
**	    OK
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	26-Jul-1993 (daveb)
**	    created.
**	15-Sep-1993 (daveb)
**	    ifdef out all but drop connection for now.
**	1-Nov-1993 (daveb)
**	    Match LRC proposal.  Drop becomes remove, remove becomes kill.
**      10-Nov-1993 (daveb)
**          Match approved proposal.  Kill becomes "crash session SESSIONID"
**	15-dec-93 (robf)
**          Add prototype "broadcast" message request.
**	4-mar-94 (robf)
**          Add initial security auditing to iimonitor events.
**	12-dec-1996 (canor01)
**	    Add support for sampler thread.
**	24-Apr-2003 (jenjo02)
**	    Added "kill" command to abort eligible queries
**	    while leaving the session intact, SIR 110141.
**	17-Sep-2004 (schka24)
**	    Manual fix to remove command so that it fires.
**      05-may-2005 (horda03) Bug 114453/INGSRV 3290
**          For server/session changes log the command.
**      22-may-2007 (horda03) Bug 117966
**          Log the command before calling CSmonitor, as
**          the CS could be crashing the server.
**      23-Sep-2009 (hanal04) Bug 115316
**          Added "SHOW SERVER CAPABILITIES".
*/
static STATUS
scs_monitor( i4 mode, CS_SCB *scb, i4 *nmode, char *command,
	    i4 powerful, i4 (*output_fcn)(PTR, i4, char *) )
{
    STATUS		ret_stat;
    char		buf[81];
    bool		completely_done;
    PTR			ptr_scb;
    SCD_SCB		*an_scb;
    i4                  log_cmd = 0;
    i4                  local_error;
    SCD_SCB		*my_scb = (SCD_SCB*)scb;
    
    *nmode = CS_EXCHANGE;
    completely_done = FALSE;
    ret_stat = OK;
    
    switch (mode)
    {
    case CS_INITIATE:
	*nmode = CS_INPUT;
	break;
	
    case CS_TERMINATE:
	break;
	
    case CS_INPUT:
		
	CVlower(command);
	if (STscompare("setservershut", 0, command, 0) == 0)
	{
	    /* Audit log the attempt here? */
	    if (!powerful)
	    {
		TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			 "Superuser status required to stop servers");
		if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE )
		    scs_mon_audit((SCD_SCB*)scb, 
			    SXF_A_CONTROL|SXF_A_FAIL,
			    I_SX274D_SET_SERVER_SHUT
			    );
	    }
	    else /* disallow regular listens, exit when last conn exits */
	    {
		Sc_main_cb->sc_listen_mask = 
		    (SC_LSN_TERM_IDLE |SC_LSN_SPECIAL_OK) ;
		TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			 "Server will stop. %d. sessions remaining",
			 Sc_main_cb->sc_current_conns );
		if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE )
		    scs_mon_audit((SCD_SCB*)scb, 
			    SXF_A_CONTROL|SXF_A_SUCCESS,
			    I_SX274D_SET_SERVER_SHUT
			    );
                log_cmd = 1;
	    }
	    completely_done = TRUE;
	}
	else if (STscompare("setserverclosed", 0, command, 0) == 0)
	{
	    /* Audit log the attempt here? */
	    if (!powerful)
	    {
		TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			 "Superuser status required to disable connections");
		if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE )
		    scs_mon_audit((SCD_SCB*)scb, 
			    SXF_A_CONTROL|SXF_A_FAIL,
			    I_SX2748_SET_SERVER_CLOSED
			    );
	    }
	    else		/* Disallow regular listens */
	    {
		if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE )
		    scs_mon_audit((SCD_SCB*)scb, 
			    SXF_A_CONTROL|SXF_A_SUCCESS,
			    I_SX2748_SET_SERVER_CLOSED
			    );
		Sc_main_cb->sc_listen_mask &= (~SC_LSN_REGULAR_OK);
		TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			 "User connections now disabled" );
                log_cmd = 1;
	    }
	    completely_done = TRUE;
	}
	else if (STscompare("setserveropen", 0, command, 0) == 0)
	{
	    /* Audit log the attempt here? */
	    if (!powerful)
	    {
		TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			 "Superuser status required to enable connections");
		if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE )
		    scs_mon_audit((SCD_SCB*)scb, 
			    SXF_A_CONTROL|SXF_A_FAIL,
			    I_SX2749_SET_SERVER_OPEN
			    );
	    }
	    else  /* allow all listens, cancel any impending shutdown */
	    {
		Sc_main_cb->sc_listen_mask =
		    (SC_LSN_REGULAR_OK | SC_LSN_SPECIAL_OK);
		TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			 "User connections now allowed" );
		if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE )
		    scs_mon_audit((SCD_SCB*)scb, 
			    SXF_A_CONTROL|SXF_A_SUCCESS,
			    I_SX2749_SET_SERVER_OPEN
			    );
                log_cmd = 1;
	    }
	    completely_done = TRUE;
	}
	else if (STncasecmp("broadcast", command, 9) == 0)
	{
	    /* Audit log the attempt here? */
	    if (!powerful)
	    {
		TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			 "Superuser status required to broadcast messages");
	    }
	    else  
	    {
		/*
		** Broadcast the message to any connected sessions
		*/
		scs_scan_scbs(scs_broadcast_mesg, (PTR)(command+10));
	    }
	    completely_done = TRUE;
	}
	else if (STscompare("stopserverconditional", 0, command, 0) == 0 ||
		 STscompare("stopserver", 0, command, 0) == 0 ||
		 STscompare("crashserver", 0, command, 0) == 0 )
	{
	    /* Audit log the attempt here? */
	    if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE )
		scs_mon_audit((SCD_SCB*)scb, 
			powerful?
			    SXF_A_CONTROL|SXF_A_SUCCESS:
			    SXF_A_CONTROL|SXF_A_FAIL,         /* Action */
			I_SX274A_STOP_SERVER
			);
                log_cmd = powerful;
	}
        else if (STscompare("showservercapabilities", 0, command, 0) == 0)
        {
            TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "%v",
                     SC_CAPABILITIES_FLAGS, Sc_main_cb->sc_capabilities );
            completely_done = TRUE;
        }
	else if (STscompare("showserverlisten", 0, command, 0) == 0)
	{
	    TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "%s", 
		     Sc_main_cb->sc_listen_mask & SC_LSN_REGULAR_OK ?
		     "OPEN" : "CLOSED" );
	    completely_done = TRUE;
	}
	else if (STscompare("showservershutdown", 0, command, 0) == 0)
	{
	    TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "%s", 
		     Sc_main_cb->sc_listen_mask & SC_LSN_TERM_IDLE ?
		     "PENDING" : "OPEN" );
	    completely_done = TRUE;
	}
# ifdef NOT_SUPPORTED
	else if (STscompare("showconnections", 0, command, 0) == 0 )
	{
	    scs_scan_scbs( scs_show_func, (PTR)&powerful );
	    completely_done = TRUE;
	}
	else if (STscompare("show connection", 15, command, 15) == 0 )
	{
	    completely_done = TRUE;
	    STzapblank(command, command);
	    if (CVaxptr(command + 14, &ptr_scb) ||
		!scs_is_user_scb( (an_scb = (SCD_SCB *)ptr_scb) ) )
	    {
		TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			 "Invalid connection id");
		break;
	    }
	    scs_show_func( an_scb, &powerful );
	}
# endif
	else if (STscompare("remove", 6, command, 6) == 0)
	{
	    completely_done = TRUE;
	    STzapblank(command, command);
	    if (CVaxptr(command + 6, &ptr_scb) || scb == NULL ||
		!scs_is_user_scb( (an_scb = (SCD_SCB *)ptr_scb) ) ||
		an_scb == my_scb )
	    {
		TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			 "Invalid session id");
		break;
	    }
	    if ((MEcmp(an_scb->cs_scb.cs_username, scb->cs_username,
		       sizeof(scb->cs_username))) && !powerful)
	    {
		TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			 "Superuser or owner status required to remove session");
		if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE )
		    scs_mon_audit((SCD_SCB*)scb, 
			    SXF_A_CONTROL|SXF_A_FAIL,
			    I_SX274B_REMOVE_SESSION
			    );
		break;
	    }
	    if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE )
		scs_mon_audit((SCD_SCB*)scb, 
			SXF_A_CONTROL|SXF_A_SUCCESS,
			I_SX274B_REMOVE_SESSION
			);
	    scs_remove_sess( an_scb );
	    TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
		     "Session %p removed", an_scb);
            log_cmd = 1;
	}
	else if (STscompare("crash session", 13, command, 13) == 0)
	{
	    completely_done = TRUE;
	    STzapblank(command, command);
	    if (CVaxptr(command + 12, &ptr_scb) || scb == NULL ||
		!scs_is_user_scb( (an_scb = (SCD_SCB *)ptr_scb) ) ||
		an_scb == my_scb )
	    {
		TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			 "Invalid session id");
		break;
	    }
	    if ((MEcmp(an_scb->cs_scb.cs_username, scb->cs_username,
		       sizeof(scb->cs_username))) && !powerful)
	    {
		TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			 "Superuser or owner status required to crash session");
		if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE )
		    scs_mon_audit((SCD_SCB*)scb, 
			SXF_A_CONTROL|SXF_A_FAIL,
			I_SX274C_CRASH_SESSION
			);
		break;
	    }
	    if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE )
		scs_mon_audit((SCD_SCB*)scb, 
			SXF_A_CONTROL|SXF_A_SUCCESS,
			I_SX274C_CRASH_SESSION
			);
	    scs_crash_sess( an_scb );
	    TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
		     "Session %p crashed", an_scb);
            log_cmd = 1;
	}
	else if (STscompare("kill", 4, command, 4) == 0)
	{
	    completely_done = TRUE;
	    STzapblank(command, command);
	    if (CVaxptr(command + 4, &ptr_scb) || scb == NULL ||
		!scs_is_user_scb( (an_scb = (SCD_SCB *)ptr_scb) ) ||
		an_scb == my_scb )
	    {
		TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			 "Invalid session id");
	    }
	    else if ((MEcmp(an_scb->cs_scb.cs_username, scb->cs_username,
		       sizeof(scb->cs_username))) && !powerful)
	    {
		TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			 "Superuser or owner status required to kill query");
		if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE )
		    scs_mon_audit((SCD_SCB*)scb, 
			SXF_A_CONTROL|SXF_A_FAIL,
			I_SX2755_KILL_QUERY
			);
	    }
	    else switch ( an_scb->scb_sscb.sscb_qmode )
	    {
		case 0:
		    TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			    "Session %p is not executing a query", an_scb);
		    break;

		/* Honor only "meaningful" types of queries: */
		case PSQ_RETRIEVE:
		case PSQ_RETINTO:
		case PSQ_APPEND:
		case PSQ_REPLACE:
		case PSQ_DELETE:
		case PSQ_COPY:
		case PSQ_MODIFY:
		case PSQ_EXECQRY:
		case PSQ_EXCURS:
		case PSQ_CALLPROC:
		case PSQ_REPCURS:
		case PSQ_RETCURS:
		case PSQ_EXEDBP:
		case PSQ_REGPROC:
		case PSQ_DDEXECPROC:
		case PSQ_CREATE:
		    if ( an_scb->scb_sscb.sscb_force_abort ||
			 an_scb->scb_sscb.sscb_interrupt )
		    {
			TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			     "Session %p query already aborting", an_scb);
		    }
		    else
		    {
			scs_kill_query( an_scb );
			if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE )
			    scs_mon_audit((SCD_SCB*)scb, 
				    SXF_A_CONTROL|SXF_A_SUCCESS,
				    I_SX2755_KILL_QUERY
				    );
			TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
				 "Session %p query killed", an_scb);
		    }
		    break;

		default:
		    TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
			     "Session %p query cannot be killed", an_scb);
		    break;
	    }
	}
# ifdef NOT_SUPPORTED
	else if (STscompare("help", 0, command, 0) == 0)
	{
	    TRformat(output_fcn, 1, buf, sizeof(buf) - 1,
		     "SCS monitor commands:\nset server shut\nset server closed\nset server open\nshow server listen\nshow server shutdown\nremove SESSION\ncrash session SESSION\n\nCS monitor commands:\n");
	}
# endif
        else if (! CS_is_mt())
	    /* OS Thread version will start an OS thread in the CS */
            if ((STscompare("start sampling", 14, command, 14) == 0))
            {
                if (!powerful)
                {
                    TRformat(output_fcn, (i4 *) 1, buf, sizeof(buf)-1,
                        "Superuser status required to start sampling.", 0L);
                }
                else
                {
                    GCA_LS_PARMS        local_crb;
	            CL_ERR_DESC         errdesc;

                    local_crb.gca_status = 0;
                    local_crb.gca_assoc_id = 0;
                    local_crb.gca_size_advise = 0;
                    local_crb.gca_user_name = "<Sampler Thread>";
                    local_crb.gca_account_name = 0;
                    local_crb.gca_access_point_identifier = "NONE";
                    local_crb.gca_application_id = 0;

		    /* set up all the CS control blocks for the sampler */
	            ret_stat = CSmonitor( mode, scb, nmode, command,
				          powerful, output_fcn );

		    if ( ret_stat == OK )
                        ret_stat = CSadd_thread(CS_LIM_PRIORITY-1, (PTR) &local_crb,
                                                SCS_SSAMPLER, (CS_SID*)NULL, &errdesc);

                    if (ret_stat)
                    {
                        TRformat(output_fcn, (i4 *) 1, buf, sizeof(buf)-1,
                               "Sampling failed to start.");
                    }
                }
            }

        /* log the command before calling CSmonitor(), as the server could be left in an
        ** unknown state if the command CRASH SERVER or STOP SERVER are used
        */

        if (log_cmd)
        {
           ule_format( I_SC051E_IIMONITOR_CMD, 0, ULE_LOG, NULL, 0, 0, 0, &local_error,
                       3, STlength(command), command,
                       DB_OWN_MAXNAME, &((SCD_SCB *)scb)->scb_sscb.sscb_ics.ics_rusername,
                       sizeof(DB_TERM_NAME), &((SCD_SCB *)scb)->scb_sscb.sscb_ics.ics_terminal, 
                       0, 0);
        }

	if( !completely_done )
	    ret_stat = CSmonitor( mode, scb, nmode, command,
				 powerful, output_fcn );
	break;
	
    case CS_OUTPUT:
	break;
    }

    return( ret_stat );
}
Exemple #3
0
STATUS gcn_recrypt( bool clustered, u_i1 *local_mask, char *gcn_val, 
    bool *v1DecryptErr, bool *writeOutput)
{
    i2 pc;
    char *pv[ 3 ];
    STATUS status = OK;
    char *p;
    char pwd[GC_L_PASSWORD];
    i2 j;
    bool printable;

    *v1DecryptErr = FALSE;

    pc = gcu_words( gcn_val, NULL, pv, ',', 3 );
    if (pc < 2 )  
        pv[1] = "";
    if (pc < 3 )  
        pv[2] = "";

    if (!STcasecmp(pv[2],"V0") || (pc < 3))
        status = gcn_decrypt( pv[0], pv[1], pwd );
    else
        status = gcn_decode( pv[0],(u_i1*)local_mask, pv[1], pwd );
    
    if (status != OK)
    {
        if (!STcasecmp(pv[2],"V1"))
            *v1DecryptErr = TRUE;
        goto end_routine;      
    }
    if (!STlength(pwd))
    {
        if (!STcasecmp(pv[2],"V1"))
            *v1DecryptErr = TRUE;
        status = FAIL;
        goto end_routine;
    }
    p = &pwd[0];
    printable = TRUE;
    for (j = 0; j < STlength(pwd); j++)
    {
        if (!CMprint(p))
        {
            printable = FALSE;
            break;
        }
        CMnext(p);
    }
    if (!printable)
    {
         if (!STcasecmp(pv[2],"V1"))
             *v1DecryptErr = TRUE;
         status = FAIL;
         goto end_routine;
    }

    if (clustered)
    {
        if (!STncasecmp("V1", pv[2], STlength(pv[2])))
            *writeOutput = TRUE;
        status = gcu_encode( pv[0], pwd, pv[1] );
        STpolycat( 5, pv[0], ",", pv[1], ",", "V0", gcn_val );
    }
    else
    {
        status = gcn_encode( pv[0],(u_i1*)local_mask, pwd, pv[1] );
        STpolycat( 5, pv[0], ",", pv[1], ",", "V1", gcn_val );
    }

end_routine:
     return status;
}
Exemple #4
0
main(int argc, char **argv)
{
    STATUS status = OK;
    VMS_STATUS vStatus;
    char srcbuf[NAME_FILE_SIZE];
    char dstbuf[NAME_FILE_SIZE];
    char delFile[NAME_FILE_SIZE];
    struct dsc$descriptor_s filename_d = 
        { sizeof (delFile) - 1,
            DSC$K_DTYPE_T,
            DSC$K_CLASS_S,
            delFile
        };
    FILE *srcFile = NULL;
    FILE *dstFile = NULL;
    FILE *nameFile = NULL;
    LOCATION loc;
    bool clusterArg = FALSE;
    bool unclusterArg = FALSE;
    bool writeOutput = FALSE;
    bool validSyntax;
    bool clustered = FALSE;
    bool v1DecryptErr = FALSE;
    bool rewrite = FALSE;
    bool isLogin = FALSE;
    i4   total_recs = 0;
    char local_host[MAX_LOC+CM_MAXATTRNAME];
    char config_host[MAX_LOC+CM_MAXATTRNAME];
    i2 i,j;
    i4 active_rec;
    i4 offset;
    char *onOff = NULL;
    bool srcOpened=FALSE;
    bool dstOpened=FALSE;
    bool printable = TRUE;
    GCN_QUEUE *gcn_q;
    GCN_QUEUE *merge_q;
    i4 rec_len = 0;
    QUEUE *q;
    u_i1  local_mask[ 8 ];        /* Must be 8 bytes */
    char name[MAX_LOC+CM_MAXATTRNAME];
    i4 count;
    char *p = NULL;
    i4 dcryptFail = 0;
    i2 pc;
    char *pv[ 3 ];
    GCN_DB_REC0 tmp_rec;
    SYSTIME timestamp;

    MEadvise(ME_INGRES_ALLOC);
    SIeqinit();
    GChostname( local_host, sizeof(local_host));
    STcopy (PMhost(), config_host);
    if (argc == 1)
       validSyntax = TRUE;
    /*
    ** Parse input arguments.
    */    
    for (i = 1; i < argc; i++)
    {
        validSyntax = FALSE;
        for (j = 0; j < argLen; j++)
        {
            if (!STncasecmp(arg[j],argv[i], STlength(argv[i])))
            {
                switch(j)
                {
                    case HELP1:
                    case HELP2:
                    case HELP3:
                    case HELP4:
                       usage();
                       break;

                    case VERBOSE:
                       validSyntax = TRUE;
                       verboseArg = TRUE;
                       break;

                    case CLUSTER:
                       validSyntax = TRUE;
                       clusterArg = TRUE;
                       writeOutput = TRUE;
                       break;

                    case UNCLUSTER:
                       validSyntax = TRUE;
                       unclusterArg = TRUE;
                       writeOutput = TRUE;
                       break;
                }
            } /* if (!STncasecmp(arg[j],argv[i], STlength(argv[i]))) */
            if (validSyntax)
                break;
        } /* for (j = 0; j < argLen; j++) */
        if (!validSyntax)
            break;
    } /* for (i = 1; i < argc; i++) */

    if (!validSyntax)
    {
        usage();
        PCexit(1);
    }

    if (clusterArg && unclusterArg)
    {
        SIprintf("Cannot specify both -c and -u\n\n");
            usage();
        PCexit(1);
    }

    if (verboseArg)
        SIprintf("Local host is %s\n", local_host);

    /*
    ** Generate key seeds for encoding and decoding.
    */
    STpolycat( 2, GCN_LOGIN_PREFIX, local_host, name );
    gcn_init_mask( name, sizeof( local_mask ), local_mask );

    QUinit(&gcn_qhead);
    QUinit(&merge_qhead);
    PMinit();

    /*
    ** See if this is a clustered installation.  If it is, 
    ** the node, login, and attribute files have no file extension.
    */
    if ( PMload( (LOCATION *)NULL, (PM_ERR_FUNC *)NULL ) != OK )
    {
        SIprintf("Error reading config.dat, exiting\n");
        goto cvt_exit;      
    }

    PMsetDefault( 0, SystemCfgPrefix );
    PMsetDefault( 1, config_host );
    PMsetDefault( 2, ERx("gcn") );

    status = PMget( ERx("!.cluster_mode"), &onOff);
    if (onOff && *onOff)
        ;
    else
        onOff = "OFF";

    if (verboseArg)
        SIprintf("Cluster mode is %s\n", onOff);

    if (!clusterArg && !unclusterArg)
        clustered = !STncasecmp(onOff, "ON", STlength(onOff));

    /*
    ** Rewrite the named GCN files.  For clustered installations, the
    ** node, login and attribute files have no hostname extension.
    */
    for ( i = 0; i < NBR_NAMED_FILES; i++ )
    {  
        /*
        ** Ticket files are simply deleted.
        */
        if (i == IILTICKET || i == IIRTICKET)
        {
            STprintf(delFile, "II_SYSTEM:[INGRES.FILES.NAME]II%s*;*", 
                named_file[i].file);
            if (verboseArg)
                SIprintf("Deleting %s\n", delFile);
            filename_d.dsc$w_length = STlength(delFile);
            vStatus = lib$delete_file(&filename_d,0,0,0,0,0,0,0,0,0);
            if (!vStatus & STS$M_SUCCESS)
                SIprintf("delete of %s failed, status is 0x%d\n", delFile,
                    vStatus);
            continue;
        }    
 
        rewrite = FALSE;
        if (!clusterArg && !unclusterArg)
            writeOutput = FALSE;
        if ( ( status = NMloc( FILES, PATH & FILENAME, 
            (char *)NULL, &loc ) ) != OK )
        {
            SIprintf("iicvtgcn: Could not find II_SYSTEM:[ingres.files]\n");
            goto cvt_exit;
        }
     
        LOfaddpath( &loc, "name", &loc );

        if (clustered || unclusterArg)
        {
            if (named_file[i].add_cluster_node)
                STprintf( srcbuf, "II%s_%s", named_file[i].file,config_host);
            else
                STprintf(srcbuf, "II%s", named_file[i].file);
        }
        else 
            STprintf( srcbuf, "II%s_%s", named_file[i].file,config_host);

        if (verboseArg)
            SIprintf("Opening %s for input\n", srcbuf);

        LOfstfile( srcbuf, &loc );

        /*
        ** Ignore non-existent files.
        */
        if ( LOexist( &loc ) != OK )
        {
            if (verboseArg)
                SIprintf("%s does not exist\n", srcbuf);
            continue;
        }
        /*
        ** Open the existing file as "regular" RACC.
        */
        status = SIfopen( &loc, "r", (i4)SI_RACC, sizeof( GCN_DB_REC0 ), 
            &srcFile );
        /*
        ** If the file exists but can't be opened, it's already optimized.
        */
        if (status == E_CL1904_SI_CANT_OPEN && ( LOexist( &loc ) == OK ) )
        {
            /*
            ** Open the existing file as "optimized" RACC.
            */
            status = SIfopen( &loc, "r", (i4)GCN_RACC_FILE, 
                sizeof( GCN_DB_REC0 ), &srcFile );
            if (status != OK)
            {
                SIprintf( "iicvtgcn: Error opening %s, status is %x\n",
                    srcbuf, status );
                continue;
            }
            if (verboseArg)
                SIprintf("%s is already optimized\n", srcbuf);
        }
        else if (status != OK)
        {
            SIprintf( "iicvtgcn: Error opening %s, status is %x\n",
                srcbuf, status );
            continue;
        }

        /*
        ** A successful open as SI_RACC means the file is not optimized.
        ** This file needs a rewrite.
        */
        else
        {
            if (verboseArg)
                SIprintf("Rewriting %s as optimized\n", srcbuf);
            writeOutput = TRUE;    
        }

        srcOpened = TRUE;

        while ( status == OK )
        {
            /*
            ** Read the source data and store in a queue for analysis.
            */
            status = SIread( srcFile, sizeof( GCN_DB_REC0 ),
                &count, (PTR)&tmp_rec );
            if ( status == ENDFILE )
                break;

            if ( status != OK )
            {
                SIprintf("iicvtgcn: Error reading %s, status is %x\n",
                    srcbuf, status);
                goto cvt_exit;
            }
            else if (tmp_rec.gcn_invalid && tmp_rec.gcn_tup_id != -1)
                continue;
            else
            {
                gcn_q = (GCN_QUEUE *)MEreqmem(0, sizeof(GCN_QUEUE),0,NULL);
                if (!gcn_q)
                {
                    SIprintf("iicvtgcn: Cannot allocate memory, exiting\n");
                    goto cvt_exit;
                }
                MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), (PTR)&gcn_q->buf);
                QUinsert(&gcn_q->q, &gcn_qhead);
                /*
                ** EOF record found.
                */
                if (gcn_q->buf.gcn_tup_id == -1)
                {
                    gcn_q->buf.gcn_l_uid = 0;
                    gcn_q->buf.gcn_uid[0] = '\0';
                    gcn_q->buf.gcn_l_obj = 0;
                    gcn_q->buf.gcn_obj[0] = '\0';
                    gcn_q->buf.gcn_l_val = 0;
                    gcn_q->buf.gcn_val[0] = '\0';
                    gcn_q->buf.gcn_invalid = TRUE;
                    break;
                }
            }
        } /* while ( status == OK ) */

        /*
        ** Decrypt passwords for IILOGIN files.  If any V1 records are found, 
        ** the IILOGIN file will need to be rewritten.
        */
        isLogin = FALSE;
        for (q = gcn_qhead.q_prev; q != &gcn_qhead; q = q->q_prev)
        {
            gcn_q = (GCN_QUEUE *)q;

            /*
            ** EOF record found.
            */
            if (gcn_q->buf.gcn_tup_id == -1)
            {
                gcn_q->buf.gcn_invalid = TRUE;
                break;
            }

            if (i == IILOGIN)
            {
                isLogin = TRUE;
                MEcopy((PTR)&gcn_q->buf, sizeof(GCN_DB_REC0), (PTR)&tmp_rec);
                if (verboseArg)
                     SIprintf("\tEncoding vnode %s\n", gcn_q->buf.gcn_obj);

                if (unclusterArg)
                    status = gcn_recrypt( FALSE, local_mask, 
                        gcn_q->buf.gcn_val, &v1DecryptErr, &writeOutput);
                else if (clusterArg)
                    status = gcn_recrypt( TRUE, local_mask, 
                    gcn_q->buf.gcn_val, &v1DecryptErr, &writeOutput);
                else
                    status = gcn_recrypt( clustered, local_mask, 
                    gcn_q->buf.gcn_val, &v1DecryptErr, &writeOutput);

                if (status != OK)
                {
                    if (verboseArg)
                        SIprintf("Cannot decrypt password from " \
                            "vnode %s status %x\n", gcn_q->buf.gcn_obj,
                            status);
                    dcryptFail++;
                    MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), 
                        (PTR)&gcn_q->buf);
                    continue;                
                }
                if (v1DecryptErr)
                {
                    if (verboseArg)
                        SIprintf("Cannot decrypt password from " \
                            "vnode %s\n", gcn_q->buf.gcn_obj);
                    dcryptFail++;
                    MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), 
                        (PTR)&gcn_q->buf);
                    continue;
                }
            }  /* if (LOGIN) */

        } /* for (q = gcn_qhead.q_prev; q != &gcn_qhead; q = q->q_prev) */
        
        if (dcryptFail && verboseArg && isLogin)
        {
            if (clustered || unclusterArg )
                SIprintf("\n%d vnode(s) could not be decrypted.\n" \
                    "Probably some login entries were created on " \
                    "another node.\nTry executing iicvtgcn on another " \
                    "node to merge the other node's entries.\n\n", dcryptFail);
            else
                SIprintf("\n%d vnode(s) could not be decrypted.\n" \
                    "Probably the login file was created on " \
                    "another host.\nTry executing iicvtgcn on " \
                    "a different host.\n\n", dcryptFail);
        }

        if (!writeOutput)
        {
            if (srcOpened)
                SIclose(srcFile);
            srcOpened = FALSE;
            cleanup_queues();
            continue;
        }
   
        /*
        ** Open the destination file with special GCN_RACC_FILE flag, for 
        ** optimized writes.
        */
        if (clustered || clusterArg) 
        {
            if (named_file[i].add_cluster_node)
                STprintf( dstbuf, "II%s_%s", named_file[i].file, local_host);
            else
                STprintf(dstbuf, "II%s", named_file[i].file);
        }
        else
            STprintf( dstbuf, "II%s_%s", named_file[i].file, local_host);

        if (clusterArg && !named_file[i].add_cluster_node)
            rewrite = TRUE;

        LOfstfile( dstbuf, &loc );

        if (rewrite)
        {
            status = SIfopen( &loc, "rw", (i4)GCN_RACC_FILE, 
                sizeof( GCN_DB_REC0 ), &dstFile );
            if ( status != OK )
            {
                status = SIfopen( &loc, "w", (i4)GCN_RACC_FILE, 
                    sizeof( GCN_DB_REC0 ), &dstFile );
                if (status == OK)
                {
                    SIclose( dstFile);
                    status = SIfopen( &loc, "rw", (i4)GCN_RACC_FILE, 
                        sizeof( GCN_DB_REC0 ), &dstFile );
                }
            }
        }
        else
            status = SIfopen( &loc, "w", (i4)GCN_RACC_FILE, 
                sizeof( GCN_DB_REC0 ), &dstFile );

        if ( status != OK )
        {
            SIprintf( "iicvtgcn: Error opening %s, status is %x\n",dstbuf,
                status );
            goto cvt_exit;
        }

        dstOpened = TRUE;

        if (verboseArg)
            SIprintf("%s %s\n", rewrite ? "Rewriting " : "Writing ", dstbuf);

        /*
        ** If this is a merge operation (-c), login, attribute or
        ** node files may change the location of EOF, since the
        ** file to be merged may have different records than
        ** the destination file. 
        ** Before merging, the output file is read and fed into a queue.
        ** Then each merge record is compared to each output record.
        ** If the entire records match, nothing is done. 
        ** If a global login record matches only the vnode name
        ** global or private records will be added if not present;
        ** otherwise, nothing is done.
        ** Node or attribute records may be added if only one field
        ** fails to match.
        */
        status = SIfseek(dstFile, (i4)0, SI_P_START);
        if (rewrite)
        {
            while ( status == OK )
            {
                /*
                ** Read the source data and store in a queue for analysis.
                */
                status = SIread( dstFile, sizeof( GCN_DB_REC0 ),
                    &count, (PTR)&tmp_rec );
                if ( status == ENDFILE )
                    break;

                if ( status != OK )
                {
                    SIprintf("iicvtgcn: Error reading %s, status is %x\n",
                        dstbuf, status);
                    goto cvt_exit;
                }
                else if (tmp_rec.gcn_invalid && tmp_rec.gcn_tup_id != -1)
                    continue;
                else
                {
                    merge_q = (GCN_QUEUE *)MEreqmem(0, sizeof(GCN_QUEUE),0,NULL);
                    if (!merge_q)
                    {
                        SIprintf("iicvtgcn: Cannot allocate memory, exiting\n");
                        goto cvt_exit;
                    }
                    MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), 
                        (PTR)&merge_q->buf);
                    QUinsert(&merge_q->q, &merge_qhead);
    
                    /*
                    ** EOF record found.
                    */
                    if (merge_q->buf.gcn_tup_id == -1)
                        break;
                }
                if ( status == ENDFILE )
                    break;

            } /* while ( status == OK ) */

            /*
            ** Go through the input queue.  Compare each record with
            ** the output (merge) queue.  If the record is invalid
            ** or doesn't match, it's ignored.
            */
            dcryptFail = 0;
            total_recs = 0;
            for (q = gcn_qhead.q_prev; q != &gcn_qhead; q = q->q_prev)
            {
                SYSTIME     timestamp;

                gcn_q = (GCN_QUEUE *)q;
                if (gcn_q->buf.gcn_tup_id == -1)
                    break;
                if ( !gcn_merge_rec( gcn_q, isLogin ) )
                    continue;
                if (isLogin)
                {
                    /*
                    ** Login passwords get encrypted as V0 in a cluster
                    ** environment.
                    */
                    MEcopy((PTR)&gcn_q->buf, sizeof(GCN_DB_REC0), 
                        (PTR)&tmp_rec);
                    status = gcn_recrypt( TRUE, local_mask, 
                        gcn_q->buf.gcn_val, &v1DecryptErr, &writeOutput);

                    if (status != OK)
                    {
                        if (verboseArg)
                            SIprintf("Cannot decrypt password from " \
                                "vnode %s status %x\n", gcn_q->buf.gcn_obj,
                                status);
                        dcryptFail++;
                        MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), 
                            (PTR)&gcn_q->buf);
                        continue;                
                    }
                    if (v1DecryptErr)
                    {
                        if (verboseArg)
                            SIprintf("Cannot decrypt password from " \
                                "vnode %s\n", gcn_q->buf.gcn_obj);
                        dcryptFail++;
                        MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), 
                            (PTR)&gcn_q->buf);
                        continue;
                    }
                }
                merge_q = (GCN_QUEUE *)MEreqmem(0, sizeof(GCN_QUEUE),0,NULL);
                if (!merge_q)
                {
                    SIprintf("iicvtgcn: Cannot allocate memory, exiting\n");
                    goto cvt_exit;
                }

                MEcopy((PTR)&gcn_q->buf, sizeof(GCN_DB_REC0), 
                    (PTR)&merge_q->buf);
                total_recs++;
              
                QUinsert(&merge_q->q, &merge_qhead);
            }

            if (dcryptFail && verboseArg && isLogin)
            {
                if (clustered || unclusterArg )
                    SIprintf("\n%d vnode(s) could not be decrypted.\n" \
                        "Probably some login entries were created on " \
                        "another node.\nTry executing iicvtgcn on another " \
                        "node to merge the other node's entries.\n\n", 
                        dcryptFail);
                    else
                        SIprintf("\n%d vnode(s) could not be decrypted.\n" \
                            "Probably the login file was created on " \
                            "another host.\nTry executing iicvtgcn on " \
                            "a different host.\n\n", dcryptFail);
            }
            if (verboseArg)
                SIprintf("Total records merged: %d\n", total_recs);

            /*
            ** If no records to merge, clean up and continue.
            */
            if (!total_recs)
            {
                cleanup_queues();
                continue;
            }

            status = SIfseek(dstFile, (i4)0, SI_P_START);
            active_rec = 0;
            for (q = merge_qhead.q_prev; q != &merge_qhead; q = q->q_prev)
            {
                merge_q = (GCN_QUEUE *)q;
                if (verboseArg)
                   SIprintf("Rewriting %s record vnode %s val %s\n", 
                       !STcasecmp("*", merge_q->buf.gcn_uid) ? "global" : 
                       "private", merge_q->buf.gcn_obj, merge_q->buf.gcn_val);
                if (merge_q->buf.gcn_tup_id == -1)
                    continue;
                status = SIwrite(sizeof( GCN_DB_REC0 ), 
                    (char *)&merge_q->buf, &count, dstFile );
                if ( status != OK)
                {
                    SIprintf( "iicvtgcn: Failed to write file %s, " \
                        "status is %x\n", srcbuf, status );
                    goto cvt_exit;
                }
                active_rec++;
            }
            /*
            ** Write new EOF record.
            */
            tmp_rec.gcn_tup_id = -1;
            tmp_rec.gcn_l_uid = 0;
            tmp_rec.gcn_uid[0] = '\0';
            tmp_rec.gcn_l_obj = 0;
            tmp_rec.gcn_obj[0] = '\0';
            tmp_rec.gcn_l_val = 0;
            tmp_rec.gcn_val[0] = '\0';
            tmp_rec.gcn_invalid = TRUE;
            offset = active_rec * sizeof(GCN_DB_REC0);
            status = SIfseek(dstFile, (i4)offset, SI_P_START);
            status = SIwrite(sizeof( GCN_DB_REC0 ), (PTR)&tmp_rec, 
                &count, dstFile );
        }
        else
        {
            for (q = gcn_qhead.q_prev; q != &gcn_qhead; q = q->q_prev)
            {
                gcn_q = (GCN_QUEUE *)q;
                gcn_q->buf.gcn_l_val = STlength(gcn_q->buf.gcn_val);
                if (verboseArg)
                   SIprintf("Writing %s record vnode %s val %s\n", 
                       !STcasecmp("*", gcn_q->buf.gcn_uid) ? "global" : 
                       "private", gcn_q->buf.gcn_obj, gcn_q->buf.gcn_val);
                status = SIwrite(sizeof( GCN_DB_REC0 ), (char *)&gcn_q->buf, 
                    &count, dstFile );
                if ( status != OK)
                {
                    SIprintf( "iicvtgcn: Failed to write file %s, " \
                        "status is %x\n", srcbuf, status );
                    goto cvt_exit;
                }
            }
        }  /* if (rewrite) */


        cleanup_queues();

        SIclose( srcFile );
        srcOpened = FALSE;
        SIclose( dstFile );
        dstOpened = FALSE;

    } /* for (i = 0; i < NBR_NAMED_FILES; i++ ) */

cvt_exit:

    cleanup_queues();

    if (srcOpened)
        SIclose(srcFile);
    if (dstOpened)
        SIclose(dstFile);
    PCexit( OK );
}
Exemple #5
0
static VOID
gcn_nq_filename( char *type, char *host, char *filename )
{
    i4		len, plen, slen;
    char        *onOff = NULL;
    bool        clustered = FALSE;
    STATUS      status;

    /*
    ** Filename template: II<type>[_<host>]
    */
    plen = 2;
    len = STlength( type );
    slen = (host && *host) ? STlength( host ) + 1 : 0;

    /*
    ** Adjust filename for platform limitations:
    **   drop prefix if type and suffix OK;
    **   drop suffix if prefix and type OK;
    **   otherwise, drop both prefix and suffix.
    */
    if ( plen + len + slen > LO_NM_LEN )
        if ( len + slen <= LO_NM_LEN )
            plen = 0;
        else  if ( plen + len <= LO_NM_LEN )
            slen = 0;
        else
            plen = slen = 0;

    /*
    ** See if this is a clustered installation.  If it is,
    ** the node, login, and attribute files have no file extension.
    */
    if ( PMload( (LOCATION *)NULL, (PM_ERR_FUNC *)NULL ) != OK )
    {
        SIprintf("Error reading config.dat\n");
        return;
    }

    PMsetDefault( 0, "ii" );
    PMsetDefault( 1, host );
    PMsetDefault( 2, ERx("gcn") );

    status = PMget( ERx("!.cluster_mode"), &onOff);

    if (onOff && *onOff)
        clustered = !STncasecmp(onOff, "ON", STlength(onOff));

    if (clustered && (!STncasecmp("LOGIN", type, STlength(type)) ||
                      !STncasecmp("NODE", type, STlength(type)) ||
                      !STncasecmp("ATTR", type, STlength(type))))
        slen = 0;

    CVupper(type);

    STprintf( filename, "%s%s%s%s",
              plen ? "II" : "", type, slen ? "_" : "", slen ? host : "" );

    /*
    ** Finally, truncate the filename if it is too long
    ** (hopefully this will never happen).
    */
    if ( STlength( filename ) > LO_NM_LEN )
        filename[ LO_NM_LEN ] = '\0';

    return;
}