void authenticator_fsm(auth_t* auth_1x)
{
    /* Change the state to AS_INITAILIZE if portControl is set to AUTO and   */
    /* other variables are appropriately set.                                */
    if(((auth_1x->global.portControl == AUTO)  &&
        (auth_1x->auth_pae.portMode   !=
         auth_1x->global.portControl))          ||
        (auth_1x->global.initialize   == BTRUE) ||
        (auth_1x->global.portEnabled  == BFALSE))
    {
        auth_initialize(auth_1x);
        return;
    }

    /* Transition to AS_FORCE_AUTH and AS_FORCE_UNAUTH may happen from any   */
    /* state. Hence the conditions for these transitions are checked here.   */

    /* Change the state to AS_FORCE_AUTH if portControl is set to            */
    /* FORCE_AUTHORIZED and other variables are appropriately set.           */
    if((auth_1x->global.portControl == FORCE_AUTHORIZED) &&
       (auth_1x->auth_pae.portMode  !=
        auth_1x->global.portControl)                     &&
       ((auth_1x->global.initialize == BFALSE) ||
       (auth_1x->global.portEnabled  == BTRUE)))
    {
        auth_force_auth(auth_1x);
    }
    /* Change the state to AS_FORCE_UNAUTH if portControl is set to          */
    /* FORCE_UNAUTHORIZED and other variables are appropriately set.         */
    else if((auth_1x->global.portControl == FORCE_UNAUTHORIZED) &&
       (auth_1x->auth_pae.portMode  !=
        auth_1x->global.portControl)                       &&
       ((auth_1x->global.initialize == BFALSE) ||
       (auth_1x->global.portEnabled  == BTRUE)))
    {
        auth_force_unauth(auth_1x);
    }


    switch(auth_1x->auth_pae.state)
    {
    case AS_INITIALIZE:
    {
        /* Change the state unconditionally to AS_DISCONNECTED */
        auth_disconnected(auth_1x);
    } /* End of case AS_INITIALIZE: */
    break;

    case AS_DISCONNECTED:
    {
        auth_connecting(auth_1x);
    }
    break;

    case AS_CONNECTING:
    {
        /* Change the state to AS_DISCONNECTED only if reAuthentication      */
        /* count has exceeded limit or an eapolLogoff message is received.   */
        if((auth_1x->auth_pae.eapolLogoff == BTRUE) ||
           ((auth_1x->auth_pae.reAuthCount > auth_1x->auth_pae.reAuthMax) &&
           (auth_1x->global.txWhenTimeout == BTRUE)))
        {
            auth_1x->auth_pae.authEapLogoffsWhileConnecting++;

            auth_disconnected(auth_1x);
        }
        /* If the retransmission limit is not reached and the time out has   */
        /* occured, re transmit the message to the Supplicant                */
        else if((auth_1x->auth_pae.reAuthCount <= auth_1x->auth_pae.reAuthMax)
                && (auth_1x->global.txWhenTimeout  == BTRUE))
        {
            auth_connecting(auth_1x);
        }

        /* Also, In the event of any reauthentication or if the EAPOL Start  */
        /* has been received in this state the ReqId message is resent to    */
        /* the Supplicant state machine                                      */
        else if((auth_1x->auth_pae.reAuthCount <= auth_1x->auth_pae.reAuthMax)
                && ((auth_1x->auth_pae.eapolStart   == BTRUE) ||
                    (auth_1x->global.reAuthenticate == BTRUE)))
        {
            auth_1x->auth_pae.reAuthCount = 0;
            auth_connecting(auth_1x);
        }

        /* Change the state to AS_AUTHENTICATING only if a EAP message is to */
        /* be sent from higher layer and reAuthentication count has not      */
        /* exceeded the limit. Also an indication of Authentication Success/ */
        /* Failure from the higher layers initiates a change of state.       */
        else if((auth_1x->auth_pae.rxRespId == BTRUE)  &&
                (auth_1x->auth_pae.reAuthCount <= auth_1x->auth_pae.reAuthMax))
        {
            auth_1x->auth_pae.authEntersAuthenticating++;

            auth_authenticating(auth_1x);
        }
        /* If a packet was ignored, restart the timer */
        else if((auth_1x->auth_pae.rxRespId   == BTRUE) ||
                (auth_1x->auth_pae.eapolStart == BTRUE))
        {
            auth_1x->auth_pae.authEapLogoffsWhileConnecting++;

            auth_disconnected(auth_1x);
        }
        else
        {
            /* No state change is required */
        }
    } /* End of case AS_CONNECTING: */
    break;

    case AS_AUTHENTICATING:
    {
        /* Change the state to AS_AUTHENTICATED only if authentication       */
        /* process successful along with portValid is TRUE (after            */
        /* establishing secure communication channel between authenticator   */
        /* and supplicant - after key exchanges in 802.11).                  */
        if(auth_1x->global.authSuccess == BTRUE &&
           auth_1x->global.portValid   == BTRUE)
        {
            auth_1x->auth_pae.authAuthSuccessesWhileAuthenticating ++;

            auth_authenticated(auth_1x);
        }
        /* Change the state to AS_ABORTING if any of the messages namely,    */
        /* eapolStart, eapolLogoff or authTimeout has arrived.               */
        else if((auth_1x->auth_pae.eapolStart  == BTRUE) ||
                (auth_1x->auth_pae.eapolLogoff == BTRUE) ||
                (auth_1x->global.authTimeout   == BTRUE))
        {
            if(auth_1x->global.authTimeout == BTRUE)
                auth_1x->auth_pae.authAuthTimeoutsWhileAuthenticating++;
            else if(auth_1x->auth_pae.eapolStart == BTRUE)
                auth_1x->auth_pae.authAuthEapStartsWhileAuthenticating++;
            else if(auth_1x->auth_pae.eapolLogoff== BTRUE)
                auth_1x->auth_pae.authAuthEapLogoffWhileAuthenticating++;

            auth_aborting(auth_1x);
        }
        /* Change the state to AS_HELD only if Authentication fails for the  */
        /* port or portValid is FALSE (after key state machine indicates if  */
        /* portValid can be tested.                                          */
        else if((auth_1x->global.authFail   == BTRUE) ||
                ((auth_1x->global.keyDone   == BTRUE) &&
                 (auth_1x->global.portValid == BFALSE)))
        {
            auth_1x->auth_pae.authAuthFailWhileAuthenticating++;

            auth_held(auth_1x);
        }
        else
        {
            /* No state change is required */
        }
    } /* End of case AS_AUTHENTICATING: */
    break;

    case AS_AUTHENTICATED:
    {
        /* Change the state to AS_RESTART if eapolStart or reauthenticate    */
        /* message arrives.                                                  */
        if((auth_1x->auth_pae.eapolStart   == BTRUE) ||
           (auth_1x->global.reAuthenticate == BTRUE))
        {
            if(auth_1x->global.reAuthenticate == BTRUE)
                auth_1x->auth_pae.authAuthReauthsWhileAuthenticated++;
            else if(auth_1x->auth_pae.eapolStart == BTRUE)
                auth_1x->auth_pae.authAuthEapStartsWhileAuthenticated++;

            auth_connecting(auth_1x);
        }
        /* Change the state to AS_DISCONNECTED if either eapolLoff message   */
        /* comes or portValid is FALSE.                                      */
        else if((auth_1x->auth_pae.eapolLogoff == BTRUE) ||
                (auth_1x->global.portValid     == BFALSE))
        {
            auth_1x->auth_pae.authAuthEapLogoffWhileAuthenticated++;

            auth_disconnected(auth_1x);
        }
        else
        {
            /* No state change is required */
        }
    } /* End of case AS_AUTHENTICATED: */
    break;

    case AS_ABORTING:
    {
        /* Change the state to AS_RESTART if eapolLogoff arrives or          */
        /* authAbort is reset by Authentication backend state machine.       */
        if((auth_1x->auth_pae.eapolLogoff == BFALSE) &&
           (auth_1x->global.authAbort     == BFALSE))
        {
            auth_connecting(auth_1x);
        }
        /* Change the state to AS_DISCONNECTED if either eapolLoff message   */
        /* comes or authAbort is reset by the Authentication backend state   */
        /* machine.                                                          */
        else if((auth_1x->auth_pae.eapolLogoff == BTRUE)  &&
                (auth_1x->global.authAbort     == BFALSE))
        {
            auth_disconnected(auth_1x);
        }
        else
        {
            /* No state change is required */
        }
    } /* End of case AS_ABORTING: */
    break;

    case AS_HELD:
    {
        /* Change the state to AS_RESTART after quietWhile timer expires     */
        if(auth_1x->global.quietWhileTimeout == BTRUE)
        {
            auth_connecting(auth_1x);
        }
        else
        {
            /* No state change is required */
        }
    } /* End of case AS_HELD: */
    break;

    case AS_FORCE_AUTH:
    {
        /* Remain in AS_FORCE_AUTH state. However, execute the function      */
        /* again only if EAPOL PDU carrying EAPOL-Start is received.         */
        if(auth_1x->auth_pae.eapolStart == BTRUE)
        {
            auth_force_auth(auth_1x);
        }
        else
        {
            /* No state change is required */
        }
    }
    break;

    case AS_FORCE_UNAUTH:
    {
        /* Remain in AS_FORCE_UNAUTH state. However, execute the function    */
        /* again only if EAPOL PDU carrying EAPOL-Start is received.         */
        if(auth_1x->auth_pae.eapolStart == BTRUE)
        {
            auth_force_unauth(auth_1x);
        }
        else
        {
            /* No state change is required */
        }
    }
    break;

    default:
    {
        /* Do nothing */
    }
    } /* End of switch(auth_1x->auth_pae.state) */
}
示例#2
0
/*
 * The main routine - parses command line and calls action procedures
 */
