Exemplo n.º 1
0
/**
 * Creates a Authorization Session for the Server, from the application specific Session starting request
 * It generates a new id and adds the session to the cdp list of sessions
 * \note Returns with a lock on AAASession->hash. Unlock when done working with the result
 * @returns the new AAASession or null on error
 */
AAASession* AAACreateServerAuthSession(AAAMessage *msg,int is_statefull,AAASessionCallback_f *cb,void *generic_data)
{
	AAASession *s;
	str id;

	if (!msg||!msg->sessionId||!msg->sessionId->data.len){
		LM_ERR("Error retrieving the Session-Id from the message.\n");
		return 0;
	}
	id.s = shm_malloc(msg->sessionId->data.len);
	if (!id.s){
		LM_ERR("Error allocating %d bytes of shm!\n",msg->sessionId->data.len);
		return 0;
	}else{
		id.len = msg->sessionId->data.len;
		memcpy(id.s,msg->sessionId->data.s,id.len);
		s=cdp_new_auth_session(id,0,is_statefull);
		if (s) {
			s->u.auth.generic_data = generic_data;
			s->cb = cb;
			if (s->cb)
				(s->cb)(AUTH_EV_SESSION_CREATED,s);
			update_auth_session_timers(&(s->u.auth),msg);
			auth_server_statefull_sm_process(s,AUTH_EV_RECV_REQ,msg);
			// this is a special exception where the session lock is not released
			//s=0;
		}
	}
	return s;
}
Exemplo n.º 2
0
/**
 * Authorization Server State-Machine - Statefull
 * \Note - should be called with a lock on the session and will unlock it - do not use it after!
 * @param s
 * @param event
 * @param msg
 */
inline void auth_server_statefull_sm_process(cdp_session_t* s, int event, AAAMessage* msg) {
    cdp_auth_session_t *x;

    if (!s) return;
    x = &(s->u.auth);

    if (s->cb) (s->cb)(event, s);
    LM_DBG("after callback for event %i\n", event);

    switch (x->state) {
        case AUTH_ST_IDLE:
            switch (event) {
                case AUTH_EV_RECV_STR:
                    break;
                case AUTH_EV_RECV_REQ:
                    // The RequestHandler will generate a Send event for the answer
                    // and we will only then now if the user is authorised or not
                    // if its not authorised it will move back to idle and cleanup the session
                    // so no big deal
                    // but this is not the Diameter RFC...
                    x->state = AUTH_ST_OPEN;
                    // execute the cb here because we won't have a chance later
                    if (s->cb) (s->cb)(AUTH_EV_SESSION_MODIFIED, s);
                    // Don't unlock the session hash table because the session is returned to the user
                    // This can only be called from the AAACreateServerAuthSession()!
                    s = 0;
                    break;
                case AUTH_EV_SEND_STA:
                    x->state = AUTH_ST_IDLE;
                    cdp_session_cleanup(s, msg);
                    s = 0;
                    break;

                    /* Just in case we have some lost sessions */
                case AUTH_EV_SESSION_TIMEOUT:
                case AUTH_EV_SESSION_GRACE_TIMEOUT:
                    cdp_session_cleanup(s, msg);
                    s = 0;
                    break;

                default:
                    LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!\n",
                            event, auth_states[x->state]);
            }
            break;

        case AUTH_ST_OPEN:


            if (event == AUTH_EV_SEND_ANS && msg && !is_req(msg)) {
                int rc = get_result_code(msg);
                if (rc >= 2000 && rc < 3000)
                    event = AUTH_EV_SEND_ANS_SUCCESS;
                else
                    event = AUTH_EV_SEND_ANS_UNSUCCESS;
            }


            switch (event) {
                case AUTH_EV_RECV_STR:
                    break;
                case AUTH_EV_SEND_ANS_SUCCESS:
                    x->state = AUTH_ST_OPEN;
                    update_auth_session_timers(x, msg);
                    add_auth_session_timers(x, msg);
                    break;
                case AUTH_EV_SEND_ANS_UNSUCCESS:
                    x->state = AUTH_ST_IDLE;
                    cdp_session_cleanup(s, msg);
                    s = 0;
                    break;
                case AUTH_EV_SEND_ASR:
                    x->state = AUTH_ST_DISCON;
                    break;
                case AUTH_EV_SESSION_TIMEOUT:
                case AUTH_EV_SESSION_GRACE_TIMEOUT:
                    x->state = AUTH_ST_IDLE;
                    LM_DBG("before session cleanup\n");
                    cdp_session_cleanup(s, msg);
                    s = 0;
                    break;
                case AUTH_EV_SEND_STA:
                    LM_ERR("SENDING STA!!!\n");
                    x->state = AUTH_ST_IDLE;
                    cdp_session_cleanup(s, msg);
                    s = 0;
                    break;
                default:
                    LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!\n",
                            event, auth_states[x->state]);
            }
            break;

        case AUTH_ST_DISCON:
            switch (event) {
                case AUTH_EV_RECV_STR:
                    break;
                case AUTH_EV_RECV_ASA:
                case AUTH_EV_RECV_ASA_SUCCESS:
                    x->state = AUTH_ST_IDLE;
                    //cdp_session_cleanup(s,msg);
                    break;
                case AUTH_EV_RECV_ASA_UNSUCCESS:
                    Send_ASR(s, msg);
                    // how many times will this be done?
                    x->state = AUTH_ST_DISCON;
                    break;
                case AUTH_EV_SEND_STA:
                    x->state = AUTH_ST_IDLE;
                    cdp_session_cleanup(s, msg);
                    s = 0;
                    break;
                default:
                    LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!\n",
                            event, auth_states[x->state]);
            }
            break;

        default:
            LM_ERR("auth_client_statefull_sm_process(): Received event %d while in invalid state %d!\n",
                    event, x->state);
    }
    if (s) {
        if (s->cb) (s->cb)(AUTH_EV_SESSION_MODIFIED, s);
        AAASessionsUnlock(s->hash);
    }
}
Exemplo n.º 3
0
/**
 * stateful client state machine
 * \Note - should be called with a lock on the session and will unlock it - do not use it after!
 * @param auth - AAAAuthSession which uses this state machine
 * @param ev   - Event
 * @param msg  - AAAMessage
 * @returns 0 if msg should be given to the upper layer 1 if not
 */
