27 #define "rlm_securid - "
29 #include <freeradius-devel/server/base.h>
30 #include <freeradius-devel/server/module_rlm.h>
36 RC_SECURID_AUTH_SUCCESS = 0,
37 RC_SECURID_AUTH_FAILURE = -3,
38 RC_SECURID_AUTH_ACCESS_DENIED_FAILURE = -4,
39 RC_SECURID_AUTH_INVALID_SERVER_FAILURE = -5,
40 RC_SECURID_AUTH_CHALLENGE = -17
76 static SD_CHAR empty_pin[] =
"";
79 static int securid_session_cmp(
void const *a,
void const *b)
89 if (ret != 0)
return ret;
95 static SECURID_AUTH_RC securidAuth(
void *instance,
request_t *request,
98 char *replyMsgBuffer,
size_t replyMsgBufferSize)
108 SD_CHAR *securid_user, *securid_pass;
111 ERROR(
"SecurID username is NULL");
112 return RC_SECURID_AUTH_FAILURE;
117 return RC_SECURID_AUTH_FAILURE;
120 memcpy(&securid_user, &
username,
sizeof(securid_user));
121 memcpy(&securid_pass, &passcode,
sizeof(securid_pass));
123 *replyMsgBuffer =
'\0';
126 if (!securid_session) {
128 SDI_HANDLE sdiHandle = SDI_HANDLE_NONE;
130 acm_ret = SD_Init(&sdiHandle);
131 if (acm_ret != ACM_OK) {
132 RERROR(
"Cannot communicate with the ACE/Server");
136 acm_ret = SD_Lock(sdiHandle, securid_user);
137 if (acm_ret != ACM_OK) {
142 acm_ret = SD_Check(sdiHandle, securid_pass, securid_user);
149 return RC_SECURID_AUTH_SUCCESS;
151 case ACM_ACCESS_DENIED:
155 return RC_SECURID_AUTH_ACCESS_DENIED_FAILURE;
157 case ACM_INVALID_SERVER:
158 RERROR(
"SecurID: Invalid ACE server");
159 return RC_SECURID_AUTH_INVALID_SERVER_FAILURE;
161 case ACM_NEW_PIN_REQUIRED:
171 acm_ret = AceGetPinParams(sdiHandle, &pin_params);
174 if (pin_params.Selectable == CANNOT_CHOOSE_PIN) {
176 snprintf(replyMsgBuffer, replyMsgBufferSize,
177 "\r\nAre you prepared to accept a new system-generated PIN [y/n]?");
180 }
else if (pin_params.Selectable == USER_SELECTABLE) {
181 snprintf(replyMsgBuffer, replyMsgBufferSize,
182 "\r\nPress 'y' to generate a new PIN\r\nOR\r\n'n'to enter a new PIN yourself [y/n]");
186 if (pin_params.Alphanumeric) {
191 snprintf(replyMsgBuffer, replyMsgBufferSize,
192 " \r\n Enter your new PIN of %d to %d %s, \r\n or\r\n <Ctrl-D> to cancel the New PIN procedure:",
193 pin_params.Min, pin_params.Max,
format);
199 return RC_SECURID_AUTH_CHALLENGE;
201 case ACM_NEXT_CODE_REQUIRED:
202 RDEBUG2(
"Next securid token code required for %s",
214 strlcpy(replyMsgBuffer,
"\r\nPlease Enter the Next Code from Your Token:", replyMsgBufferSize);
215 return RC_SECURID_AUTH_CHALLENGE;
218 ERROR(
"SecurID: Unexpected error from ACE/Agent API acm_ret=%d", acm_ret);
220 return RC_SECURID_AUTH_FAILURE;
234 acm_ret = SD_Next(securid_session->
sdiHandle, securid_pass);
235 if (acm_ret == ACM_OK) {
236 INFO(
"Next SecurID token accepted for [%s].", securid_session->
identity);
237 rc = RC_SECURID_AUTH_SUCCESS;
240 INFO(
"SecurID: Next token rejected for [%s].", securid_session->
identity);
241 rc = RC_SECURID_AUTH_FAILURE;
249 RDEBUG2(
"SecurID NEW_PIN_REQUIRED_STATE for %s",
253 if (securid_session->
pin) TALLOC_FREE(securid_session->
pin);
256 strlcpy(replyMsgBuffer,
"\r\n Please re-enter new PIN:", replyMsgBufferSize);
263 return RC_SECURID_AUTH_CHALLENGE;
268 if (!securid_session->
pin || strcmp(securid_session->
pin, passcode)) {
269 RDEBUG2(
"Pin confirmation failed. Pins do not match [%s] and [%s]",
274 AceGetPinParams(securid_session->
sdiHandle, &pin_params);
275 if (pin_params.Alphanumeric) {
280 snprintf(replyMsgBuffer, replyMsgBufferSize,
281 " \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:",
282 pin_params.Min, pin_params.Max,
format);
288 rc = RC_SECURID_AUTH_CHALLENGE;
292 RDEBUG2(
"Pin confirmation succeeded. Pins match");
293 acm_ret = SD_Pin(securid_session->
sdiHandle, securid_pass);
294 if (acm_ret == ACM_NEW_PIN_ACCEPTED) {
295 RDEBUG2(
"New SecurID pin accepted for %s.", securid_session->
identity);
302 rc = RC_SECURID_AUTH_CHALLENGE;
303 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);
305 RDEBUG2(
"SecurID: New SecurID pin rejected for %s.", securid_session->
identity);
306 SD_Pin(securid_session->
sdiHandle, &empty_pin[0]);
309 rc = RC_SECURID_AUTH_FAILURE;
317 acm_ret = SD_Check(securid_session->
sdiHandle, securid_pass, securid_user);
318 if (acm_ret == ACM_OK) {
319 RDEBUG2(
"New SecurID passcode accepted for %s", securid_session->
identity);
320 rc = RC_SECURID_AUTH_SUCCESS;
323 INFO(
"SecurID: New passcode rejected for [%s]", securid_session->
identity);
324 rc = RC_SECURID_AUTH_FAILURE;
332 if (!strcmp(passcode,
"y")) {
333 AceGetSystemPin(securid_session->
sdiHandle, new_pin);
337 if (securid_session->
pin) TALLOC_FREE(securid_session->
pin);
340 snprintf(replyMsgBuffer, replyMsgBufferSize,
341 "\r\nYour new PIN is: %s\r\nDo you accept this [y/n]?",
349 rc = RC_SECURID_AUTH_CHALLENGE;
352 SD_Pin(securid_session->
sdiHandle, &empty_pin[0]);
356 rc = RC_SECURID_AUTH_FAILURE;
362 acm_ret = SD_Pin(securid_session->
sdiHandle, (SD_CHAR*)securid_session->
pin);
363 if (acm_ret == ACM_NEW_PIN_ACCEPTED) {
364 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);
368 rc = RC_SECURID_AUTH_CHALLENGE;
371 SD_Pin(securid_session->
sdiHandle, &empty_pin[0]);
372 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);
375 rc = RC_SECURID_AUTH_FAILURE;
382 if (!strcmp(passcode,
"y")) {
384 AceGetSystemPin(securid_session->
sdiHandle, new_pin);
385 snprintf(replyMsgBuffer, replyMsgBufferSize,
386 "\r\nYour new PIN is: %s\r\nDo you accept this [y/n]?",
393 rc = RC_SECURID_AUTH_CHALLENGE;
397 AceGetPinParams(securid_session->
sdiHandle,
399 if (pin_params.Alphanumeric) {
405 snprintf(replyMsgBuffer, replyMsgBufferSize,
406 " \r\n Enter your new PIN of %d to %d %s, \r\n or\r\n <Ctrl-D> to cancel the New PIN procedure:",
407 pin_params.Min, pin_params.Max,
format);
413 rc = RC_SECURID_AUTH_CHALLENGE;
435 if (
inst->session_tree) {
437 inst->session_tree = NULL;
440 pthread_mutex_destroy(&(
inst->session_mutex));
455 if (!
inst->session_tree) {
456 ERROR(
"Cannot initialize session tree");
460 pthread_mutex_init(&(
inst->session_mutex), NULL);
484 REDEBUG(
"Attribute \"User-Name\" is required for authentication");
489 REDEBUG(
"Attribute \"User-Password\" is required for authentication");
496 if (password->vp_length == 0) {
497 REDEBUG(
"Password should not be empty");
502 RDEBUG3(
"Login attempt with password \"%pV\"", &password->data);
504 RDEBUG2(
"Login attempt with password");
507 rcode = securidAuth(
inst, request,
username->vp_strvalue, password->vp_strvalue,
511 case RC_SECURID_AUTH_SUCCESS:
515 case RC_SECURID_AUTH_CHALLENGE:
524 RDEBUG2(
"Sending Access-Challenge");
528 case RC_SECURID_AUTH_FAILURE:
529 case RC_SECURID_AUTH_ACCESS_DENIED_FAILURE:
530 case RC_SECURID_AUTH_INVALID_SERVER_FAILURE:
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
static int const char char buffer[256]
strcpy(log_entry->msg, buffer)
#define CONF_PARSER_TERMINATOR
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Defines a CONF_PAIR to C data type mapping.
@ FR_RADIUS_CODE_ACCESS_CHALLENGE
RFC2865 - Access-Challenge.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
void *_CONST data
Module instance's parsed configuration.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
dl_module_inst_t const * inst
HIDDEN fr_dict_attr_t const * attr_reply_message
int8_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
HIDDEN fr_dict_attr_t const * attr_state
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_OCTETS
Raw octets.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for instantiation calls.
Specifies a module method identifier.
int securid_sessionlist_add(rlm_securid_t *inst, request_t *request, SECURID_SESSION *session)
SECURID_SESSION * securid_session_alloc(void)
void securid_session_free(UNUSED rlm_securid_t *inst, request_t *request, SECURID_SESSION *session)
SECURID_SESSION * securid_sessionlist_find(rlm_securid_t *inst, request_t *request)
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
static const conf_parser_t config[]
static fr_dict_attr_t const * attr_user_password
static fr_dict_t const * dict_radius
static fr_dict_attr_t const * attr_user_name
static const conf_parser_t module_config[]
#define fr_rb_inline_talloc_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black that verifies elements are of a specific talloc type.
#define RETURN_MODULE_RCODE(_rcode)
#define RETURN_MODULE_INVALID
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_REJECT
Immediately reject the request.
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
static int instantiate(module_inst_ctx_t const *mctx)
static unlang_action_t mod_authenticate(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static int mod_detach(module_detach_ctx_t *mctx)
static int mod_instantiate(module_inst_ctx_t const *mctx)
SECURID_SESSION_STATE securidSessionState
@ NEW_PIN_SYSTEM_CONFIRM_STATE
@ NEW_PIN_USER_SELECT_STATE
@ NEW_PIN_AUTH_VALIDATE_STATE
@ NEW_PIN_SYSTEM_ACCEPT_STATE
@ NEXT_CODE_REQUIRED_STATE
@ NEW_PIN_USER_CONFIRM_STATE
HIDDEN fr_dict_attr_t const * attr_prompt
char state[SECURID_STATE_LEN]
#define MODULE_NAME_TERMINATOR
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
size_t strlcpy(char *dst, char const *src, size_t siz)
Stores an attribute, a value and various bits of other data.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
#define talloc_get_type_abort_const
#define FR_MAX_STRING_LEN
int format(printf, 5, 0))