int
main (int argc, char *argv[])
{
    int i;
    const char *sourcename = defsource;
    char **arglist = defcmds;
    int nargs = ndefcmds;
    int status;

    ProgramName = argv[0];

    for (i = 1; i < argc; i++) {
	const char *arg = argv[i];

	if (arg[0] == '-') {
	    const char *flag;

	    for (flag = (arg + 1); *flag; flag++) {
		switch (*flag) {
		  case 'f':		/* -f authfilename */
		    if (++i >= argc) usage ();
		    authfilename = argv[i];
		    continue;
		  case 'v':		/* -v */
		    verbose = 1;
		    continue;
		  case 'q':		/* -q */
		    verbose = 0;
		    continue;
		  case 'b':		/* -b */
		    break_locks = True;
		    continue;
		  case 'i':		/* -i */
		    ignore_locks = True;
		    continue;
		  default:
		    usage ();
		}
	    }
	} else {
	    sourcename = "(argv)";
	    nargs = argc - i;
	    arglist = argv + i;
	    if (verbose == -1) verbose = 0;
	    break;
	}
    }

    if (verbose == -1) {		/* set default, don't junk stdout */
	verbose = (isatty(fileno(stdout)) != 0);
    }

    if (!authfilename) {
	authfilename = IceAuthFileName ();	/* static name, do not free */
	if (!authfilename) {
	    fprintf (stderr,
		     "%s:  unable to generate an authority file name\n",
		     ProgramName);
	    exit (1);
	}
    }
    if (auth_initialize (authfilename) != 0) {
	/* error message printed in auth_initialize */
	exit (1);
    }

    status = process_command (sourcename, 1, nargs, arglist);

    (void) auth_finalize ();
    exit ((status != 0) ? 1 : 0);
}