inline int auth_client_statefull_sm_process(cdp_session_t* s, int event, AAAMessage* msg) {

    cdp_auth_session_t *x;
    int rc;
    int rv = 0; //return value

    if (!s) {
        switch (event) {
            case AUTH_EV_RECV_ASR:
                Send_ASA(0, msg);
                break;
            default:
                LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d with no session!\n",
                        event);
        }
        return rv;
    }
    x = &(s->u.auth);

    if (s->cb) (s->cb)(event, s);
    LM_INFO("after callback of event %i\n", event);

    //if (x && x->state && msg) LM_ERR("auth_client_statefull_sm_process [event %i] [state %i] endtoend %u hopbyhop %u\n",event,x->state,msg->endtoendId,msg->hopbyhopId);

    switch (x->state) {
        case AUTH_ST_IDLE:
            switch (event) {
                case AUTH_EV_SEND_REQ:
                    s->application_id = msg->applicationId;
                    s->u.auth.state = AUTH_ST_PENDING;
                    update_auth_session_timers(x, msg);
                    add_auth_session_timers(x, msg);

                    //Richard add this add: add destination realm to cdp session
                    //use msg origin realm as the destination realm
                    //we do this here as this is were the state changes to open
                    //Where must we free this?
                    s->dest_realm.s = (char*) shm_malloc(msg->dest_realm->data.len);
                    memcpy(s->dest_realm.s, msg->dest_realm->data.s, msg->dest_realm->data.len);
                    s->dest_realm.len = msg->dest_realm->data.len;


                    //LM_INFO("state machine: i was in idle and i am going to pending\n");
                    break;
                default:
                    LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!(data %p)\n",
                            event, auth_states[x->state], x->generic_data);
            }
            break;

        case AUTH_ST_PENDING:
            if (event == AUTH_EV_RECV_ANS && msg && !is_req(msg)) {
                rc = get_result_code(msg);
                if (rc >= 2000 && rc < 3000 && get_auth_session_state(msg) == STATE_MAINTAINED)
                    event = AUTH_EV_RECV_ANS_SUCCESS;
                else
                    event = AUTH_EV_RECV_ANS_UNSUCCESS;
            }

            switch (event) {
                case AUTH_EV_RECV_ANS_SUCCESS:
                    x->state = AUTH_ST_OPEN;
                    update_auth_session_timers(x, msg);
                    //LM_INFO("state machine: i was in pending and i am going to open\n");
                    break;
                case AUTH_EV_RECV_ANS_UNSUCCESS:
                    LM_DBG("In state AUTH_ST_PENDING and received AUTH_EV_RECV_ANS_UNSUCCESS - nothing to do but clean up session\n");
                case AUTH_EV_SESSION_TIMEOUT:
                case AUTH_EV_SERVICE_TERMINATED:
                case AUTH_EV_SESSION_GRACE_TIMEOUT:
                    cdp_session_cleanup(s, NULL);
                    s = 0;
                    break;

                default:
                    LM_ERR("auth_client_stateless_sm_process(): Received invalid event %d while in state %s!\n",
                            event, auth_states[x->state]);
            }
            break;

        case AUTH_ST_OPEN:
            if (event == AUTH_EV_RECV_ANS && msg && !is_req(msg)) {
                rc = get_result_code(msg);
                if (rc >= 2000 && rc < 3000 && get_auth_session_state(msg) == STATE_MAINTAINED)
                    event = AUTH_EV_RECV_ANS_SUCCESS;
                else
                    event = AUTH_EV_RECV_ANS_UNSUCCESS;
            }

            switch (event) {
                case AUTH_EV_SEND_REQ:
                    // if the request is STR i should move to Discon ..
                    // this is not in the state machine but I (Alberto Diez) need it
                    if (msg->commandCode == IMS_STR)
                        s->u.auth.state = AUTH_ST_DISCON;
                    else {
                        s->u.auth.state = AUTH_ST_OPEN;
                        add_auth_session_timers(x, msg);
                    }
                    break;

                case AUTH_EV_RECV_ANS_SUCCESS:
                    x->state = AUTH_ST_OPEN;
                    update_auth_session_timers(x, msg);
                    //LM_INFO("state machine: i was in open and i am going to open\n");
                    break;

                case AUTH_EV_RECV_ANS_UNSUCCESS:
                    x->state = AUTH_ST_DISCON;
                    //LM_INFO("state machine: i was in open and i am going to discon\n");
                    break;

                case AUTH_EV_SESSION_TIMEOUT:
                case AUTH_EV_SERVICE_TERMINATED:
                case AUTH_EV_SESSION_GRACE_TIMEOUT:
                    x->state = AUTH_ST_DISCON;
                    //LM_INFO("state machine: i was in open and i am going to discon\n");

                    Send_STR(s, msg);
                    break;

                case AUTH_EV_SEND_ASA_SUCCESS:
                    x->state = AUTH_ST_DISCON;
                    //LM_INFO("state machine: i was in open and i am going to discon\n");
                    Send_STR(s, msg);
                    break;

                case AUTH_EV_SEND_ASA_UNSUCCESS:
                    x->state = AUTH_ST_OPEN;
                    update_auth_session_timers(x, msg);
                    //LM_INFO("state machine: i was in open and i am going to open\n");
                    break;

                case AUTH_EV_RECV_ASR:
                    // two cases , client will comply or will not
                    // our client is very nice and always complys.. because
                    // our brain is in the PCRF... if he says to do this , we do it
                    // Alberto Diez , (again this is not Diameter RFC)
                    x->state = AUTH_ST_DISCON;
                    Send_ASA(s, msg);
                    Send_STR(s, msg);
                    break;

                default:
                    LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!\n",
                            event, auth_states[x->state]);
            }
            break;

        case AUTH_ST_DISCON:
            switch (event) {
                case AUTH_EV_RECV_ASR:
                    x->state = AUTH_ST_DISCON;
                    //LM_INFO("state machine: i was in discon and i am going to discon\n");
                    Send_ASA(s, msg);
                    break;

                    // Just added this because it might happen if the other peer doesnt
                    // send a valid STA, then the session stays open forever...
                    // We dont accept that... we have lifetime+grace_period for that
                    // This is not in the Diameter RFC ...
                case AUTH_EV_SESSION_TIMEOUT:
                case AUTH_EV_SESSION_GRACE_TIMEOUT:
                    // thats the addition
                case AUTH_EV_RECV_STA:
                    x->state = AUTH_ST_IDLE;
                    LM_INFO("state machine: AUTH_EV_RECV_STA about to clean up\n");
                    if (msg) AAAFreeMessage(&msg); // if might be needed in frequency
                    // If I register a ResponseHandler then i Free the STA there not here..
                    // but i dont have interest in that now..
                    cdp_session_cleanup(s, NULL);
                    s = 0;
                    rv = 1;
                    break;

                default:
                    LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!\n",
                            event, auth_states[x->state]);
            }
            break;
        default:
            LM_ERR("auth_client_statefull_sm_process(): Received event %d while in invalid state %d!\n",
                    event, x->state);
    }
    if (s) {
        if (s->cb) (s->cb)(AUTH_EV_SESSION_MODIFIED, s);
        AAASessionsUnlock(s->hash);
    }
    return rv;
}