Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/vty_auth.c b/vty_auth.c
index a81327cf..6535f88d 100644
--- a/vty_auth.c
+++ b/vty_auth.c
@@ -1,273 +1,279 @@
#include "config.h"
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <grp.h>
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include "utils.h"
#include "vty_auth.h"
#include "vty_utils.h"
static int knet_pam_misc_conv(int num_msg, const struct pam_message **msgm,
struct pam_response **response, void *appdata_ptr)
{
int count = 0;
struct pam_response *reply;
struct knet_vty *vty = (struct knet_vty *)appdata_ptr;
if (num_msg <= 0)
return PAM_CONV_ERR;
reply = (struct pam_response *) calloc(num_msg, sizeof(struct pam_response));
if (reply == NULL)
return PAM_CONV_ERR;
for (count=0; count < num_msg; ++count) {
unsigned char readbuf[VTY_MAX_BUFFER_SIZE];
char *string=NULL;
int nc;
memset(readbuf, 0, sizeof(readbuf));
switch (msgm[count]->msg_style) {
case PAM_PROMPT_ECHO_OFF:
if (knet_vty_set_echo(vty, 0) < 0) {
knet_vty_write(vty, "Unable to turn off terminal/telnet echo");
goto failed_conversation;
}
knet_vty_write(vty, "%s", msgm[count]->msg);
nc = knet_vty_read(vty, readbuf, sizeof(readbuf));
if (nc < 0)
goto failed_conversation;
if (knet_vty_set_echo(vty, 1) < 0) {
/* doesn't really make a lot of sense tho.... */
knet_vty_write(vty, "Unable to turn on terminal/telnet echo");
goto failed_conversation;
}
knet_vty_write(vty, "\n");
readbuf[nc-2] = 0;
string = strdup((const char*)readbuf);
if (!string)
goto failed_conversation;
break;
case PAM_PROMPT_ECHO_ON:
knet_vty_write(vty, "\n%s", msgm[count]->msg);
nc = knet_vty_read(vty, readbuf, sizeof(readbuf));
if (nc < 0)
goto failed_conversation;
readbuf[nc-2] = 0;
string = strdup((const char*)readbuf);
if (!string)
goto failed_conversation;
break;
case PAM_ERROR_MSG:
log_error("Received PAM error message %s", msgm[count]->msg);
knet_vty_write(vty, "%s", msgm[count]->msg);
break;
case PAM_TEXT_INFO:
log_error("Received PAM text info: %s", msgm[count]->msg);
knet_vty_write(vty, "%s", msgm[count]->msg);
break;
default:
log_error("Unknown PAM conversation message");
knet_vty_write(vty, "Unknown PAM conversation message");
goto failed_conversation;
}
if (string) {
reply[count].resp_retcode = 0;
reply[count].resp = string;
string = NULL;
}
}
*response = reply;
reply = NULL;
return PAM_SUCCESS;
failed_conversation:
log_error("PAM conversation error");
knet_vty_write(vty, "PAM conversation error");
if (reply) {
for (count=0; count < num_msg; ++count) {
if (reply[count].resp == NULL)
continue;
switch (msgm[count]->msg_style) {
case PAM_PROMPT_ECHO_ON:
case PAM_PROMPT_ECHO_OFF:
_pam_overwrite(reply[count].resp);
free(reply[count].resp);
break;
case PAM_BINARY_PROMPT:
{
void *bt_ptr = reply[count].resp;
pam_binary_handler_free(appdata_ptr, bt_ptr);
break;
}
case PAM_ERROR_MSG:
case PAM_TEXT_INFO:
free(reply[count].resp);
}
}
free(reply);
reply = NULL;
}
return PAM_CONV_ERR;
}
static int knet_vty_get_pam_user(struct knet_vty *vty, pam_handle_t *pamh)
{
const void *value;
int err;
memset(vty->username, 0, sizeof(vty->username));
err = pam_get_item(pamh, PAM_USER, &value);
if (err != PAM_SUCCESS)
return err;
strncpy(vty->username, (const char*)value, 32);
return 0;
}
static int knet_vty_pam_auth_user(struct knet_vty *vty, const char *user)
{
pam_handle_t *pamh=NULL;
struct pam_conv conv;
int err;
int retry = 1;
conv.conv = knet_pam_misc_conv;
conv.appdata_ptr = (void *)vty;
retry_auth:
err = pam_start("kronosnet", user, &conv, &pamh);
if (err != PAM_SUCCESS) {
+ errno = EINVAL;
log_error("PAM fatal error: %s", pam_strerror(pamh, err));
knet_vty_write(vty, "PAM fatal error: %s",
pam_strerror(pamh, err));
goto out_fatal;
}
err = pam_authenticate(pamh, 0);
- if (err != PAM_SUCCESS)
- goto out_clean;
+ if (err != PAM_SUCCESS) {
+ errno = EINVAL;
+ log_error("PAM fatal error: %s", pam_strerror(pamh, err));
+ knet_vty_write(vty, "PAM fatal error: %s",
+ pam_strerror(pamh, err));
+ goto out_fatal;
+ }
if (knet_vty_get_pam_user(vty, pamh) != PAM_SUCCESS) {
log_error("PAM: unable to get PAM_USER: %s",
pam_strerror(pamh, err));
knet_vty_write(vty, "PAM: unable to get PAM_USER: %s",
pam_strerror(pamh, err));
goto out_clean;
}
err = pam_acct_mgmt(pamh, 0);
if (err != PAM_SUCCESS) {
log_info("User: %s failed to authenticate on vty(%d) attempt %d",
vty->username, vty->conn_num, retry);
goto out_clean;
}
out_clean:
if (pamh) {
pam_end(pamh, err);
pamh = NULL;
}
if ((err != PAM_SUCCESS) && (retry < AUTH_MAX_RETRY)) {
retry++;
goto retry_auth;
}
out_fatal:
knet_vty_write(vty, "\n");
return err;
}
static int knet_vty_group_check(struct knet_vty *vty)
{
struct group grp;
char *buf;
size_t buflen;
long int initlen;
struct group *result;
char *gr_mem;
int err, i;
errno = 0;
initlen = sysconf(_SC_GETGR_R_SIZE_MAX);
if ((initlen < 0) && (errno == EINVAL))
return -1;
if (initlen < 0)
initlen = 1024;
buflen = (size_t) initlen;
buf = malloc(buflen);
if (!buf)
return -1;
while ((err = getgrnam_r(DEFAULTADMGROUP, &grp, buf, buflen, &result)) == ERANGE) {
size_t newlen = 2 * buflen;
char *newbuf;
newbuf = realloc(buf, newlen);
if (!newbuf) {
err = -1;
goto out_clean;
}
buf = newbuf;
}
if (err)
goto out_clean;
if (result == NULL) {
errno = EACCES;
log_error("No " DEFAULTADMGROUP " group found on the system");
knet_vty_write(vty, "No " DEFAULTADMGROUP " group found on the system\n");
err = -1;
goto out_clean;
}
gr_mem = *grp.gr_mem;
i = 1;
while(gr_mem != NULL) {
if (!strcmp(vty->username, gr_mem)) {
vty->user_can_enable = 1;
break;
}
gr_mem = *(grp.gr_mem + i);
i++;
}
out_clean:
free(buf);
return err;
}
int knet_vty_auth_user(struct knet_vty *vty, const char *user)
{
int err;
err = knet_vty_pam_auth_user(vty, user);
if (err != PAM_SUCCESS)
return -1;
return knet_vty_group_check(vty);
}

File Metadata

Mime Type
text/x-diff
Expires
Wed, Jun 25, 5:01 AM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1952221
Default Alt Text
(6 KB)

Event Timeline