/*
* Copyright 2002,2003 Christopher SEKIYA <wileyc@rezrov.net>
*/
#include "tacshell.h"
#include <time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
/* local prototypes */
u_int32_t getservername(char *serv);
int
authenticate(char *user);
/* globals */
char *user = NULL;
char *tac_secret = NULL;
int tac_encryption = 1;
char *challenge = NULL;
u_int32_t session_id;
u_int8_t sequence_number = 1;
char *servers[MAX_SERVERS];
char *server_secret = NULL;
char *user_shell = NULL;
#if defined(HAVE_GETPASSPHRASE)
# define get_pass(x) getpassphrase(x)
#elif defined(HAVE_GETPASS)
# define get_pass(x) getpass(x)
#else
# error Neither getpassphrase() nor getpass() exist on this system.
#endif
int
authenticate(char *user)
{
u_int32_t seed;
struct timeval t;
int tac_fd = -1;
int msg;
char *pass;
char *tty;
int index;
/* create session id for this transaction */
gettimeofday(&t, NULL);
seed = gethostid() ^ t.tv_sec ^ t.tv_usec ^ getpid();
srand48(seed);
session_id = mrand48();
sequence_number = 1;
tty = ttyname(0);
if (strncmp(tty, "/dev/", 5) == 0)
tty += 5;
for (index = 0; index < MAX_SERVERS; index++)
if (servers[index] != NULL)
if ( (tac_fd = tac_connect(getservername(servers[index]))) >= 0)
break;
if (tac_fd < 0) {
printf("Error connecting to TACACS+ server\n");
return -1;
}
/* start authentication */
if (tac_authen_send(tac_fd, user, tty) < 0) {
fprintf(stderr, "Error sending query to TACACS+ server\n");
return -1;
}
for (;;) {
msg = tac_authen_read(tac_fd);
switch (msg) {
case TAC_PLUS_AUTHEN_STATUS_FAIL:
if (challenge != NULL) {
fprintf(stderr, "%s", challenge);
free(challenge);
challenge = NULL;
} else
fprintf(stderr, "Authentication FAILED\n");
close(tac_fd);
return -1;
case TAC_PLUS_AUTHEN_STATUS_PASS:
if (challenge != NULL) {
fprintf(stderr, "%s\n", challenge);
free(challenge);
challenge = NULL;
} else
fprintf(stderr, "Authentication SUCCEEDED\n");
close(tac_fd);
return 0;
case TAC_PLUS_AUTHEN_STATUS_GETPASS:
case TAC_PLUS_AUTHEN_STATUS_GETDATA:
case TAC_PLUS_AUTHEN_STATUS_GETUSER:
if (challenge != NULL)
{
pass = get_pass(challenge);
free(challenge);
}
else
pass = get_pass("Enter password: ");
challenge = NULL;
tac_authen_continue_send(tac_fd, pass);
break;
case TAC_PLUS_AUTHEN_STATUS_ERROR:
fprintf(stderr, "tacshell: server returned TAC_PLUS_AUTHEN_STATUS_ERROR, exiting\n");
return -1;
case TAC_PLUS_AUTHEN_STATUS_FOLLOW:
fprintf(stderr, "tacshell: server returned TAC_PLUS_AUTHEN_STATUS_FOLLOW. Contact another server.\n");
return -1;
case TAC_PLUS_AUTHEN_STATUS_RESTART:
fprintf(stderr, "tacshell: server returned TAC_PLUS_AUTHEN_STATUS_RESTART. Not yet implemented.\n");
return -1;
default:
fprintf(stderr, "tacshell: unhandled status %x\n", msg);
return -1;
}
}
/* never actually reached, but just in case ... */
return -1;
}
u_int32_t
getservername(char *serv)
{
struct in_addr addr;
struct hostent *h;
if (inet_aton(serv, &addr) == 0) {
if ((h = gethostbyname(serv)) == NULL) {
herror("gethostbyname");
} else {
bcopy(h->h_addr, (char *) &addr, sizeof(struct in_addr));
return (addr.s_addr);
}
} else
return (addr.s_addr);
return 0;
}
void
cleanup(void)
{
int index;
if (tac_secret != NULL)
free(tac_secret);
if (challenge != NULL)
free(challenge);
if (user != NULL)
free(user);
for (index = 0; index < MAX_SERVERS; index++)
if (servers[index] != NULL)
free(servers[index]);
if (server_secret != NULL)
free(server_secret);
if (user_shell != NULL)
free(user_shell);
return;
}
syntax highlighted by Code2HTML, v. 0.9.1