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.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
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.
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Module instance to detach.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for detach calls.
Temporary structure to hold arguments for instantiation calls.
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 SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
void * data
Module's instance data.
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Named methods exported by a module.
#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))