server config UPDATE keyboard interactive
These changes include:
- PAM filename is set globally for all clients
- PAM directory not configurable (security reasons)
- Removal of the ln2 PAM module and its use in a test
- Description added to the ln2 YANG module
- Change of add_user_interactive API to only enable kbint for a
user
diff --git a/src/session_server_ssh.c b/src/session_server_ssh.c
index 3ea0b81..39b3a82 100644
--- a/src/session_server_ssh.c
+++ b/src/session_server_ssh.c
@@ -240,9 +240,7 @@
* @param[in] msg PAM module's messages.
* @param[out] resp User responses.
* @param[in] appdata_ptr Callback's data.
- * @return PAM_SUCCESS on success;
- * @return PAM_BUF_ERR on memory allocation error;
- * @return PAM_CONV_ERR otherwise.
+ * @return PAM_SUCCESS on success, PAM_BUF_ERR on memory allocation error, PAM_CONV_ERR otherwise.
*/
static int
nc_pam_conv_clb(int n_messages, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
@@ -256,10 +254,10 @@
struct nc_pam_thread_arg *clb_data = appdata_ptr;
ssh_session libssh_session;
struct timespec ts_timeout;
- struct nc_server_ssh_opts *opts;
+ uint16_t auth_timeout;
libssh_session = clb_data->session->ti.libssh.session;
- opts = clb_data->opts;
+ auth_timeout = clb_data->auth_timeout;
/* PAM_MAX_NUM_MSG == 32 by default */
if ((n_messages <= 0) || (n_messages >= PAM_MAX_NUM_MSG)) {
@@ -331,8 +329,8 @@
goto cleanup;
}
- if (opts->auth_timeout) {
- nc_timeouttime_get(&ts_timeout, opts->auth_timeout * 1000);
+ if (auth_timeout) {
+ nc_timeouttime_get(&ts_timeout, auth_timeout * 1000);
}
/* get user's replies */
@@ -349,7 +347,7 @@
}
usleep(NC_TIMEOUT_STEP);
- } while (opts->auth_timeout && (nc_timeouttime_cur_diff(&ts_timeout) >= 1));
+ } while (auth_timeout && (nc_timeouttime_cur_diff(&ts_timeout) >= 1));
if (!reply) {
ERR(NULL, "Authentication timeout.");
@@ -397,50 +395,30 @@
* @return PAM error otherwise.
*/
static int
-nc_pam_auth(struct nc_session *session, struct nc_server_ssh_opts *opts, ssh_message ssh_msg)
+nc_pam_auth(struct nc_session *session, struct nc_auth_client *client, uint16_t auth_timeout, ssh_message ssh_msg)
{
pam_handle_t *pam_h = NULL;
int ret;
struct nc_pam_thread_arg clb_data;
struct pam_conv conv;
- uint16_t i;
/* structure holding callback's data */
clb_data.msg = ssh_msg;
clb_data.session = session;
- clb_data.opts = opts;
+ clb_data.auth_timeout = auth_timeout;
/* PAM conversation structure holding the callback and it's data */
conv.conv = nc_pam_conv_clb;
conv.appdata_ptr = &clb_data;
- /* get the current client's configuration file */
- for (i = 0; i < opts->client_count; i++) {
- if (!strcmp(opts->auth_clients[i].username, session->username)) {
- break;
- }
- }
-
- if (i == opts->client_count) {
- ERR(NULL, "User \"%s\" not found.", session->username);
- ret = 1;
- goto cleanup;
- }
-
- if (!opts->auth_clients[i].pam_config_name) {
- ERR(NULL, "User's \"%s\" PAM configuration filename not set.");
+ if (!server_opts.pam_config_name) {
+ ERR(NULL, "PAM configuration filename not set.");
ret = 1;
goto cleanup;
}
/* initialize PAM and see if the given configuration file exists */
-# ifdef LIBPAM_HAVE_CONFDIR
- /* PAM version >= 1.4 */
- ret = pam_start_confdir(opts->auth_clients[i].pam_config_name, session->username, &conv, opts->auth_clients[i].pam_config_dir, &pam_h);
-# else
- /* PAM version < 1.4 */
- ret = pam_start(opts->auth_clients[i].pam_config_name, session->username, &conv, &pam_h);
-# endif
+ ret = pam_start(server_opts.pam_config_name, client->username, &conv, &pam_h);
if (ret != PAM_SUCCESS) {
ERR(NULL, "PAM error occurred (%s).\n", pam_strerror(pam_h, ret));
goto cleanup;
@@ -470,7 +448,7 @@
VRB(NULL, "PAM warning occurred (%s).\n", pam_strerror(pam_h, ret));
ret = pam_chauthtok(pam_h, PAM_CHANGE_EXPIRED_AUTHTOK);
if (ret == PAM_SUCCESS) {
- VRB(NULL, "The authentication token of user \"%s\" updated successfully.", session->username);
+ VRB(NULL, "The authentication token of user \"%s\" updated successfully.", client->username);
} else {
ERR(NULL, "PAM error occurred (%s).\n", pam_strerror(pam_h, ret));
goto cleanup;
@@ -485,10 +463,10 @@
return ret;
}
-#endif
+#endif /* HAVE_LIBPAM */
static int
-nc_sshcb_auth_kbdint(struct nc_session *session, struct nc_server_ssh_opts *opts, ssh_message msg)
+nc_sshcb_auth_kbdint(struct nc_session *session, struct nc_auth_client *client, uint16_t auth_timeout, ssh_message msg)
{
int auth_ret = 1;
@@ -496,7 +474,7 @@
auth_ret = server_opts.interactive_auth_clb(session, session->ti.libssh.session, msg, server_opts.interactive_auth_data);
} else {
#ifdef HAVE_LIBPAM
- if (nc_pam_auth(session, opts, msg) == PAM_SUCCESS) {
+ if (nc_pam_auth(session, client, auth_timeout, msg) == PAM_SUCCESS) {
auth_ret = 0;
}
#else
@@ -515,6 +493,40 @@
return auth_ret;
}
+API void
+nc_server_ssh_set_interactive_auth_clb(int (*interactive_auth_clb)(const struct nc_session *session, ssh_session ssh_sess, ssh_message msg, void *user_data),
+ void *user_data, void (*free_user_data)(void *user_data))
+{
+ server_opts.interactive_auth_clb = interactive_auth_clb;
+ server_opts.interactive_auth_data = user_data;
+ server_opts.interactive_auth_data_free = free_user_data;
+}
+
+#ifdef HAVE_LIBPAM
+
+API int
+nc_server_ssh_set_pam_conf_filename(const char *filename)
+{
+ NC_CHECK_ARG_RET(NULL, filename, 1);
+
+ free(server_opts.pam_config_name);
+ server_opts.pam_config_name = strdup(filename);
+ NC_CHECK_ERRMEM_RET(!server_opts.pam_config_name, 1);
+ return 0;
+}
+
+#else
+
+API int
+nc_server_ssh_set_pam_conf_filename(const char *filename)
+{
+ (void) filename;
+ ERR("LibPAM not found.");
+ return 1;
+}
+
+#endif /* HAVE_LIBPAM */
+
/*
* Get the public key type from binary data stored in buffer.
* The data is in the form of: 4 bytes = data length, then data of data length
@@ -654,7 +666,7 @@
static void
nc_sshcb_auth_none(struct nc_session *session, struct nc_auth_client *auth_client, ssh_message msg)
{
- if (auth_client->supports_none && !auth_client->password && !auth_client->pubkey_count && !auth_client->pam_config_name) {
+ if (auth_client->none_enabled && !auth_client->password && !auth_client->pubkey_count && !auth_client->kb_int_enabled) {
/* only authenticate the client if he supports none and no other method */
session->flags |= NC_SESSION_SSH_AUTHENTICATED;
VRB(session, "User \"%s\" authenticated.", session->username);
@@ -963,11 +975,11 @@
state->auth_method_count++;
libssh_auth_methods |= SSH_AUTH_METHOD_PASSWORD;
}
- if (auth_client->pam_config_name) {
+ if (auth_client->kb_int_enabled) {
state->auth_method_count++;
libssh_auth_methods |= SSH_AUTH_METHOD_INTERACTIVE;
}
- if (auth_client->supports_none) {
+ if (auth_client->none_enabled) {
libssh_auth_methods |= SSH_AUTH_METHOD_NONE;
}
@@ -995,7 +1007,7 @@
} else if (subtype == SSH_AUTH_METHOD_PUBLICKEY) {
ret = nc_sshcb_auth_pubkey(session, auth_client, msg);
} else if (subtype == SSH_AUTH_METHOD_INTERACTIVE) {
- ret = nc_sshcb_auth_kbdint(session, opts, msg);
+ ret = nc_sshcb_auth_kbdint(session, auth_client, opts->auth_timeout, msg);
}
if (!ret) {