Esempio n. 1
0
/*
 *	Find existing session if any which matches the State variable in current AccessRequest
 *	Then, release the session from the list, and return it to
 *	the caller.
 *
 */
SECURID_SESSION *securid_sessionlist_find(rlm_securid_t *inst, REQUEST *request)
{
	VALUE_PAIR	*state;
	SECURID_SESSION* session;
	SECURID_SESSION mySession;
	
	/* clean expired sessions if any */
	pthread_mutex_lock(&(inst->session_mutex));
	securid_sessionlist_clean_expired(inst, request, request->timestamp);
	pthread_mutex_unlock(&(inst->session_mutex));

	/*
	 *	We key the sessions off of the 'state' attribute
	 */
	state = pairfind(request->packet->vps, PW_STATE, 0, TAG_ANY);
	if (!state) {
		return NULL;
	}

	if (state->length != SECURID_STATE_LEN) {
		radlog(L_ERR,"rlm_securid: Invalid State variable. length=%d",state->length);
		return NULL;
	}

	memset(&mySession,0,sizeof(mySession));
	mySession.src_ipaddr = request->packet->src_ipaddr;
	memcpy(mySession.state, state->vp_strvalue, sizeof(mySession.state));

	/*
	 *	Playing with a data structure shared among threads
	 *	means that we need a lock, to avoid conflict.
	 */
	pthread_mutex_lock(&(inst->session_mutex));
	session = securid_sessionlist_delete(inst, &mySession);
	pthread_mutex_unlock(&(inst->session_mutex));

	/*
	 *	Might not have been there.
	 */
	if (!session) {
		radlog(L_ERR,"rlm_securid: No SECURID session matching the State variable.");
		return NULL;
	}

	RDEBUG2("Session found identity='%s' state='%s', released from the list",
			 SAFE_STR(session->identity),session->state);
	if (session->trips >= inst->max_trips_per_session) {
		RDEBUG2("More than %d authentication packets for this SECURID session.  Aborted.",inst->max_trips_per_session);
		securid_session_free(inst,request,session);
		return NULL;
	}
	session->trips++;

	return session;
}
Esempio n. 2
0
void securid_sessionlist_free(rlm_securid_t *inst,REQUEST *request)
{
	SECURID_SESSION *node, *next;

	pthread_mutex_lock(&(inst->session_mutex));

       	for (node = inst->session_head; node != NULL; node = next) {
		next = node->next;
		securid_session_free(inst,request,node);
	}

	inst->session_head = inst->session_tail = NULL;

	pthread_mutex_unlock(&(inst->session_mutex));
}
Esempio n. 3
0
static void securid_sessionlist_clean_expired(rlm_securid_t *inst, REQUEST *request, time_t timestamp)
{
	int num_sessions;
	SECURID_SESSION *session;

	num_sessions = rbtree_num_elements(inst->session_tree);
	RDEBUG2("There are %d sessions in the tree\n",num_sessions);

	/*
	 *	Delete old sessions from the list
	 *
	 */
       	while((session = inst->session_head)) {
		if ((timestamp - session->timestamp) > inst->timer_limit) {
			rbnode_t *node;
			node = rbtree_find(inst->session_tree, session);
			rad_assert(node != NULL);
			rbtree_delete(inst->session_tree, node);

			/*
			 *	session == inst->session_head
			 */
			inst->session_head = session->next;
			if (session->next) {
				session->next->prev = NULL;
			} else {
				inst->session_head = NULL;
				inst->session_tail = NULL;
			}

			RDEBUG2("Cleaning expired session: identity='%s' state='%s'\n",
					  SAFE_STR(session->identity),session->state);
			securid_session_free(inst,request,session);
		} else {
			/* no need to check all sessions since they are sorted by age */
			break;
		}
	}
}
Esempio n. 4
0
static SECURID_AUTH_RC securidAuth(void *instance, REQUEST *request,
				   const char* username, 
				   const char* passcode,
				   char* replyMsgBuffer,int replyMsgBufferSize)
{
	rlm_securid_t *inst = (rlm_securid_t *) instance;
	int         acmRet;
	SD_PIN pinParams;
	char newPin[10];
	char format[30];
	SECURID_SESSION *pSecurid_session=NULL;
	int rc=-1;

	if (!username) {
		radlog(L_ERR, "SecurID username is NULL");
		return RC_SECURID_AUTH_FAILURE;		
	}

	if (!passcode) {
		radlog(L_ERR, "SecurID passcode is NULL for %s user",username);
		return RC_SECURID_AUTH_FAILURE;		
	}

	*replyMsgBuffer = '\0';

	pSecurid_session = securid_sessionlist_find(inst,request);
	if (pSecurid_session == NULL) {
		/* securid session not found */
		SDI_HANDLE  sdiHandle = SDI_HANDLE_NONE;

		acmRet = SD_Init(&sdiHandle);
		if (acmRet != ACM_OK) {
			radlog(L_ERR, "Cannot communicate with the ACE/Server");
			return -1;
		}

		acmRet = SD_Lock(sdiHandle, (SD_CHAR*)username);
		if (acmRet != ACM_OK) {
			radlog(L_ERR,"SecurID: Access denied. Name [%s] lock failed.",username);
			return -2;
		}

		acmRet = SD_Check(sdiHandle, (SD_CHAR*) passcode,
				  (SD_CHAR*) username);
		switch (acmRet) {
		case ACM_OK:
			/* we are in now */
			RDEBUG("SecurID authentication successful for %s.",
			       username);
			SD_Close(sdiHandle);

			return RC_SECURID_AUTH_SUCCESS;

		case ACM_ACCESS_DENIED:         
			/* not this time */
			RDEBUG("SecurID Access denied for %s", username);
			SD_Close(sdiHandle);
			return RC_SECURID_AUTH_ACCESS_DENIED_FAILURE;

		case ACM_INVALID_SERVER:
			radlog(L_ERR,"SecurID: Invalid ACE server.");
			return RC_SECURID_AUTH_INVALID_SERVER_FAILURE;

		case ACM_NEW_PIN_REQUIRED:
			RDEBUG2("SeecurID new pin required for %s",
				username);

			/* create a new session */
			pSecurid_session = securid_session_alloc();
			pSecurid_session->sdiHandle = sdiHandle; /* save ACE handle for future use */
			pSecurid_session->securidSessionState = NEW_PIN_REQUIRED_STATE;
			pSecurid_session->identity = strdup(username);
			 
			/* Get PIN requirements */
			acmRet = AceGetPinParams(sdiHandle, &pinParams);
			 
			/* If a system-generated PIN is required */
			if (pinParams.Selectable == CANNOT_CHOOSE_PIN) {
				/* Prompt user to accept a system generated PIN */
				snprintf(replyMsgBuffer, replyMsgBufferSize,
					 "\r\nAre you prepared to accept a new system-generated PIN [y/n]?");
				pSecurid_session->securidSessionState = NEW_PIN_SYSTEM_ACCEPT_STATE;

			} else if (pinParams.Selectable == USER_SELECTABLE) { //may be returned by AM 6.x servers.
				snprintf(replyMsgBuffer, replyMsgBufferSize,
					 "\r\nPress 'y' to generate a new PIN\r\nOR\r\n'n'to enter a new PIN yourself [y/n]");
				pSecurid_session->securidSessionState = NEW_PIN_USER_SELECT_STATE;

			} else {
				if (pinParams.Alphanumeric) {
					strcpy(format, "alphanumeric characters");
				} else {
					strcpy(format, "digits");
				}
				snprintf(replyMsgBuffer, replyMsgBufferSize,
					 " \r\n   Enter your new PIN of %d to %d %s,\r\n                or\r\n   <Ctrl-D> to cancel the New PIN procedure:",
					 pinParams.Min, pinParams.Max, format);
			}

			/* insert new session in the session list */
			securid_sessionlist_add(inst,request,pSecurid_session);
			 
			return RC_SECURID_AUTH_CHALLENGE;

		case ACM_NEXT_CODE_REQUIRED:
			RDEBUG2("Next securid token code required for %s",
				username);

			/* create a new session */
			pSecurid_session = securid_session_alloc();
			pSecurid_session->sdiHandle = sdiHandle;
			pSecurid_session->securidSessionState = NEXT_CODE_REQUIRED_STATE;
			pSecurid_session->identity = strdup(username);

			/* insert new session in the session list */
			securid_sessionlist_add(inst,request,pSecurid_session);
		     
			strlcpy(replyMsgBuffer, "\r\nPlease Enter the Next Code from Your Token:", replyMsgBufferSize);
			return RC_SECURID_AUTH_CHALLENGE;
		default:
			radlog(L_ERR,"SecurID: Unexpected error from ACE/Agent API acmRet=%d",acmRet);
			return RC_SECURID_AUTH_FAILURE;
  
			
		}
	} else {
		/* existing session found */
		RDEBUG("Continuing previous session found for user [%s]",username);

		/* continue previous session */
		switch (pSecurid_session->securidSessionState) {
		case NEXT_CODE_REQUIRED_STATE:
			DEBUG2("Securid NEXT_CODE_REQUIRED_STATE: User [%s]",username);
			/* next token code mode */

			acmRet = SD_Next(pSecurid_session->sdiHandle, (SD_CHAR*)passcode);
			if (acmRet == ACM_OK) {
				radlog(L_INFO,"Next SecurID token accepted for [%s].",pSecurid_session->identity);
				rc = RC_SECURID_AUTH_SUCCESS;

			} else {
				radlog(L_INFO,"SecurID: Next token rejected for [%s].",pSecurid_session->identity);
				rc = RC_SECURID_AUTH_FAILURE;
			}

			/* deallocate session */
			securid_session_free(inst,request,pSecurid_session);
			return rc;

		case NEW_PIN_REQUIRED_STATE:
			RDEBUG2("SecurID NEW_PIN_REQUIRED_STATE for %s",
				username);

			/* save the previous pin */
			if (pSecurid_session->pin) {
				free(pSecurid_session->pin);
				pSecurid_session->pin = NULL;
			}
			pSecurid_session->pin = strdup(passcode);

			strlcpy(replyMsgBuffer,"\r\n                 Please re-enter new PIN:", replyMsgBufferSize);

			/* set next state */
			pSecurid_session->securidSessionState = NEW_PIN_USER_CONFIRM_STATE;

			/* insert the updated session in the session list */
			securid_sessionlist_add(inst,request,pSecurid_session);
			return RC_SECURID_AUTH_CHALLENGE;
			  
		case NEW_PIN_USER_CONFIRM_STATE:
			RDEBUG2("SecurID NEW_PIN_USER_CONFIRM_STATE: User [%s]",username);
			/* compare previous pin and current pin */
			if (!pSecurid_session->pin || strcmp(pSecurid_session->pin,passcode)) {
				RDEBUG2("Pin confirmation failed. Pins do not match [%s] and [%s]",
				       SAFE_STR(pSecurid_session->pin),
				       passcode);
				/* pins do not match */

				/* challenge the user again */
				AceGetPinParams(pSecurid_session->sdiHandle, &pinParams);
				if (pinParams.Alphanumeric) {
					strcpy(format, "alphanumeric characters");
				} else {
					strcpy(format, "digits");
				}
				snprintf(replyMsgBuffer, replyMsgBufferSize,
					 " \r\n   Pins do not match--Please try again.\r\n   Enter your new PIN of %d to %d %s,\r\n                or\r\n   <Ctrl-D> to cancel the New PIN procedure:",
					 pinParams.Min, pinParams.Max, format);

				pSecurid_session->securidSessionState = NEW_PIN_REQUIRED_STATE;

				/* insert the updated session in the session list */
				securid_sessionlist_add(inst,request,pSecurid_session);
				rc = RC_SECURID_AUTH_CHALLENGE;

			} else {
				/* pins match */
				RDEBUG2("Pin confirmation succeeded. Pins match");
				acmRet = SD_Pin(pSecurid_session->sdiHandle, (SD_CHAR*)passcode);
				if (acmRet == ACM_NEW_PIN_ACCEPTED) {
					RDEBUG("New SecurID pin accepted for %s.",pSecurid_session->identity);

					pSecurid_session->securidSessionState = NEW_PIN_AUTH_VALIDATE_STATE;

					/* insert the updated session in the session list */
					securid_sessionlist_add(inst,request,pSecurid_session);

					rc = RC_SECURID_AUTH_CHALLENGE;
					strlcpy(replyMsgBuffer," \r\n\r\nWait for the code on your card to change, then enter new PIN and TokenCode\r\n\r\nEnter PASSCODE:", replyMsgBufferSize);
				} else {
					RDEBUG("SecurID: New SecurID pin rejected for %s.",pSecurid_session->identity);
					SD_Pin(pSecurid_session->sdiHandle, (SD_CHAR*)"");  /* cancel PIN */
					

					rc = RC_SECURID_AUTH_FAILURE;

					/* deallocate session */
					securid_session_free(inst, request,
							     pSecurid_session);
				}
			}
			return rc;		  
		case NEW_PIN_AUTH_VALIDATE_STATE:
			acmRet = SD_Check(pSecurid_session->sdiHandle, (SD_CHAR*)passcode, (SD_CHAR*)username);
			if (acmRet == ACM_OK) {
				RDEBUG("New SecurID passcode accepted for %s.",
				       pSecurid_session->identity);
				rc = RC_SECURID_AUTH_SUCCESS;

			} else {
				radlog(L_INFO,"SecurID: New passcode rejected for [%s].",pSecurid_session->identity);
				rc = RC_SECURID_AUTH_FAILURE;
			}

			/* deallocate session */
			securid_session_free(inst,request,pSecurid_session);

			return rc;
		case NEW_PIN_SYSTEM_ACCEPT_STATE:
			if (!strcmp(passcode, "y")) {
				AceGetSystemPin(pSecurid_session->sdiHandle, newPin);
					
				/* Save the PIN for the next session
				 * continuation */
				if (pSecurid_session->pin) {
					free(pSecurid_session->pin);
					pSecurid_session->pin = NULL;
				}
				pSecurid_session->pin = strdup(newPin);
					
				snprintf(replyMsgBuffer, replyMsgBufferSize,
					 "\r\nYour new PIN is: %s\r\nDo you accept this [y/n]?",
					 newPin);
				pSecurid_session->securidSessionState = NEW_PIN_SYSTEM_CONFIRM_STATE;
					
				/* insert the updated session in the
				 * session list */
				securid_sessionlist_add(inst, request,
							pSecurid_session);
					
				rc = RC_SECURID_AUTH_CHALLENGE;

			} else {
				SD_Pin(pSecurid_session->sdiHandle, (SD_CHAR*)""); //Cancel new PIN
					
				/* deallocate session */
				securid_session_free(inst, request,
						     pSecurid_session);
					
				rc = RC_SECURID_AUTH_FAILURE;
			}
				
			return rc;				
			 
		case NEW_PIN_SYSTEM_CONFIRM_STATE:
			acmRet = SD_Pin(pSecurid_session->sdiHandle, (SD_CHAR*)pSecurid_session->pin);
			if (acmRet == ACM_NEW_PIN_ACCEPTED) {
				strlcpy(replyMsgBuffer," \r\n\r\nPin Accepted. Wait for the code on your card to change, then enter new PIN and TokenCode\r\n\r\nEnter PASSCODE:",replyMsgBufferSize);
				pSecurid_session->securidSessionState = NEW_PIN_AUTH_VALIDATE_STATE;
				/* insert the updated session in the session list */
				securid_sessionlist_add(inst,request,pSecurid_session);
				rc = RC_SECURID_AUTH_CHALLENGE;

			} else {
				SD_Pin(pSecurid_session->sdiHandle, (SD_CHAR*)""); //Cancel new PIN
				strlcpy(replyMsgBuffer," \r\n\r\nPin Rejected. Wait for the code on your card to change, then try again.\r\n\r\nEnter PASSCODE:",replyMsgBufferSize);
				/* deallocate session */
				securid_session_free(inst, request,
						     pSecurid_session);
				rc = RC_SECURID_AUTH_FAILURE;
			}
				
			return rc;
			 
			/* USER_SELECTABLE state should be implemented to preserve compatibility with AM 6.x servers, which can return this state */
		case NEW_PIN_USER_SELECT_STATE:
			if (!strcmp(passcode, "y")) {
				/* User has opted for a system-generated PIN */
				AceGetSystemPin(pSecurid_session->sdiHandle, newPin);
				snprintf(replyMsgBuffer, replyMsgBufferSize,
					 "\r\nYour new PIN is: %s\r\nDo you accept this [y/n]?",
					 newPin);
				pSecurid_session->securidSessionState = NEW_PIN_SYSTEM_CONFIRM_STATE;
					
				/* insert the updated session in the session list */
				securid_sessionlist_add(inst, request,
							pSecurid_session);
				rc = RC_SECURID_AUTH_CHALLENGE;

			} else {
				/* User has opted for a user-defined PIN */
				AceGetPinParams(pSecurid_session->sdiHandle,
						&pinParams);
				if (pinParams.Alphanumeric) {
					strcpy(format, "alphanumeric characters");
				} else {
					strcpy(format, "digits");
				}
					
				snprintf(replyMsgBuffer, replyMsgBufferSize,
					 " \r\n   Enter your new PIN of %d to %d %s,\r\n                or\r\n   <Ctrl-D> to cancel the New PIN procedure:",
					 pinParams.Min, pinParams.Max, format);
				pSecurid_session->securidSessionState = NEW_PIN_REQUIRED_STATE;
					
				/* insert the updated session in the session list */
				securid_sessionlist_add(inst, request,
							pSecurid_session);
				rc = RC_SECURID_AUTH_CHALLENGE;
			}
				
			return rc;
				
		default:
			radlog(L_ERR|L_CONS, "rlm_securid: Invalid session state %d for user [%s]",
			       pSecurid_session->securidSessionState,
			       username);
			break;	
		}
	}
	
	return 0;
		
}