4 * TACACS_PLUS daemon suitable for using on Un*x systems.
6 * October 1994, Lol Grant
8 * Copyright (c) 1994-1998 by Cisco systems, Inc.
9 * Permission to use, copy, modify, and distribute this software for
10 * any purpose and without fee is hereby granted, provided that this
11 * copyright and permission notice appear on all copies of the
12 * software and supporting documentation, the name of Cisco Systems,
13 * Inc. not be used in advertising or publicity pertaining to
14 * distribution of the program without specific prior permission, and
15 * notice be given in supporting documentation that modification,
16 * copying and distribution is by permission of Cisco Systems, Inc.
18 * Cisco Systems, Inc. makes no representations about the suitability
19 * of this software for any purpose. THIS SOFTWARE IS PROVIDED ``AS
20 * IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
21 * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22 * FITNESS FOR A PARTICULAR PURPOSE.
29 static int standalone = 1; /* running standalone (1) or under inetd (0) */
30 static int initialised = 0; /* data structures have been allocated */
31 int sendauth_only = 0; /* don't respond to sendpass requests */
32 int debug = 0; /* debugging flags */
33 int port = 0; /* port we're listening on */
34 int console = 0; /* write all syslog messages to console */
35 int parse_only = 0; /* exit after verbose parsing */
36 int single = 0; /* single thread (for debugging) */
37 int wtmpfd = 0; /* for wtmp file logging */
38 char *wtmpfile = NULL;
40 struct timeval started_at;
42 struct session session; /* session data */
44 static char pidfilebuf[75]; /* holds current name of the pidfile */
65 pid = wait3(&status, WNOHANG, 0);
68 if (debug & DEBUG_FORK_FLAG)
69 report(LOG_DEBUG, "%d reaped", pid);
72 #endif /* REAPCHILD */
78 report(LOG_INFO, "Received signal %d, shutting down", signum);
89 report(LOG_INFO, "Reading config");
91 session.acctfile = tac_strdup("/var/log/acctfile");
93 if (!session.cfgfile) {
94 report(LOG_ERR, "no config file specified");
98 /* read the config file */
99 if (cfg_read_config(session.cfgfile)) {
100 report(LOG_ERR, "Parsing %s", session.cfgfile);
101 fprintf(stderr,"Config file not found!!\n");
107 report(LOG_INFO, "Version %s Initialized %d", VERSION, initialised);
115 report(LOG_INFO, "Received signal %d", signum);
118 signal(SIGUSR1, handler);
119 signal(SIGHUP, handler);
124 * Return a socket bound to an appropriate port number/address. Exits
125 * the program on failure */
130 struct sockaddr_in sin;
134 bzero((char *) &sin, sizeof(sin));
137 sin.sin_port = htons(port);
139 sp = getservbyname("tacacs", "tcp");
141 sin.sin_port = sp->s_port;
143 report(LOG_ERR, "Cannot find socket port");
148 sin.sin_family = AF_INET;
149 sin.sin_addr.s_addr = htonl(INADDR_ANY);
151 s = socket(AF_INET, SOCK_STREAM, 0);
155 report(LOG_ERR, "get_socket: socket: %s", sys_errlist[errno]);
159 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
161 perror("setsockopt - SO_REUSEADDR");
162 #endif /* SO_REUSEADDR */
164 if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
166 report(LOG_ERR, "get_socket: bind %d %s",
178 openlog("tac_plus", LOG_PID, LOG_LOCAL6);
180 openlog("tac_plus", LOG_PID);
182 setlogmask(LOG_UPTO(LOG_DEBUG));
188 * We will eventually be called from inetd or via the rc scripts directly
189 * Parse arguments and act appropiately.
203 debug = 0; /* no debugging */
204 standalone = 1; /* standalone */
205 single = 0; /* single threaded */
207 /* initialise global session data */
208 bzero(&session, sizeof(session));
209 session.peer = tac_strdup("unknown");
214 port = TAC_PLUS_PORT;
218 fprintf(stderr, "Usage: tac_plus -C <configuration file>\n");
219 fprintf(stderr, "\t[ -t ] [ -P ] [ -g ] [ -p <port> ]\n");
220 fprintf(stderr, "\t[ -d <debug level> ] [ -i ] [ -v ] [ -s ]\n");
221 fprintf(stderr, "\t[ -l logfile ]");
223 fprintf(stderr, " [ -w whologfile ]");
225 fprintf(stderr, "\n");
229 while ((c = getopt(argc, argv, "td:C:ip:PgvsLl:w:u:")) != EOF)
231 case 'L': /* lookup peer names via DNS */
234 case 's': /* don't respond to sendpass */
237 case 'v': /* print version and exit */
241 console++; /* log to console too */
243 case 'P': /* Parse config file only */
246 case 'g': /* single threaded */
252 case 'd': /* debug */
253 debug = atoi(optarg);
255 case 'C': /* config file name */
256 session.cfgfile = tac_strdup(optarg);
258 case 'i': /* stand-alone */
261 case 'l': /* logfile */
262 logfile = tac_strdup(optarg);
265 case 'w': /* wholog file */
266 wholog = tac_strdup(optarg);
270 wtmpfile = tac_strdup(optarg);
274 fprintf(stderr, "%s: bad switch %c\n", argv[0], c);
278 if (geteuid() != 0) {
279 fprintf(stderr, "Warning, not running as uid 0\n");
280 fprintf(stderr, "Tac_plus is usually run as root\n");
287 signal(SIGUSR1, handler);
288 signal(SIGHUP, handler);
289 signal(SIGTERM, die);
290 signal(SIGPIPE, SIG_IGN);
296 report(LOG_DEBUG, "tac_plus server %s starting", VERSION);
299 /* running under inetd */
300 struct sockaddr_in name;
304 name_len = sizeof(name);
307 if (getpeername(session.sock, (struct sockaddr *) &name, &name_len)) {
308 report(LOG_ERR, "getpeername failure %s", sys_errlist[errno]);
311 hp = gethostbyaddr((char *) &name.sin_addr.s_addr,
312 sizeof(name.sin_addr.s_addr), AF_INET);
316 session.peer = tac_strdup(hp ? hp->h_name :
317 (char *) inet_ntoa(name.sin_addr));
320 if (ioctl(session.sock, FIONBIO, &on) < 0) {
321 report(LOG_ERR, "ioctl(FIONBIO) %s", sys_errlist[errno]);
330 /* Running standalone. Background ourselves, let go of controlling tty */
333 signal(SIGTTOU, SIG_IGN);
336 signal(SIGTTIN, SIG_IGN);
339 signal(SIGTSTP, SIG_IGN);
342 signal(SIGHUP, SIG_IGN);
344 if ((childpid = fork()) < 0)
345 report(LOG_ERR, "Can't fork first child");
346 else if (childpid > 0)
347 exit(0); /* parent */
350 report(LOG_DEBUG, "Backgrounded");
357 if (setpgrp(0, getpid()) == -1)
359 report(LOG_ERR, "Can't change process group");
361 c = open("/dev/tty", O_RDWR);
363 ioctl(c, TIOCNOTTY, (char *) 0);
366 signal(SIGCHLD, reapchild);
368 #else /* REAPCHILD */
371 report(LOG_ERR, "Can't change process group");
373 signal(SIGHUP, SIG_IGN);
375 if ((childpid = fork()) < 0)
376 report(LOG_ERR, "Can't fork second child");
377 else if (childpid > 0)
380 if (debug & DEBUG_FORK_FLAG)
381 report(LOG_DEBUG, "Forked grandchild");
383 signal(SIGCHLD, SIG_IGN);
385 #endif /* REAPCHILD */
387 closelog(); /* some systems require this */
389 for (c = 0; c < getdtablesize(); c++)
392 /* make sure we can still log to syslog now we've closed everything */
395 } /* ! single threaded */
406 #define SOMAXCONN 128
410 #endif /* SOMAXCONN */
412 if (listen(s, SOMAXCONN) < 0) {
414 report(LOG_ERR, "listen: %s", sys_errlist[errno]);
418 if (port == TAC_PLUS_PORT) {
419 strcpy(pidfilebuf, TACPLUS_PIDFILE);
421 sprintf(pidfilebuf, "%s.%d", TACPLUS_PIDFILE, port);
424 /* write process id to pidfile */
425 if ((fp = fopen(pidfilebuf, "w")) != NULL) {
426 fprintf(fp, "%d\n", getpid());
429 report(LOG_ERR, "Cannot write pid to %s %s",
430 pidfilebuf, sys_errlist[errno]);
432 #ifdef TACPLUS_GROUPID
433 if (setgid(TACPLUS_GROUPID))
434 report(LOG_ERR, "Cannot set group id to %d %s",
435 TACPLUS_GROUPID, sys_errlist[errno]);
438 #ifdef TACPLUS_USERID
439 if (setuid(TACPLUS_USERID))
440 report(LOG_ERR, "Cannot set user id to %d %s",
441 TACPLUS_USERID, sys_errlist[errno]);
448 report(LOG_DEBUG, "uid=%d euid=%d gid=%d egid=%d s=%d",
449 getuid(), geteuid(), getgid(), getegid(), s);
453 struct sockaddr_in from;
456 struct hostent *hp = NULL;
458 bzero((char *) &from, sizeof(from));
459 from_len = sizeof(from);
461 newsockfd = accept(s, (struct sockaddr *) &from, &from_len);
467 report(LOG_ERR, "accept: %s", sys_errlist[errno]);
472 hp = gethostbyaddr((char *) &from.sin_addr.s_addr,
473 sizeof(from.sin_addr.s_addr), AF_INET);
479 session.peer = tac_strdup(hp ? hp->h_name :
480 (char *) inet_ntoa(from.sin_addr));
482 if (debug & DEBUG_PACKET_FLAG)
483 report(LOG_DEBUG, "session request from %s sock=%d",
484 session.peer, newsockfd);
490 report(LOG_ERR, "fork error");
501 session.sock = newsockfd;
503 shutdown(session.sock, 2);
508 if (debug & DEBUG_FORK_FLAG)
509 report(LOG_DEBUG, "forked %d", pid);
522 #endif /* GETDTABLESIZE */
524 /* Make sure version number is kosher. Return 0 if it is */
526 bad_version_check(pak)
529 HDR *hdr = (HDR *) pak;
532 case TAC_PLUS_AUTHEN:
534 * Let authen routines take care of more sophisticated version
535 * checking as its now a bit involved.
539 case TAC_PLUS_AUTHOR:
541 if (hdr->version != TAC_PLUS_VER_0) {
542 send_error_reply(hdr->type, "Illegal packet version");
553 * Determine the packet type, read the rest of the packet data,
554 * decrypt it and call the appropriate service routine.
561 u_char *pak, *read_packet();
574 if (debug & DEBUG_PACKET_FLAG) {
575 report(LOG_DEBUG, "validation request from %s", session.peer);
580 session.session_id = ntohl(hdr->session_id);
582 /* Do some version checking */
583 if (bad_version_check(pak)) {
589 case TAC_PLUS_AUTHEN:
594 case TAC_PLUS_AUTHOR:
604 /* Note: can't send error reply if type is unknown */
605 report(LOG_ERR, "Illegal type %d in received packet", hdr->type);
613 fprintf(stdout, "tac_plus version %s\n", VERSION);
615 fprintf(stdout,"AIX\n");
618 fprintf(stdout,"ARAP_DES\n");
621 fprintf(stdout,"BSDI\n");
623 #ifdef CONST_SYSERRLIST
624 fprintf(stdout,"CONST_SYSERRLIST\n");
627 fprintf(stdout,"DEBUG\n");
630 fprintf(stdout,"DES_DEBUG\n");
633 fprintf(stdout,"FIONBIO\n");
636 fprintf(stdout,"FREEBSD\n");
639 fprintf(stdout,"GETDTABLESIZE\n");
642 fprintf(stdout,"HPUX\n");
645 fprintf(stdout,"LINUX\n");
648 fprintf(stdout,"LITTLE_ENDIAN\n");
651 fprintf(stdout,"LOG_LOCAL6\n");
654 fprintf(stdout,"MAXSESS\n");
657 fprintf(stdout,"MIPS\n");
660 fprintf(stdout,"NEED_BZERO\n");
663 fprintf(stdout,"NETBSD\n");
666 fprintf(stdout,"NO_PWAGE\n");
669 fprintf(stdout,"REAPCHILD\n");
672 fprintf(stdout,"REARMSIGNAL\n");
674 #ifdef SHADOW_PASSWORDS
675 fprintf(stdout,"SHADOW_PASSWORDS\n");
678 fprintf(stdout,"SIGTSTP\n");
681 fprintf(stdout,"SIGTTIN\n");
684 fprintf(stdout,"SIGTTOU\n");
687 fprintf(stdout,"SKEY\n");
690 fprintf(stdout,"SOLARIS\n");
693 fprintf(stdout,"SO_REUSEADDR\n");
696 fprintf(stdout,"STDLIB_MALLOC\n");
699 fprintf(stdout,"STRCSPN\n");
702 fprintf(stdout,"SYSLOG_IN_SYS\n");
705 fprintf(stdout,"SYSV\n");
707 #ifdef TACPLUS_GROUPID
708 fprintf(stdout,"TACPLUS_GROUPID\n");
711 fprintf(stdout,"TAC_PLUS_PORT\n");
713 #ifdef TACPLUS_USERID
714 fprintf(stdout,"TACPLUS_USERID\n");
717 fprintf(stdout,"TRACE\n");
720 fprintf(stdout,"UNIONWAIT\n");
723 fprintf(stdout,"VOIDSIG\n");
726 fprintf(stdout,"_BSD1\n");
729 fprintf(stdout,"_BSD_INCLUDES\n");
732 fprintf(stdout,"__STDC__\n");