/* * Copyright 2002,2003 Christopher SEKIYA */ #include "tacshell.h" #include #include #include #include #include /* 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; }